diff options
Diffstat (limited to 'c64/c64.c')
| -rw-r--r-- | c64/c64.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/c64/c64.c b/c64/c64.c new file mode 100644 index 0000000..2cbbfe9 --- /dev/null +++ b/c64/c64.c @@ -0,0 +1,207 @@ +// 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();
+ }
+}
+
|
