#include <hardware/clocks.h>
#include <hardware/gpio.h>
#include <hardware/timer.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_3sira_still_human_by_arise_3sira_by_arise_A_d64_start[174848];
static uint32_t ts;
static cpu_t cpu;
static via_t via1;
static via_t via2;
static 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);
}
}
}
int main() {
set_sys_clock_khz(250000, true);
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;
drive_init(&drive);
drive.image = _binary__Users_max_Downloads_blackbird_1_2_Blackbird_1_2_d64_start;
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);
via_cycle(&via1, cycles);
via_cycle(&via2, cycles);
cpu.irq = via_irq(&via1) | via_irq(&via2);
if (drive_cycle(&drive, cycles, true) && (via2.pcr & 0b1110) == 0b1110) {
cpu.flags |= 1 << FLAG_V_BIT;
}
ts += cycles;
while (ts > time_us_32()) {}
}
gpio_put(GPIO_LED, 1);
return 0;
}