Mercurial > repos > simple16
diff src/main.c @ 25:fb14515266f4
Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 31 Mar 2016 23:25:52 -0700 |
parents | 4c9dbfa30a66 |
children | 083347ccd508 |
line wrap: on
line diff
--- a/src/main.c Thu Mar 31 00:07:37 2016 -0700 +++ b/src/main.c Thu Mar 31 23:25:52 2016 -0700 @@ -5,6 +5,7 @@ #include "cpu.h" #include "vdp.h" #include "audio.h" +#include "timer.h" #include "system.h" #define CYCLES_PER_FRAME (832*262) @@ -34,8 +35,9 @@ typedef struct { cpu *proc; + audio *audio; + timer timer; vdp video; - audio *audio; } console; void debug_port_write(cpu *context, uint8_t port, uint16_t value) @@ -111,6 +113,55 @@ audio_write_vol(system->audio, port - PORT_VOLUME_AB, value); } +void timer_port_write(cpu *context, uint8_t port, uint16_t value) +{ + console *system = context->system; + timer_run(&system->timer, context->cycles); + timer_write(&system->timer, value); + uint32_t next_int = next_interrupt_cycle(context, (~context->pending_interrupts) & 3); + if (next_int < context->current_target) { + context->current_target = next_int; + } +} + +uint32_t next_interrupt_cycle(cpu *context, uint8_t mask) +{ + console *system = context->system; + uint32_t next = 0xFFFFFFFF; + if (mask & 1) { + timer_run(&system->timer, context->cycles); + next = timer_next_interrupt(&system->timer); + } + if (mask & 2) { + vdp_run(&system->video, context->cycles); + //TODO: VBlank interrupt + } + return next; +} + +uint8_t get_current_interrupts(cpu *context) +{ + console *system = context->system; + timer_run(&system->timer, context->cycles); + uint8_t bits = 0; + if (system->timer.pending) { + bits |= 1; + } + vdp_run(&system->video, context->cycles); + //TODO: VBlank interrupt + return bits; +} + +void ack_interrupt(cpu *context, int which) +{ + console *system = context->system; + if (which == 0) { + timer_run(&system->timer, context->cycles); + system->timer.pending = 0; + } + //TODO: VBlank interrupt +} + memory_region regions[] = { {rom, 0, sizeof(rom)-1, MEM_READ}, {ram, sizeof(rom), sizeof(rom)-1+sizeof(ram), MEM_READ}, @@ -123,9 +174,11 @@ run_cpu(context->proc, CYCLES_PER_FRAME); audio_run(context->audio, CYCLES_PER_FRAME); vdp_run(&context->video, CYCLES_PER_FRAME); + timer_run(&context->timer, CYCLES_PER_FRAME); context->proc->cycles -= CYCLES_PER_FRAME; context->video.cycles -= CYCLES_PER_FRAME; context->audio->cycles -= CYCLES_PER_FRAME; + context->timer.cycles -= CYCLES_PER_FRAME; system_poll_events(); } } @@ -150,12 +203,14 @@ context.proc = alloc_cpu(10, sizeof(regions)/sizeof(memory_region), regions); context.proc->system = &context; vdp_init(&context.video, 2); + timer_init(&context.timer, 16); context.proc->port_handlers[PORT_FREQUENCY_A].write = frequency_port_write; context.proc->port_handlers[PORT_FREQUENCY_B].write = frequency_port_write; context.proc->port_handlers[PORT_FREQUENCY_C].write = frequency_port_write; context.proc->port_handlers[PORT_FREQUENCY_D].write = frequency_port_write; context.proc->port_handlers[PORT_VOLUME_AB].write = volume_port_write; context.proc->port_handlers[PORT_VOLUME_CD].write = volume_port_write; + context.proc->port_handlers[PORT_TIMER].write = timer_port_write; context.proc->port_handlers[PORT_SERIAL].write = debug_port_write; context.proc->port_handlers[PORT_SERIAL].read = debug_port_read; context.proc->port_handlers[PORT_VERTICAL].write = vertical_port_write;