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 {