comparison genesis.c @ 2227:eaaf28af3c94

Implement VDP read latency and invalid write delays revealed by Ti_'s instruction timing ROM
author Michael Pavone <pavone@retrodev.com>
date Mon, 05 Sep 2022 22:18:25 -0700
parents 01ff005b08f6
children 0db9dc6a9020
comparison
equal deleted inserted replaced
2226:d15c68157288 2227:eaaf28af3c94
632 //context->current_cycle = v_context->cycles; 632 //context->current_cycle = v_context->cycles;
633 } 633 }
634 } else if(vdp_port < 8) { 634 } else if(vdp_port < 8) {
635 vdp_run_context_full(v_context, context->current_cycle); 635 vdp_run_context_full(v_context, context->current_cycle);
636 before_cycle = v_context->cycles; 636 before_cycle = v_context->cycles;
637 blocked = vdp_control_port_write(v_context, value); 637 blocked = vdp_control_port_write(v_context, value, context->current_cycle);
638 if (blocked) { 638 if (blocked) {
639 while (blocked) { 639 while (blocked) {
640 while(v_context->flags & FLAG_DMA_RUN) { 640 while(v_context->flags & FLAG_DMA_RUN) {
641 vdp_run_dma_done(v_context, gen->frame_end); 641 vdp_run_dma_done(v_context, gen->frame_end);
642 if (v_context->cycles >= gen->frame_end) { 642 if (v_context->cycles >= gen->frame_end) {
651 gen->bus_busy = 0; 651 gen->bus_busy = 0;
652 } 652 }
653 } 653 }
654 654
655 if (blocked < 0) { 655 if (blocked < 0) {
656 blocked = vdp_control_port_write(v_context, value); 656 blocked = vdp_control_port_write(v_context, value, context->current_cycle);
657 } else { 657 } else {
658 blocked = 0; 658 blocked = 0;
659 } 659 }
660 } 660 }
661 } else { 661 } else {
717 if (vdp_port < 4) { 717 if (vdp_port < 4) {
718 vdp_run_context(gen->vdp, context->Z80_CYCLE); 718 vdp_run_context(gen->vdp, context->Z80_CYCLE);
719 vdp_data_port_write(gen->vdp, value << 8 | value); 719 vdp_data_port_write(gen->vdp, value << 8 | value);
720 } else if (vdp_port < 8) { 720 } else if (vdp_port < 8) {
721 vdp_run_context_full(gen->vdp, context->Z80_CYCLE); 721 vdp_run_context_full(gen->vdp, context->Z80_CYCLE);
722 vdp_control_port_write(gen->vdp, value << 8 | value); 722 vdp_control_port_write(gen->vdp, value << 8 | value, context->Z80_CYCLE);
723 } else { 723 } else {
724 fatal_error("Illegal write to HV Counter port %X\n", vdp_port); 724 fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
725 } 725 }
726 } else if (vdp_port < 0x18) { 726 } else if (vdp_port < 0x18) {
727 sync_sound(gen, context->Z80_CYCLE); 727 sync_sound(gen, context->Z80_CYCLE);
750 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); 750 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
751 last_sync_cycle = context->current_cycle; 751 last_sync_cycle = context->current_cycle;
752 #endif 752 #endif
753 sync_components(context, 0); 753 sync_components(context, 0);
754 vdp_context * v_context = gen->vdp; 754 vdp_context * v_context = gen->vdp;
755 uint32_t before_cycle = v_context->cycles; 755 uint32_t before_cycle = context->current_cycle;
756 if (vdp_port < 0x10) { 756 if (vdp_port < 0x10) {
757 if (vdp_port < 4) { 757 if (vdp_port < 4) {
758 value = vdp_data_port_read(v_context); 758 value = vdp_data_port_read(v_context, &context->current_cycle, MCLKS_PER_68K);
759 } else if(vdp_port < 8) { 759 } else if(vdp_port < 8) {
760 value = vdp_control_port_read(v_context); 760 value = vdp_control_port_read(v_context);
761 } else { 761 } else {
762 value = vdp_hv_counter_read(v_context); 762 value = vdp_hv_counter_read(v_context);
763 //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); 763 //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles);
765 } else if (vdp_port < 0x18){ 765 } else if (vdp_port < 0x18){
766 fatal_error("Illegal read from PSG port %X\n", vdp_port); 766 fatal_error("Illegal read from PSG port %X\n", vdp_port);
767 } else { 767 } else {
768 value = get_open_bus_value(&gen->header); 768 value = get_open_bus_value(&gen->header);
769 } 769 }
770 if (v_context->cycles != before_cycle) { 770 if (context->current_cycle != before_cycle) {
771 //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); 771 //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);
772 context->current_cycle = v_context->cycles;
773 //Lock the Z80 out of the bus until the VDP access is complete 772 //Lock the Z80 out of the bus until the VDP access is complete
774 genesis_context *gen = context->system; 773 genesis_context *gen = context->system;
775 gen->bus_busy = 1; 774 gen->bus_busy = 1;
776 sync_z80(gen, v_context->cycles); 775 sync_z80(gen, context->current_cycle);
777 gen->bus_busy = 0; 776 gen->bus_busy = 0;
778 } 777 }
779 #ifdef REFRESH_EMULATION 778 #ifdef REFRESH_EMULATION
780 last_sync_cycle -= 4 * MCLKS_PER_68K; 779 last_sync_cycle -= 4 * MCLKS_PER_68K;
781 //refresh may have happened while we were waiting on the VDP, 780 //refresh may have happened while we were waiting on the VDP,
816 vdp_port &= 0x1F; 815 vdp_port &= 0x1F;
817 uint16_t ret; 816 uint16_t ret;
818 if (vdp_port < 0x10) { 817 if (vdp_port < 0x10) {
819 //These probably won't currently interact well with the 68K accessing the VDP 818 //These probably won't currently interact well with the 68K accessing the VDP
820 vdp_run_context(gen->vdp, context->Z80_CYCLE); 819 vdp_run_context(gen->vdp, context->Z80_CYCLE);
820 uint32_t before = context->Z80_CYCLE;
821 if (vdp_port < 4) { 821 if (vdp_port < 4) {
822 ret = vdp_data_port_read(gen->vdp); 822 ret = vdp_data_port_read(gen->vdp, &context->Z80_CYCLE, MCLKS_PER_Z80);
823 } else if (vdp_port < 8) { 823 } else if (vdp_port < 8) {
824 ret = vdp_control_port_read(gen->vdp); 824 ret = vdp_control_port_read(gen->vdp);
825 } else { 825 } else {
826 ret = vdp_hv_counter_read(gen->vdp); 826 ret = vdp_hv_counter_read(gen->vdp);
827 }
828 if (context->Z80_CYCLE != before) {
829 gen->m68k->current_cycle += context->Z80_CYCLE - before;
827 } 830 }
828 } else { 831 } else {
829 //TODO: Figure out the correct value today 832 //TODO: Figure out the correct value today
830 ret = 0xFFFF; 833 ret = 0xFFFF;
831 } 834 }