# HG changeset patch # User Michael Pavone # Date 1495605632 25200 # Node ID d78ef6f4fba2eb64d446f9e3dc1a76ab4326a4e5 # Parent 5b20840711c1b1a7d209f5ca77b0cb5e9e26c9cb Attempt at improving refresh emulation diff -r 5b20840711c1 -r d78ef6f4fba2 genesis.c --- a/genesis.c Tue May 23 21:09:38 2017 -0700 +++ b/genesis.c Tue May 23 23:00:32 2017 -0700 @@ -181,11 +181,11 @@ z80_context * z_context = gen->z80; #ifdef REFRESH_EMULATION //lame estimation of refresh cycle delay + refresh_counter += context->current_cycle - last_sync_cycle; if (!gen->bus_busy) { - refresh_counter += context->current_cycle - last_sync_cycle; context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); - refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); } + refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); #endif uint32_t mclks = context->current_cycle; @@ -273,6 +273,13 @@ } vdp_port &= 0x1F; //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); +#ifdef REFRESH_EMULATION + //do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access + refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; + context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); + refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); + last_sync_cycle = context->current_cycle; +#endif sync_components(context, 0); genesis_context * gen = context->system; vdp_context *v_context = gen->vdp; @@ -280,7 +287,6 @@ int blocked; uint32_t before_cycle = v_context->cycles; if (vdp_port < 4) { - while (vdp_data_port_write(v_context, value) < 0) { while(v_context->flags & FLAG_DMA_RUN) { vdp_run_dma_done(v_context, gen->frame_end); @@ -340,12 +346,6 @@ m68k_cycle_diff += MCLKS_PER_68K; } context->current_cycle += m68k_cycle_diff; -#ifdef REFRESH_EMULATION - last_sync_cycle = context->current_cycle; - if (vdp_port >= 4 && vdp_port < 8) { - refresh_counter = 0; - } -#endif //Lock the Z80 out of the bus until the VDP access is complete gen->bus_busy = 1; sync_z80(gen->z80, v_context->cycles); @@ -356,6 +356,14 @@ } else { vdp_test_port_write(gen->vdp, value); } +#ifdef REFRESH_EMULATION + last_sync_cycle -= 4; + //refresh may have happened while we were waiting on the VDP, + //so advance refresh_counter but don't add any delays + refresh_counter += (context->current_cycle - last_sync_cycle); + refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); + last_sync_cycle = context->current_cycle; +#endif return context; } @@ -399,6 +407,13 @@ } vdp_port &= 0x1F; uint16_t value; +#ifdef REFRESH_EMULATION + //do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access + refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; + context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); + refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); + last_sync_cycle = context->current_cycle; +#endif sync_components(context, 0); genesis_context *gen = context->system; vdp_context * v_context = gen->vdp; @@ -420,15 +435,20 @@ if (v_context->cycles != before_cycle) { //printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); context->current_cycle = v_context->cycles; -#ifdef REFRESH_EMULATION - last_sync_cycle = context->current_cycle; -#endif //Lock the Z80 out of the bus until the VDP access is complete genesis_context *gen = context->system; gen->bus_busy = 1; sync_z80(gen->z80, v_context->cycles); gen->bus_busy = 0; } +#ifdef REFRESH_EMULATION + last_sync_cycle -= 4; + //refresh may have happened while we were waiting on the VDP, + //so advance refresh_counter but don't add any delays + refresh_counter += (context->current_cycle - last_sync_cycle); + refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); + last_sync_cycle = context->current_cycle; +#endif return value; }