diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 41f1a19cba..e287120bce 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -339,6 +339,7 @@ THREAD_RETURN EmuThread(void *pArg) VideoInitialize.pUpdateInterrupts = &(CommandProcessor::UpdateInterruptsFromVideoPlugin); VideoInitialize.pMemoryBase = Memory::base; VideoInitialize.pKeyPress = Callback_KeyPress; + VideoInitialize.pSetFifoIdle = &(CommandProcessor::SetFifoIdleFromVideoPlugin); VideoInitialize.bWii = _CoreParameter.bWii; VideoInitialize.bUseDualCore = _CoreParameter.bUseDualCore; VideoInitialize.pBBox = &PixelEngine::bbox[0]; diff --git a/Source/Core/Core/Src/HW/CommandProcessor.cpp b/Source/Core/Core/Src/HW/CommandProcessor.cpp index 47cd9b5d76..9bdb7187c1 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.cpp +++ b/Source/Core/Core/Src/HW/CommandProcessor.cpp @@ -152,6 +152,7 @@ u16 m_tokenReg; SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread static u32 fake_GPWatchdogLastToken = 0; +static Common::Event s_fifoIdleEvent; void DoState(PointerWrap &p) { @@ -191,7 +192,8 @@ void IncrementGPWDToken() void WaitForFrameFinish() { while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && (fifo.CPReadWriteDistance > 0) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint)) - Common::YieldCPU(); + s_fifoIdleEvent.MsgWait(); + fake_GPWatchdogLastToken = fifo.Fake_GPWDToken; } @@ -222,11 +224,14 @@ void Init() fifo.CPCmdIdle = 1 ; fifo.CPReadIdle = 1; + s_fifoIdleEvent.Init(); + et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); } void Shutdown() { + s_fifoIdleEvent.Shutdown(); } void Read16(u16& _rReturnValue, const u32 _Address) @@ -377,7 +382,7 @@ void Write16(const u16 _Value, const u32 _Address) // (mb2) We don't sleep here since it could be a perf issue for super monkey ball (yup only this game IIRC) // Touching that game is a no-go so I don't want to take the risk :p while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance > 0 && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint) ) - Common::YieldCPU(); + s_fifoIdleEvent.MsgWait(); } } @@ -428,9 +433,9 @@ void Write16(const u16 _Value, const u32 _Address) // BP interrupt is cleared here - //if (tmpCtrl.CPIntEnable) - if (!m_CPCtrlReg.CPIntEnable && tmpCtrl.CPIntEnable) // raising edge //if (m_CPCtrlReg.CPIntEnable && !tmpCtrl.Hex) // falling edge + // raising edge or falling egde + if ((!m_CPCtrlReg.CPIntEnable && tmpCtrl.CPIntEnable) || (m_CPCtrlReg.CPIntEnable && !tmpCtrl.Hex)) { m_CPStatusReg.Breakpoint = 0; Common::AtomicStore(fifo.bFF_Breakpoint, 0); @@ -608,7 +613,7 @@ void STACKALIGN GatherPipeBursted() INFO_LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached"); // Wait for GPU to catch up while (!(fifo.bFF_BPEnable && fifo.bFF_Breakpoint) && fifo.CPReadWriteDistance > fifo.CPLoWatermark) - Common::YieldCPU(); + s_fifoIdleEvent.MsgWait(); } // check if we are in sync _assert_msg_(COMMANDPROCESSOR, fifo.CPWritePointer == CPeripheralInterface::Fifo_CPUWritePointer, "FIFOs linked but out of sync"); @@ -677,7 +682,6 @@ void CatchUpGPU() // adjust, take care ptr = Memory::GetPointer(fifo.CPReadPointer); INFO_LOG(COMMANDPROCESSOR, "BUFFER LOOP"); - // PanicAlert("loop now"); } } } @@ -734,4 +738,9 @@ void UpdateInterruptsFromVideoPlugin() CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts); } +void SetFifoIdleFromVideoPlugin() +{ + s_fifoIdleEvent.Set(); +} + } // end of namespace CommandProcessor diff --git a/Source/Core/Core/Src/HW/CommandProcessor.h b/Source/Core/Core/Src/HW/CommandProcessor.h index 534238a63e..62b83f771f 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.h +++ b/Source/Core/Core/Src/HW/CommandProcessor.h @@ -81,6 +81,7 @@ void CatchUpGPU(); void GatherPipeBursted(); void UpdateInterrupts(); void UpdateInterruptsFromVideoPlugin(); +void SetFifoIdleFromVideoPlugin(); bool AllowIdleSkipping(); @@ -88,8 +89,8 @@ bool AllowIdleSkipping(); void IncrementGPWDToken(); void WaitForFrameFinish(); -} // end of namespace CommandProcessor +} // namespace CommandProcessor -#endif +#endif // _COMMANDPROCESSOR_H diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 6dcc6181f1..f8f1b49d4b 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -25,20 +25,17 @@ #include "Fifo.h" volatile bool g_bSkipCurrentFrame = false; - +volatile bool g_EFBAccessRequested = false; extern u8* g_pVideoData; -volatile bool g_EFBAccessRequested = false; - -namespace { - +namespace +{ static volatile bool fifoStateRun = false; static u8 *videoBuffer; static Common::Event fifo_exit_event; static Common::CriticalSection s_criticalFifo; // STATE_TO_SAVE static int size = 0; - } // namespace void Fifo_DoState(PointerWrap &p) @@ -78,8 +75,9 @@ u8* FAKE_GetFifoEndPtr() return &videoBuffer[size]; } -void Fifo_SetRendering(bool bEnabled) { - g_bSkipCurrentFrame = !bEnabled; +void Fifo_SetRendering(bool enabled) +{ + g_bSkipCurrentFrame = !enabled; } // Executed from another thread, no the graphics thread! @@ -133,9 +131,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) while (fifoStateRun) { video_initialize.pPeekMessages(); - VideoFifo_CheckEFBAccess(); - VideoFifo_CheckSwapRequest(); s_criticalFifo.Enter(); @@ -145,58 +141,52 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) { Common::AtomicStore(_fifo.CPReadIdle, 0); - while (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance) + do { if (!fifoStateRun) break; + // Get the Read Pointer // Create pointer to video data and send it to the VideoPlugin u32 readPtr = _fifo.CPReadPointer; - u8 *uData = video_initialize.pGetMemoryPointer(readPtr); + // Set distance // if we are on BP mode we must send 32B chunks to Video plugin for BP checking - // TODO (mb2): test & check if MP1/MP2 realy need this now. - if (_fifo.bFF_BPEnable) - { - if (readPtr == _fifo.CPBreakpoint) - { - Common::AtomicStore(_fifo.bFF_Breakpoint, 1); - video_initialize.pUpdateInterrupts(); - break; - } - distToSend = 32; - readPtr += 32; - if ( readPtr >= _fifo.CPEnd) - readPtr = _fifo.CPBase; - } - else + distToSend = _fifo.bFF_BPEnable ? 32 : _fifo.CPReadWriteDistance; + // send 1024B chunk max length to have better control over PeekMessages' period + //distToSend = distToSend > 1024 ? 1024 : distToSend; + + // Get Data based on pointer + u8 *uData = video_initialize.pGetMemoryPointer(readPtr); + + // Check Pointer and move pointer + if ((distToSend + readPtr) >= _fifo.CPEnd) { - distToSend = _fifo.CPReadWriteDistance; - // send 1024B chunk max length to have better control over PeekMessages' period - distToSend = distToSend > 1024 ? 1024 : distToSend; - if ((distToSend + readPtr) >= _fifo.CPEnd) // TODO: better? - { - distToSend =_fifo.CPEnd - readPtr; - readPtr = _fifo.CPBase; - } - else - readPtr += distToSend; + distToSend =_fifo.CPEnd - readPtr; + readPtr = _fifo.CPBase; } + else + readPtr += distToSend; // Execute new instructions found in uData Fifo_SendFifoData(uData, distToSend); + //Check BP Mode - Pokemon XD wants this to be called after the pointer move + if (_fifo.bFF_BPEnable && (readPtr == _fifo.CPBreakpoint)) + { + Common::AtomicStore(_fifo.bFF_Breakpoint, 1); + video_initialize.pUpdateInterrupts(); + } + + // Update CPReadPointer and RWDistance Common::AtomicStore(_fifo.CPReadPointer, readPtr); Common::AtomicAdd(_fifo.CPReadWriteDistance, -distToSend); - video_initialize.pPeekMessages(); - VideoFifo_CheckEFBAccess(); - - VideoFifo_CheckSwapRequest(); - } + } while (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint)); Common::AtomicStore(_fifo.CPReadIdle, 1); + video_initialize.pSetFifoIdle(); } else { diff --git a/Source/PluginSpecs/pluginspecs_video.h b/Source/PluginSpecs/pluginspecs_video.h index 8a55b3ba54..045e12efcb 100644 --- a/Source/PluginSpecs/pluginspecs_video.h +++ b/Source/PluginSpecs/pluginspecs_video.h @@ -21,6 +21,7 @@ typedef unsigned int (*TPeekMessages)(void); typedef void (*TUpdateInterrupts)(void); typedef void (*TUpdateFPSDisplay)(const char* text); // sets the window title typedef void (*TKeyPressed)(int keycode, bool shift, bool control); // sets the window title +typedef void (*TSetFifoIdle)(); enum FieldType { @@ -81,7 +82,7 @@ typedef struct TUpdateInterrupts pUpdateInterrupts; TUpdateFPSDisplay pUpdateFPSDisplay; TKeyPressed pKeyPress; - + TSetFifoIdle pSetFifoIdle; SCPFifoStruct *pCPFifo; void *pMemoryBase; bool bWii;