Mercurial > repos > blastem
comparison genesis.c @ 1372:d78ef6f4fba2
Attempt at improving refresh emulation
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 23 May 2017 23:00:32 -0700 |
parents | 5b20840711c1 |
children | 7cfc9d532e34 |
comparison
equal
deleted
inserted
replaced
1371:5b20840711c1 | 1372:d78ef6f4fba2 |
---|---|
179 genesis_context * gen = context->system; | 179 genesis_context * gen = context->system; |
180 vdp_context * v_context = gen->vdp; | 180 vdp_context * v_context = gen->vdp; |
181 z80_context * z_context = gen->z80; | 181 z80_context * z_context = gen->z80; |
182 #ifdef REFRESH_EMULATION | 182 #ifdef REFRESH_EMULATION |
183 //lame estimation of refresh cycle delay | 183 //lame estimation of refresh cycle delay |
184 refresh_counter += context->current_cycle - last_sync_cycle; | |
184 if (!gen->bus_busy) { | 185 if (!gen->bus_busy) { |
185 refresh_counter += context->current_cycle - last_sync_cycle; | |
186 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); | 186 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); |
187 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | 187 } |
188 } | 188 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); |
189 #endif | 189 #endif |
190 | 190 |
191 uint32_t mclks = context->current_cycle; | 191 uint32_t mclks = context->current_cycle; |
192 sync_z80(z_context, mclks); | 192 sync_z80(z_context, mclks); |
193 sync_sound(gen, mclks); | 193 sync_sound(gen, mclks); |
271 if (vdp_port & 0x2700E0) { | 271 if (vdp_port & 0x2700E0) { |
272 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); | 272 fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); |
273 } | 273 } |
274 vdp_port &= 0x1F; | 274 vdp_port &= 0x1F; |
275 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); | 275 //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); |
276 #ifdef REFRESH_EMULATION | |
277 //do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access | |
278 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; | |
279 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); | |
280 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | |
281 last_sync_cycle = context->current_cycle; | |
282 #endif | |
276 sync_components(context, 0); | 283 sync_components(context, 0); |
277 genesis_context * gen = context->system; | 284 genesis_context * gen = context->system; |
278 vdp_context *v_context = gen->vdp; | 285 vdp_context *v_context = gen->vdp; |
279 if (vdp_port < 0x10) { | 286 if (vdp_port < 0x10) { |
280 int blocked; | 287 int blocked; |
281 uint32_t before_cycle = v_context->cycles; | 288 uint32_t before_cycle = v_context->cycles; |
282 if (vdp_port < 4) { | 289 if (vdp_port < 4) { |
283 | |
284 while (vdp_data_port_write(v_context, value) < 0) { | 290 while (vdp_data_port_write(v_context, value) < 0) { |
285 while(v_context->flags & FLAG_DMA_RUN) { | 291 while(v_context->flags & FLAG_DMA_RUN) { |
286 vdp_run_dma_done(v_context, gen->frame_end); | 292 vdp_run_dma_done(v_context, gen->frame_end); |
287 if (v_context->cycles >= gen->frame_end) { | 293 if (v_context->cycles >= gen->frame_end) { |
288 uint32_t cycle_diff = v_context->cycles - context->current_cycle; | 294 uint32_t cycle_diff = v_context->cycles - context->current_cycle; |
338 uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K; | 344 uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K; |
339 if (m68k_cycle_diff < cycle_diff) { | 345 if (m68k_cycle_diff < cycle_diff) { |
340 m68k_cycle_diff += MCLKS_PER_68K; | 346 m68k_cycle_diff += MCLKS_PER_68K; |
341 } | 347 } |
342 context->current_cycle += m68k_cycle_diff; | 348 context->current_cycle += m68k_cycle_diff; |
343 #ifdef REFRESH_EMULATION | |
344 last_sync_cycle = context->current_cycle; | |
345 if (vdp_port >= 4 && vdp_port < 8) { | |
346 refresh_counter = 0; | |
347 } | |
348 #endif | |
349 //Lock the Z80 out of the bus until the VDP access is complete | 349 //Lock the Z80 out of the bus until the VDP access is complete |
350 gen->bus_busy = 1; | 350 gen->bus_busy = 1; |
351 sync_z80(gen->z80, v_context->cycles); | 351 sync_z80(gen->z80, v_context->cycles); |
352 gen->bus_busy = 0; | 352 gen->bus_busy = 0; |
353 } | 353 } |
354 } else if (vdp_port < 0x18) { | 354 } else if (vdp_port < 0x18) { |
355 psg_write(gen->psg, value); | 355 psg_write(gen->psg, value); |
356 } else { | 356 } else { |
357 vdp_test_port_write(gen->vdp, value); | 357 vdp_test_port_write(gen->vdp, value); |
358 } | 358 } |
359 #ifdef REFRESH_EMULATION | |
360 last_sync_cycle -= 4; | |
361 //refresh may have happened while we were waiting on the VDP, | |
362 //so advance refresh_counter but don't add any delays | |
363 refresh_counter += (context->current_cycle - last_sync_cycle); | |
364 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | |
365 last_sync_cycle = context->current_cycle; | |
366 #endif | |
359 return context; | 367 return context; |
360 } | 368 } |
361 | 369 |
362 static m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value) | 370 static m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value) |
363 { | 371 { |
397 if (vdp_port & 0x2700E0) { | 405 if (vdp_port & 0x2700E0) { |
398 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); | 406 fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); |
399 } | 407 } |
400 vdp_port &= 0x1F; | 408 vdp_port &= 0x1F; |
401 uint16_t value; | 409 uint16_t value; |
410 #ifdef REFRESH_EMULATION | |
411 //do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access | |
412 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; | |
413 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); | |
414 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | |
415 last_sync_cycle = context->current_cycle; | |
416 #endif | |
402 sync_components(context, 0); | 417 sync_components(context, 0); |
403 genesis_context *gen = context->system; | 418 genesis_context *gen = context->system; |
404 vdp_context * v_context = gen->vdp; | 419 vdp_context * v_context = gen->vdp; |
405 uint32_t before_cycle = v_context->cycles; | 420 uint32_t before_cycle = v_context->cycles; |
406 if (vdp_port < 0x10) { | 421 if (vdp_port < 0x10) { |
418 value = vdp_test_port_read(v_context); | 433 value = vdp_test_port_read(v_context); |
419 } | 434 } |
420 if (v_context->cycles != before_cycle) { | 435 if (v_context->cycles != before_cycle) { |
421 //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); | 436 //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); |
422 context->current_cycle = v_context->cycles; | 437 context->current_cycle = v_context->cycles; |
423 #ifdef REFRESH_EMULATION | |
424 last_sync_cycle = context->current_cycle; | |
425 #endif | |
426 //Lock the Z80 out of the bus until the VDP access is complete | 438 //Lock the Z80 out of the bus until the VDP access is complete |
427 genesis_context *gen = context->system; | 439 genesis_context *gen = context->system; |
428 gen->bus_busy = 1; | 440 gen->bus_busy = 1; |
429 sync_z80(gen->z80, v_context->cycles); | 441 sync_z80(gen->z80, v_context->cycles); |
430 gen->bus_busy = 0; | 442 gen->bus_busy = 0; |
431 } | 443 } |
444 #ifdef REFRESH_EMULATION | |
445 last_sync_cycle -= 4; | |
446 //refresh may have happened while we were waiting on the VDP, | |
447 //so advance refresh_counter but don't add any delays | |
448 refresh_counter += (context->current_cycle - last_sync_cycle); | |
449 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | |
450 last_sync_cycle = context->current_cycle; | |
451 #endif | |
432 return value; | 452 return value; |
433 } | 453 } |
434 | 454 |
435 static uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) | 455 static uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) |
436 { | 456 { |