# HG changeset patch # User Michael Pavone # Date 1432103033 25200 # Node ID 22dbdf50d33c9b6c70906e5e76beb04585550f8b # Parent b707a8ddc202853708dcce9ed6f9a1b351419eb6 Small correction to VBLANK flag timing. Fixed some inconsistencies in interrupt timing calculation. diff -r b707a8ddc202 -r 22dbdf50d33c blastem.c --- a/blastem.c Sun May 17 20:03:27 2015 -0700 +++ b/blastem.c Tue May 19 23:23:53 2015 -0700 @@ -125,6 +125,7 @@ void adjust_int_cycle(m68k_context * context, vdp_context * v_context) { + //static int old_int_cycle = CYCLE_NEVER; genesis_context *gen = context->system; if (context->sync_cycle - context->current_cycle > gen->max_cycles) { context->sync_cycle = context->current_cycle + gen->max_cycles; @@ -147,6 +148,10 @@ } } } + /*if (context->int_cycle != old_int_cycle) { + printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter); + old_int_cycle = context->int_cycle; + }*/ context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle; /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", @@ -242,6 +247,7 @@ context->sync_cycle = gen->frame_end; //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); if (context->int_ack) { + printf("acknowledging %d @ %d:%d, vcounter: %d, hslot: %d\n", context->int_ack, context->current_cycle, v_context->cycles, v_context->vcounter, v_context->hslot); vdp_int_ack(v_context, context->int_ack); context->int_ack = 0; } diff -r b707a8ddc202 -r 22dbdf50d33c vdp.c --- a/vdp.c Sun May 17 20:03:27 2015 -0700 +++ b/vdp.c Tue May 19 23:23:53 2015 -0700 @@ -33,6 +33,8 @@ #define HBLANK_END_H32 0 //should be 5 according to Nemesis, but 0 seems to fit better with my test ROM results #define LINE_CHANGE_H40 165 #define LINE_CHANGE_H32 132 +#define VBLANK_START_H40 (LINE_CHANGE_H40+2) +#define VBLANK_START_H32 (LINE_CHANGE_H32+2) #define FIFO_LATENCY 3 int32_t color_map[1 << 12]; @@ -562,7 +564,7 @@ context->regs[REG_DMALEN_H] = dma_len >> 8; context->regs[REG_DMALEN_L] = dma_len; if (!dma_len) { - //printf("DMA end at cycle %d\n", context->cycles); + //printf("DMA end at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", context->cycles, context->frame, context->vcounter, context->hslot); context->flags &= ~FLAG_DMA_RUN; context->cd &= 0xF; } @@ -1448,6 +1450,20 @@ uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19}; +void vdp_advance_line(vdp_context *context) +{ + context->vcounter++; + if (context->vcounter > (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) { + context->hint_counter = context->regs[REG_HINT]; + } else if (context->hint_counter) { + context->hint_counter--; + } else { + context->flags2 |= FLAG2_HINT_PENDING; + context->pending_hint_start = context->cycles; + context->hint_counter = context->regs[REG_HINT]; + } +} + void vdp_run_context(vdp_context * context, uint32_t target_cycles) { while(context->cycles < target_cycles) @@ -1480,19 +1496,11 @@ context->slot_counter = MAX_SPRITES_LINE_H32; } } - if (is_h40 && slot == LINE_CHANGE_H40 || !is_h40 && slot == LINE_CHANGE_H32) { - if (line > inactive_start) { - context->hint_counter = context->regs[REG_HINT]; - } else if (context->hint_counter) { - context->hint_counter--; - } else { - context->flags2 |= FLAG2_HINT_PENDING; - context->hint_counter = context->regs[REG_HINT]; - } - } else if(line == inactive_start) { + if(line == inactive_start) { uint32_t intslot = context->regs[REG_MODE_4] & BIT_H40 ? VINT_SLOT_H40 : VINT_SLOT_H32; if (slot == intslot) { context->flags2 |= FLAG2_VINT_PENDING; + context->pending_vint_start = context->cycles; } } uint32_t inccycles; @@ -1522,7 +1530,6 @@ if (slot == LINE_CHANGE_H40 && line < inactive_start && (target_cycles - context->cycles) >= MCLKS_LINE) { vdp_h40_line(line, context); inccycles = MCLKS_LINE; - context->vcounter++; inc_slot = 0; } else { vdp_h40(line, slot, context); @@ -1541,12 +1548,13 @@ if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) { run_dma_src(context, slot); } + context->cycles += inccycles; if (inc_slot) { context->hslot++; context->hslot &= 0xFF; if (is_h40) { if (context->hslot == LINE_CHANGE_H40) { - context->vcounter++; + vdp_advance_line(context); if (context->vcounter == (inactive_start + 8)) { context->frame++; } @@ -1555,7 +1563,7 @@ } } else { if (context->hslot == LINE_CHANGE_H32) { - context->vcounter++; + vdp_advance_line(context); if (context->vcounter == (inactive_start + 8)) { context->frame++; } @@ -1564,6 +1572,8 @@ } } + } else { + vdp_advance_line(context); } context->vcounter &= 0x1FF; if (context->flags2 & FLAG2_REGION_PAL) { @@ -1577,7 +1587,7 @@ } else if (!(context->latched_mode & BIT_PAL) && context->vcounter == 0xEB) { context->vcounter = 0x1E5; } - context->cycles += inccycles; + } } @@ -1631,7 +1641,7 @@ //DMA copy or 68K -> VDP, transfer starts immediately context->flags |= FLAG_DMA_RUN; context->dma_cd = context->cd; - //printf("DMA start at cycle %d\n", context->cycles); + //printf("DMA start (length: %X) at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L], context->cycles, context->frame, context->vcounter, context->hslot); if (!(context->regs[REG_DMASRC_H] & 0x80)) { //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]); return 1; @@ -1654,6 +1664,9 @@ if (reg == REG_BG_COLOR) { value &= 0x3F; } + if (reg == REG_MODE_4 && ((value ^ context->regs[reg]) & BIT_H40)) { + printf("Mode changed from H%d to H%d @ %d, frame: %d\n", context->regs[reg] & BIT_H40 ? 40 : 32, value & BIT_H40 ? 40 : 32, context->cycles, context->frame); + } context->regs[reg] = value; if (reg == REG_MODE_4) { context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); @@ -1736,11 +1749,21 @@ } uint32_t line= context->vcounter; uint32_t slot = context->hslot; + uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START); if ( ( - line >= (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START) + line > inactive_start && line < 0x1FF ) + || (line == inactive_start + && ( + slot >= (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32) + || slot < (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32) + ) + ) + || (line == 0x1FF + && slot < (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32)) + && slot >= (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32) || !(context->regs[REG_MODE_2] & BIT_DISP_EN) ) { value |= 0x8; @@ -1840,6 +1863,16 @@ void vdp_adjust_cycles(vdp_context * context, uint32_t deduction) { context->cycles -= deduction; + if (context->pending_vint_start >= deduction) { + context->pending_vint_start -= deduction; + } else { + context->pending_vint_start = 0; + } + if (context->pending_hint_start >= deduction) { + context->pending_hint_start -= deduction; + } else { + context->pending_hint_start = 0; + } if (context->fifo_read >= 0) { int32_t idx = context->fifo_read; do { @@ -1853,24 +1886,31 @@ } } +uint32_t vdp_cycles_hslot_wrap_h40(vdp_context * context) +{ + if (context->hslot < 183) { + return MCLKS_LINE - context->hslot * MCLKS_SLOT_H40; + } else if (context->hslot < HSYNC_END_H40) { + uint32_t before_hsync = context->hslot < HSYNC_SLOT_H40 ? (HSYNC_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40 : 0; + uint32_t hsync = 0; + for (int i = context->hslot <= HSYNC_SLOT_H40 ? 0 : context->hslot - HSYNC_SLOT_H40; i < sizeof(h40_hsync_cycles)/sizeof(uint32_t); i++) + { + hsync += h40_hsync_cycles[i]; + } + uint32_t after_hsync = (256- HSYNC_END_H40) * MCLKS_SLOT_H40; + return before_hsync + hsync + after_hsync; + } else { + return (256-context->hslot) * MCLKS_SLOT_H40; + } +} + uint32_t vdp_cycles_next_line(vdp_context * context) { if (context->regs[REG_MODE_4] & BIT_H40) { if (context->hslot < LINE_CHANGE_H40) { return (LINE_CHANGE_H40 - context->hslot) * MCLKS_SLOT_H40; - } else if (context->hslot < 183) { - return MCLKS_LINE - (context->hslot - LINE_CHANGE_H40) * MCLKS_SLOT_H40; - } else if (context->hslot < HSYNC_END_H40){ - uint32_t before_hsync = context->hslot < HSYNC_SLOT_H40 ? (HSYNC_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40 : 0; - uint32_t hsync = 0; - for (int i = context->hslot <= HSYNC_SLOT_H40 ? 0 : context->hslot - HSYNC_SLOT_H40; i < sizeof(h40_hsync_cycles)/sizeof(uint32_t); i++) - { - hsync += h40_hsync_cycles[i]; - } - uint32_t after_hsync = (256- HSYNC_END_H40 + LINE_CHANGE_H40) * MCLKS_SLOT_H40; - return before_hsync + hsync + after_hsync; } else { - return (256-context->hslot + LINE_CHANGE_H40) * MCLKS_SLOT_H40; + return vdp_cycles_hslot_wrap_h40(context) + LINE_CHANGE_H40 * MCLKS_SLOT_H40; } } else { if (context->hslot < LINE_CHANGE_H32) { @@ -1912,9 +1952,9 @@ } } else { if (context->vcounter < jump_start) { - lines = jump_start - context->vcounter + 512 - jump_dst; + lines = jump_start - context->vcounter + 512 - jump_dst + 1; } else { - lines = 512 - context->vcounter; + lines = 512 - context->vcounter + 1; } if (target < jump_start) { lines += target; @@ -1955,7 +1995,7 @@ return 0xFFFFFFFF; } if (context->flags2 & FLAG2_HINT_PENDING) { - return context->cycles; + return context->pending_hint_start; } uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START; uint32_t hint_line; @@ -1974,7 +2014,7 @@ return 0xFFFFFFFF; } if (context->flags2 & FLAG2_VINT_PENDING) { - return context->cycles; + return context->pending_vint_start; } @@ -1987,12 +2027,8 @@ if (context->vcounter == inactive_start) { if (context->regs[REG_MODE_4] & BIT_H40) { if (context->hslot >= LINE_CHANGE_H40) { - if (context->hslot < 183) { - return context->cycles + (VINT_SLOT_H40 + 183 - context->hslot + 256 - 229) * MCLKS_SLOT_H40; - } else { - return context->cycles + (VINT_SLOT_H40 + 256 - context->hslot) * MCLKS_SLOT_H40; - } - } else if (context->hslot < VINT_SLOT_H40) { + return context->cycles + vdp_cycles_hslot_wrap_h40(context) + VINT_SLOT_H40 * MCLKS_SLOT_H40; + } else if (context->hslot <= VINT_SLOT_H40) { return context->cycles + (VINT_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40; } } else { @@ -2002,14 +2038,14 @@ } else { return context->cycles + (VINT_SLOT_H32 + 256 - context->hslot) * MCLKS_SLOT_H32; } - } else if (context->hslot < VINT_SLOT_H32) { + } else if (context->hslot <= VINT_SLOT_H32) { return context->cycles + (VINT_SLOT_H32 - context->hslot) * MCLKS_SLOT_H32; } } } int32_t cycles_to_vint = vdp_cycles_to_line(context, inactive_start); if (context->regs[REG_MODE_4] & BIT_H40) { - cycles_to_vint += (VINT_SLOT_H40 + 183 - LINE_CHANGE_H40 + 256 - 229) * MCLKS_SLOT_H40; + cycles_to_vint += MCLKS_LINE - (LINE_CHANGE_H40 - VINT_SLOT_H40) * MCLKS_SLOT_H40; } else { cycles_to_vint += (VINT_SLOT_H32 + 148 - LINE_CHANGE_H32 + 256 - 233) * MCLKS_SLOT_H32; } diff -r b707a8ddc202 -r 22dbdf50d33c vdp.h --- a/vdp.h Sun May 17 20:03:27 2015 -0700 +++ b/vdp.h Tue May 19 23:23:53 2015 -0700 @@ -132,6 +132,8 @@ uint8_t regs[VDP_REGS]; //cycle count in MCLKs uint32_t cycles; + uint32_t pending_vint_start; + uint32_t pending_hint_start; uint8_t *vdpmem; //stores 2-bit palette + 4-bit palette index + priority for current sprite line uint8_t *linebuf;