// c64.c // // 20060803 Markku Alén #include "c64.h" #include "cpu.h" #include "mem.h" #include "sid.h" #include "cia.h" #include "tape.h" unsigned int total_cycles; static cia_t cia1; static int on_chip_port_pins; static int on_chip_port_input; static int on_chip_port_output; static int on_chip_port_direction; #define UPDATE_ON_CHIP_PORT_PINS() (on_chip_port_pins = (on_chip_port_output & on_chip_port_direction) | (on_chip_port_input & ~on_chip_port_direction)) static int page_read(int address) { switch(address & 0xffff) { case 0x0000: return on_chip_port_direction; case 0x0001: return on_chip_port_output; default: return ram[address & 0xffff]; } } static void page_write(int address, int data) { switch(address & 0xffff) { case 0x0000: on_chip_port_direction = data; UPDATE_ON_CHIP_PORT_PINS(); break; case 0x0001: on_chip_port_output = data; UPDATE_ON_CHIP_PORT_PINS(); break; default: ram[address & 0xffff] = data; } } static int io_read(int address) { switch(address & 0x0c00) { case 0x0000: return 0; case 0x0400: return sid_read(address); case 0x0800: return color[address % sizeof(color)]; default: switch(address & 0x0300) { case 0x0000: return cia_read(&cia1, address); case 0x0100: return 0; default: return 0x00; } } } static void io_write(int address, int data) { switch(address & 0x0c00) { case 0x0000: break; case 0x0400: sid_write(address, data); break; case 0x0800: color[address % sizeof(color)] = data; break; default: switch(address & 0x0300) { case 0x0000: cia_write(&cia1, address, data); if((address & 0x000f) == 0x00) cia_port_b_input(&cia1, kbd_data(cia_a_port_output(&cia1))); break; case 0x0100: break; } } } static int cpu_read(int address) { switch(address & 0xf000) { case 0xa000: case 0xb000: switch(on_chip_port_pins & 0x07) { case 0x03: case 0x07: return basic[address % sizeof(basic)]; default: return page_read(address); } break; case 0xd000: switch(on_chip_port_pins & 0x07) { case 0x01: case 0x02: case 0x03: return chars[address % sizeof(chars)]; case 0x05: case 0x06: case 0x07: return io_read(address); default: return page_read(address); } break; case 0xe000: case 0xf000: switch(on_chip_port_pins & 0x07) { case 0x02: case 0x03: case 0x06: case 0x07: return kernel[address % sizeof(kernel)]; default: return page_read(address); } break; default: return page_read(address); } } static void cpu_write(int address, int data) { switch(address & 0xf000) { case 0xd000: switch(on_chip_port_pins & 0x07) { case 0x05: case 0x06: case 0x07: io_write(address, data); break; default: page_write(address, data); } break; default: page_write(address, data); } } static void cpu_jam(int address, int op_code) { reset_cpu(); } void c64_init(void) { total_cycles = 0; on_chip_port_input = 0xff; on_chip_port_output = 0x00; on_chip_port_direction = 0x00; UPDATE_ON_CHIP_PORT_PINS(); kbd_init(); sid_init(); cia_init(&cia1); init_cpu(cpu_read, cpu_write, page_read, page_write, cpu_jam); init_tape(); reset_cpu(); } void c64_run(unsigned int cycle_count) { unsigned int elapsed_cycles; for(;;) { elapsed_cycles = cycles; exec_cpu(); elapsed_cycles = cycles - elapsed_cycles; if(cycle_count <= elapsed_cycles) break; cycle_count -= elapsed_cycles; total_cycles += elapsed_cycles; cia_exec(&cia1, elapsed_cycles); if(cia1.irq_pin) raise_irq(); } }