1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
#include <hardware/clocks.h>
#include <hardware/gpio.h>
#include <hardware/timer.h>
#include <pico/multicore.h>
#include "6502.h"
#include "6522.h"
#include "drive.h"
const uint32_t GPIO_CLK = 2;
const uint32_t GPIO_DATA = 3;
const uint32_t GPIO_DATA2 = 5;
const uint32_t GPIO_ATN = 4;
const uint32_t GPIO_LED = 25;
const uint8_t DEVICE = 8;
static uint8_t ram[2048];
extern uint8_t _binary__Users_max_Documents_c64_roms_dos1541_start[16384];
// extern uint8_t _binary__Users_max_Downloads_blackbird_1_2_Blackbird_1_2_d64_start[174848];
extern uint8_t _binary__Users_max_Downloads_Bloodsuckers_StillRising_BSK_StillRising_disk1_d64_start[174848];
uint32_t ts;
cpu_t cpu;
static via_t via1;
static via_t via2;
drive_t drive;
int8_t track_step;
void via_pa_read(via_t *via, uint8_t cycle) {
if (via == &via2) {
via->ira = drive.latched[(drive.current_idx + cycle) & (DRIVE_LOOKAHEAD - 1)];
} else {
via->ira = via->ora;
}
}
void via_pb_read(via_t *via, uint8_t cycle) {
if (via == &via1) {
while (ts + cycle > time_us_32()) {}
uint8_t clk = gpio_get(GPIO_CLK) ? 0 : 0b00000100;
uint8_t data = gpio_get(GPIO_DATA) ? 0 : 0b00000001;
uint8_t atn = gpio_get(GPIO_ATN) ? 0 : 0b10000000;
uint8_t dev = (DEVICE - 8) << 5;
uint8_t atna = via->orb & 0b00010000;
via->irb = clk | data | atn | dev | atna;
} else {
uint8_t low = via->orb & 0b00001111;
uint8_t sync = drive.sync[(drive.current_idx + cycle) & (DRIVE_LOOKAHEAD - 1)] ? 0 : 0b10000000;
via->irb = low | sync | 0b00010000;
}
}
void via_pa_write(via_t *via, uint8_t cycle) {
}
void via_pb_write(via_t *via, uint8_t cycle) {
if (via == &via1) {
while (ts + cycle > time_us_32()) {}
gpio_set_dir(GPIO_CLK, (via->orb & 0b00001000) > 0 && (via->ddrb & 0b00001000) > 0);
gpio_set_dir(GPIO_DATA, (via->orb & 0b00000010) > 0 && (via->ddrb & 0b00000010) > 0);
if ((via->orb & 0b00010000) && (via->ddrb & 0b00010000)) {
gpio_set_dir(GPIO_DATA2, gpio_get(GPIO_ATN));
} else {
gpio_set_dir(GPIO_DATA2, !gpio_get(GPIO_ATN));
}
} else if (via == &via2) {
if ((via->ddrb & 3) == 3) {
int8_t step = via->orb & 3;
int8_t r = (step - track_step) % 4;
uint8_t mod = r < 0 ? r + 4 : r;
if (mod == 1) {
drive_step_up(&drive);
} else if (mod == 3) {
drive_step_down(&drive);
}
track_step = step;
}
drive.spinning = ((via->ddrb & via->orb) & 4) > 0;
gpio_put(GPIO_LED, (via->orb & 0b00001000) > 0 && (via->ddrb & 0b00001000) > 0);
}
}
uint8_t bus_read(uint16_t addr, uint8_t cycle) {
if (addr < 2048) {
return ram[addr];
} else if (addr >= 0xc000) {
return _binary__Users_max_Documents_c64_roms_dos1541_start[addr - 0xc000];
} else if (addr >= 0x1800 && addr < 0x1810) {
uint8_t v = 0;
via_read(&via1, addr - 0x1800, &v, cycle);
return v;
} else if (addr >= 0x1c00 && addr < 0x1c10) {
uint8_t v = 0;
via_read(&via2, addr - 0x1c00, &v, cycle);
return v;
} else {
return 0;
}
}
void bus_write(uint16_t addr, uint8_t v, uint8_t cycle) {
if (addr < 2048) {
ram[addr] = v;
} else if (addr >= 0x1800 && addr < 0x1810) {
via_write(&via1, addr - 0x1800, v, cycle);
} else if (addr >= 0x1c00 && addr < 0x1c10) {
via_write(&via2, addr - 0x1c00, v, cycle);
}
}
void atn_irq_callback(uint pin, uint32_t flags) {
if (flags & GPIO_IRQ_EDGE_RISE) {
if (!(via1.pcr & 1)) {
via1.ifr |= 0b10000010;
}
if ((via1.orb & 0b00010000) && (via1.ddrb & 0b00010000)) {
gpio_set_dir(GPIO_DATA2, 1);
} else {
gpio_set_dir(GPIO_DATA2, 0);
}
} else {
if (via1.pcr & 1) {
via1.ifr |= 0b10000010;
}
if ((via1.orb & 0b00010000) && (via1.ddrb & 0b00010000)) {
gpio_set_dir(GPIO_DATA2, 0);
} else {
gpio_set_dir(GPIO_DATA2, 1);
}
}
}
void drive_thread() {
drive_init(&drive);
drive.image = _binary__Users_max_Downloads_Bloodsuckers_StillRising_BSK_StillRising_disk1_d64_start;
multicore_fifo_push_blocking(1);
while (true) {
uint32_t cycles = multicore_fifo_pop_blocking_inline();
if (drive_cycle(&drive, cycles, true) && (via2.pcr & 0b1110) == 0b1110) {
cpu.flags |= 1 << FLAG_V_BIT;
}
}
}
int main() {
set_sys_clock_khz(250000, true);
multicore_launch_core1(drive_thread);
gpio_init(GPIO_CLK);
gpio_init(GPIO_DATA);
gpio_init(GPIO_ATN);
gpio_init(GPIO_DATA2);
gpio_init(25);
gpio_put(GPIO_CLK, 0);
gpio_put(GPIO_DATA, 0);
gpio_put(GPIO_LED, 0);
gpio_put(GPIO_DATA2, 0);
gpio_set_dir(GPIO_CLK, GPIO_IN);
gpio_set_dir(GPIO_DATA, GPIO_IN);
gpio_set_dir(GPIO_ATN, GPIO_IN);
gpio_set_dir(GPIO_LED, GPIO_OUT);
gpio_set_dir(GPIO_DATA2, GPIO_IN);
gpio_set_pulls(GPIO_CLK, true, false);
gpio_set_pulls(GPIO_DATA, true, false);
gpio_set_pulls(GPIO_DATA2, true, false);
gpio_set_pulls(GPIO_ATN, true, false);
gpio_set_irq_enabled_with_callback(GPIO_ATN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &atn_irq_callback);
track_step = 0;
multicore_fifo_pop_blocking();
cpu_reset(&cpu);
via_init(&via1);
via_init(&via2);
ts = time_us_32();
uint16_t osc2 = 0xffff;
while (!cpu.jammed) {
if (ts + 100 < time_us_32()) {
break;
}
uint8_t cycles = cpu_step(&cpu);
multicore_fifo_push_blocking_inline((uint32_t)cycles);
via_cycle(&via1, cycles);
via_cycle(&via2, cycles);
cpu.irq = via_irq(&via1) | via_irq(&via2);
ts += cycles;
while (ts > time_us_32()) {}
}
return 0;
}
|