From c5e219de520073848e63be017990fca2b9d44308 Mon Sep 17 00:00:00 2001 From: David Shadoff Date: Wed, 6 Jul 2022 22:13:13 -0400 Subject: [PATCH] Approximate effects of MAWR slicing ( #5 , #56 ) Mednafen does not respect the time-slicing of the MAWR (Memory Access Width Register) register, which arbitrates between accesses for the CPU versus those used for video display. This Pull Request doesn't accurately fix that, but it does approximate correct timing more closely. During Active Display, CPU shares access with display based on MAWR timing; when a CPU access is made when it's not the CPU's 'slot', there is a wait state introduced. This PR adds penalty cycles on a 50% ratio basis during active scan, rather than emulating the exact timing of the time slots, so it is only an approximation. It also does not impose penalty cycles during HSYNC, when sprite prefetch would take place, so this will also continue to be an inaccuracy for the time being. --- mednafen/src/hw_video/huc6270/vdc.cpp | 58 +++++++++++++++++++++++++++ mednafen/src/hw_video/huc6270/vdc.h | 4 ++ mednafen/src/pce/vce.cpp | 10 +++++ 3 files changed, 72 insertions(+) diff --git a/mednafen/src/hw_video/huc6270/vdc.cpp b/mednafen/src/hw_video/huc6270/vdc.cpp index b0060ee..089e215 100755 --- a/mednafen/src/hw_video/huc6270/vdc.cpp +++ b/mednafen/src/hw_video/huc6270/vdc.cpp @@ -297,6 +297,14 @@ void VDC::SetLayerEnableMask(uint64 mask) userle = mask; } +bool VDC::IsActiveDisplay(void) +{ + if ((VPhase == VPHASE_VDW) && (HPhase == HPHASE_HDW)) + return true; + else + return false; +} + void VDC::RunSATDMA(int32 cycles, bool force_completion) { assert(sat_dma_counter > 0); @@ -1333,6 +1341,18 @@ uint8 VDC::Read(uint32 A, int32 &next_event, bool peek) pending_read_addr = MARR; MARR += vram_inc_tab[(CR >> 11) & 0x3]; + // Simulate MAWR round-robin; implementing it properly would require changing too much code + // Assume a 50% hit rate on missing the CPU window, taking a 1-cycle penalty + // when committing such a word. + if (IsActiveDisplay()) + { +// if (MAWRPhase && ((select & 0x1F) == 0x02)) +// { + ActiveDisplayPenaltyCycles++; +// } +// MAWRPhase = (MAWRPhase == true) ? false : true; + } + CheckAndCommitPending(); } } @@ -1372,6 +1392,19 @@ uint16 VDC::Read16(bool A, bool peek) pending_read_addr = MARR; MARR += vram_inc_tab[(CR >> 11) & 0x3]; + // Simulate MAWR round-robin; implementing it properly would require changing too much code + // Assume a 50% hit rate on missing the CPU window, taking a 1-cycle penalty + // when committing such a word. + if (IsActiveDisplay()) + { +// if (MAWRPhase) +// { + ActiveDisplayPenaltyCycles++; + ActiveDisplayPenaltyCycles++; +// } +// MAWRPhase = (MAWRPhase == true) ? false : true; + } + CheckAndCommitPending(); } } @@ -1462,6 +1495,18 @@ void VDC::Write(uint32 A, uint8 V, int32 &next_event) pending_write_latch = write_latch | (V << 8); MAWR += vram_inc_tab[(CR >> 11) & 0x3]; + // Simulate MAWR round-robin; implementing it properly would require changing too much code + // Assume a 50% hit rate on missing the CPU window, taking a 1-cycle penalty + // when committing such a word. + if (IsActiveDisplay()) + { +// if (MAWRPhase && ((select & 0x1F) == 0x03)) +// { + ActiveDisplayPenaltyCycles++; +// } +// MAWRPhase = (MAWRPhase == true) ? false : true; + } + CheckAndCommitPending(); } break; @@ -1590,6 +1635,19 @@ void VDC::Write16(bool A, uint16 V) pending_write_latch = V; MAWR += vram_inc_tab[(CR >> 11) & 0x3]; + // Simulate MAWR round-robin; implementing it properly would require changing too much code + // Assume a 50% hit rate on missing the CPU window, taking a 1-cycle penalty + // when committing such a word. + if (IsActiveDisplay()) + { +// if (MAWRPhase) +// { + ActiveDisplayPenaltyCycles++; + ActiveDisplayPenaltyCycles++; +// } +// MAWRPhase = (MAWRPhase == true) ? false : true; + } + CheckAndCommitPending(); break; diff --git a/mednafen/src/hw_video/huc6270/vdc.h b/mednafen/src/hw_video/huc6270/vdc.h index afec3cb..2e68a36 100755 --- a/mednafen/src/hw_video/huc6270/vdc.h +++ b/mednafen/src/hw_video/huc6270/vdc.h @@ -272,6 +272,10 @@ class VDC void DoVBIRQTest(void); void HDS_Start(void); + bool IsActiveDisplay(void); + uint32 ActiveDisplayPenaltyCycles = 0; // to simulate the MAWR time-slot + bool MAWRPhase = false; // to simulate the MAWR time-slot + void StateExtra(LEPacker &sl_packer, bool load); void StateAction(StateMem *sm, const unsigned load, const bool data_only, const char *sname); diff --git a/mednafen/src/pce/vce.cpp b/mednafen/src/pce/vce.cpp index 6aa711c..6a45cda 100644 --- a/mednafen/src/pce/vce.cpp +++ b/mednafen/src/pce/vce.cpp @@ -77,6 +77,16 @@ bool VCE::WS_Hook(int32 vdc_cycles) ret = false; } + for(unsigned chip = 0; chip < chip_count; chip++) + { + while (vdc[chip].ActiveDisplayPenaltyCycles > 0) // try to make accesses to ActiveDisplayPenaltyCycles as atomic as possible + { + to_steal++; + vdc[chip].ActiveDisplayPenaltyCycles--; + } + } + + if(to_steal > 0) { HuCPU.StealCycles(to_steal);