diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index 61e8da0eb91e..adbd45c6810e 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -60,9 +60,6 @@ void SCPFifoStruct::DoState(PointerWrap& p) p.Do(CPWritePointer); p.Do(CPReadPointer); p.Do(CPBreakpoint); - - // keep compatible - u32 SafeCPReadPointer = 0; p.Do(SafeCPReadPointer); p.Do(bFF_GPLinkEnable); @@ -255,33 +252,56 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // Some MMIOs have different handlers for single core vs. dual core mode. mmio->Register(base | FIFO_RW_DISTANCE_LO, + IsOnThread() ? + MMIO::ComplexRead([](u32) { + if (fifo.CPWritePointer >= fifo.SafeCPReadPointer) + return ReadLow(fifo.CPWritePointer - fifo.SafeCPReadPointer); + else + return ReadLow(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - + fifo.CPBase + 32); + }) : MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance)), MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), WMASK_LO_ALIGN_32BIT)); mmio->Register(base | FIFO_RW_DISTANCE_HI, + IsOnThread() ? + MMIO::ComplexRead([](u32) { + if (fifo.CPWritePointer >= fifo.SafeCPReadPointer) + return ReadHigh(fifo.CPWritePointer - fifo.SafeCPReadPointer); + else + return ReadHigh(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - + fifo.CPBase + 32); + }) : MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.CPReadWriteDistance)), MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { - WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); - Fifo::SyncGPU(Fifo::SyncGPUReason::Other); - if (fifo.CPReadWriteDistance == 0) - { - GPFifo::ResetGatherPipe(); - Fifo::ResetVideoBuffer(); - } - else - { - Fifo::ResetVideoBuffer(); - } - Fifo::RunGpu(); + WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); + Fifo::SyncGPU(Fifo::SyncGPUReason::Other); + if (fifo.CPReadWriteDistance == 0) + { + GPFifo::ResetGatherPipe(); + Fifo::ResetVideoBuffer(); + } + else + { + Fifo::ResetVideoBuffer(); + } + Fifo::RunGpu(); })); - mmio->Register(base | FIFO_READ_POINTER_LO, - MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadPointer)), - MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadPointer), - WMASK_LO_ALIGN_32BIT)); - mmio->Register(base | FIFO_READ_POINTER_HI, - MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.CPReadPointer)), - MMIO::DirectWrite(MMIO::Utils::HighPart(&fifo.CPReadPointer), - WMASK_HI_RESTRICT)); + mmio->Register( + base | FIFO_READ_POINTER_LO, + IsOnThread() ? MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : + MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadPointer)), + MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT)); + mmio->Register( + base | FIFO_READ_POINTER_HI, + IsOnThread() ? MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.SafeCPReadPointer)) : + MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.CPReadPointer)), + IsOnThread() ? + MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + fifo.SafeCPReadPointer = fifo.CPReadPointer; + }) : + MMIO::DirectWrite(MMIO::Utils::HighPart(&fifo.CPReadPointer), WMASK_HI_RESTRICT)); } void GatherPipeBursted() diff --git a/Source/Core/VideoCommon/CommandProcessor.h b/Source/Core/VideoCommon/CommandProcessor.h index 4ff843215a71..77623357d9e4 100644 --- a/Source/Core/VideoCommon/CommandProcessor.h +++ b/Source/Core/VideoCommon/CommandProcessor.h @@ -25,6 +25,7 @@ struct SCPFifoStruct volatile u32 CPWritePointer; volatile u32 CPReadPointer; volatile u32 CPBreakpoint; + volatile u32 SafeCPReadPointer; volatile u32 bFF_GPLinkEnable; volatile u32 bFF_GPReadEnable; diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index aaa96fc57fca..340e990d191a 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -365,6 +365,9 @@ void RunGpuLoop() s_video_buffer_read_ptr = OpcodeDecoder::Run( DataReader(s_video_buffer_read_ptr, write_ptr), &cyclesExecuted, false, &needSize); + if ((write_ptr - s_video_buffer_read_ptr) == 0) + Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer); + if (param.bSyncGPU) { cyclesExecuted = (u32)(cyclesExecuted / param.fSyncGpuOverclock);