# HG changeset patch # User Michael Pavone # Date 1459571678 25200 # Node ID 083347ccd508bd605553dfaf80614c9814d461c6 # Parent fb14515266f4eab30d35a62fc6b96e38d08ce8e0 Implemented vblank interrupts and fixed a bug in exception vector address calculation diff -r fb14515266f4 -r 083347ccd508 src/cpu.c --- a/src/cpu.c Thu Mar 31 23:25:52 2016 -0700 +++ b/src/cpu.c Fri Apr 01 21:34:38 2016 -0700 @@ -129,7 +129,7 @@ context->exception_pc = context->regs[REG_PC] - 2; context->exception_sr = context->regs[REG_SR]; context->regs[REG_SR] &= ~(STATUS_INT0_ENABLE | STATUS_INT1_ENABLE); - context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception); + context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception * 2); context->state = STATE_NEED_FETCH; } diff -r fb14515266f4 -r 083347ccd508 src/main.c --- a/src/main.c Thu Mar 31 23:25:52 2016 -0700 +++ b/src/main.c Fri Apr 01 21:34:38 2016 -0700 @@ -134,7 +134,10 @@ } if (mask & 2) { vdp_run(&system->video, context->cycles); - //TODO: VBlank interrupt + uint32_t vnext = vdp_next_interrupt(&system->video); + if (vnext < next) { + next = vnext; + } } return next; } @@ -148,7 +151,9 @@ bits |= 1; } vdp_run(&system->video, context->cycles); - //TODO: VBlank interrupt + if (vdp_interrupt_pending(&system->video)) { + bits |= 2; + } return bits; } @@ -158,8 +163,9 @@ if (which == 0) { timer_run(&system->timer, context->cycles); system->timer.pending = 0; + } else { + vdp_ack_interrupt(&system->video); } - //TODO: VBlank interrupt } memory_region regions[] = { diff -r fb14515266f4 -r 083347ccd508 src/vdp.c --- a/src/vdp.c Thu Mar 31 23:25:52 2016 -0700 +++ b/src/vdp.c Fri Apr 01 21:34:38 2016 -0700 @@ -146,6 +146,8 @@ context->framebuffer = system_get_framebuffer(&context->pitch); //pitch is in terms of bytes, but we want it in terms of pixels context->pitch /= sizeof(uint16_t); + //clear pending interrupt flag since VBlank is over + context->status &= ~VDP_STATUS_PENDING_VINT; } uint16_t *dest = context->framebuffer + (context->vcounter - 9) * context->pitch + context->hcounter; if (context->status & VDP_STATUS_ENABLED && context->vcounter > 16 && context->vcounter < 241) { @@ -159,6 +161,9 @@ *dest = *context->cram; } } else if(!context->hcounter && context->vcounter == 249) { + if (context->status & VDP_STATUS_ENABLED) { + context->status |= VDP_STATUS_PENDING_VINT; + } system_framebuffer_updated(); context->framebuffer = NULL; } @@ -220,3 +225,30 @@ context->status &= ~VDP_STATUS_ENABLED; } } + +uint32_t vdp_next_interrupt(vdp *context) +{ + if (context->status & VDP_STATUS_PENDING_VINT) { + return 0; + } else if (context->status & VDP_STATUS_ENABLED) { + uint32_t next_line = context->vcounter + 1; + uint32_t next_line_cyc = context->cycles + ((416 - context->hcounter) >> 1) * context->clock_inc; + if (context->vcounter < 249) { + return next_line_cyc + (249 - next_line) * 832; + } else { + return next_line_cyc + (249 + 262 - next_line) * 832; + } + } else { + return 0xFFFFFFFF; + } +} + +void vdp_ack_interrupt(vdp *context) +{ + context->status &= ~VDP_STATUS_PENDING_VINT; +} + +uint8_t vdp_interrupt_pending(vdp *context) +{ + return (context->status & VDP_STATUS_PENDING_VINT) != 0; +} diff -r fb14515266f4 -r 083347ccd508 src/vdp.h --- a/src/vdp.h Thu Mar 31 23:25:52 2016 -0700 +++ b/src/vdp.h Fri Apr 01 21:34:38 2016 -0700 @@ -51,16 +51,20 @@ FIFO_DEST_CRAM }; -#define VDP_STATUS_FIFO 1 -#define VDP_STATUS_VRAM 2 -#define VDP_STATUS_SRAM 4 -#define VDP_STATUS_ENABLED 8 -#define VDP_STATUS_SPRITE_SCAN 16 +#define VDP_STATUS_FIFO 1 +#define VDP_STATUS_VRAM 2 +#define VDP_STATUS_SRAM 4 +#define VDP_STATUS_ENABLED 8 +#define VDP_STATUS_SPRITE_SCAN 16 +#define VDP_STATUS_PENDING_VINT 32 void vdp_init(vdp *context, uint32_t clock_div); void vdp_run(vdp *context, uint32_t target); void vdp_write_address(vdp *context, uint16_t value); void vdp_write_data(vdp *context, uint16_t value); void vdp_write_hscroll(vdp *context, uint16_t value); +uint32_t vdp_next_interrupt(vdp *context); +void vdp_ack_interrupt(vdp *context); +uint8_t vdp_interrupt_pending(vdp *context); #endif //VDP_H_ diff -r fb14515266f4 -r 083347ccd508 vint.s16 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vint.s16 Fri Apr 01 21:34:38 2016 -0700 @@ -0,0 +1,55 @@ + ldim vectors, r0 + setvbr r0 + ;current color value + ldim 0, r0 + ;color increment + ldim $11, r3 + ldimh $1, r3 + ;color max + ldim $FF, r5 + ldimh $F, r5 + ;counter + ldim 1, r4 + ;Palette RAM address + ldim 0, r1 + ldimh $FF, r1 + ;enable interrupt + ori 2, sr + ;enable display + ldim 0, r2 + ldimh $80, r2 + outi $D, r2 +wait + bra wait + ;shouldn't get here, disable display so it's clear something broke + ldimh $0, r2 + outi $D, r2 + bra wait + +vectors: + dc.w 0 + dc.w vint_handler + +vint_handler + addi -1, r4 + bne done + outi $E, r1 + outi $F, r0 + cmp r0, r5 + beq down +resume + add r3, r0, r0 + beq up + ldim 5, r4 +done + reti r13 +down + ldim $EF, r3 + ldimh $FE, r3 + bra resume +up + ldim $11, r3 + ldimh $1, r3 + ldim 5, r4 + reti r13 + \ No newline at end of file