From a3c258cf9cd46a24d1471f95f5b750456c55c2f0 Mon Sep 17 00:00:00 2001 From: ayuanx Date: Sun, 3 Jan 2010 16:04:40 +0000 Subject: [PATCH] Fixed Issue 1921 This also fixed Ikaruga, not sure whether it could fix Metriod Prime. If not, how about disabling EFB copy? git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4777 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Core/VideoCommon/Src/CommandProcessor.cpp | 21 ++++++++++++-- Source/Core/VideoCommon/Src/Fifo.cpp | 28 +++++++++++-------- Source/Core/VideoCommon/Src/Fifo.h | 1 + 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index ba9a75ed7a..bf88c57e57 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -381,8 +381,11 @@ void Write16(const u16 _Value, const u32 _Address) DEBUG_LOG(COMMANDPROCESSOR, "*********************** GXSetGPFifo very soon? ***********************"); // (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 && !fifo.bFF_Breakpoint) + while (fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint))) + { + Fifo_RunLoop(); s_fifoIdleEvent.MsgWait(); + } } } @@ -411,6 +414,8 @@ void Write16(const u16 _Value, const u32 _Address) Common::AtomicStore(fifo.bFF_Breakpoint, 0); } + Fifo_RunLoop(); + DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | LINK %s | BP %s || Init %s | OvF %s | UndF %s" , fifo.bFF_GPReadEnable ? "ON" : "OFF" @@ -566,7 +571,10 @@ bool AllowIdleSkipping() void WaitForFrameFinish() { while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint))); + { + Fifo_RunLoop(); s_fifoIdleEvent.MsgWait(); + } fake_GPWatchdogLastToken = fifo.Fake_GPWDToken; } @@ -586,6 +594,7 @@ void STACKALIGN GatherPipeBursted() fifo.CPWritePointer += GATHER_PIPE_SIZE; Common::AtomicAdd(fifo.CPReadWriteDistance, GATHER_PIPE_SIZE); + Fifo_RunLoop(); // High watermark overflow handling (hacked way) if (fifo.CPReadWriteDistance > fifo.CPHiWatermark) @@ -608,8 +617,11 @@ void STACKALIGN GatherPipeBursted() INFO_LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark (Hi: 0x%04x, Lo: 0x%04x) reached (RWDistance: 0x%04x)", fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance); // Wait for GPU to catch up - while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && !fifo.bFF_Breakpoint) + while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && fifo.bFF_GPReadEnable && (!fifo.bFF_BPEnable || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint))) + { + Fifo_RunLoop(); s_fifoIdleEvent.MsgWait(); + } } // check if we are in sync _assert_msg_(COMMANDPROCESSOR, fifo.CPWritePointer == *(g_VideoInitialize.Fifo_CPUWritePointer), "FIFOs linked but out of sync"); @@ -649,7 +661,9 @@ void CatchUpGPU() { if ( (fifo.CPReadPointer == fifo.CPBreakpoint) || - (fifo.CPReadPointer == fifo.CPWritePointer) || + //(fifo.CPReadPointer <= fifo.CPBreakpoint && fifo.CPReadPointer + 32 > fifo.CPBreakpoint) || + (fifo.CPReadPointer <= fifo.CPWritePointer && fifo.CPWritePointer < fifo.CPBreakpoint) || + (fifo.CPReadPointer <= fifo.CPWritePointer && fifo.CPReadPointer > fifo.CPBreakpoint) || (fifo.CPReadPointer > fifo.CPBreakpoint && fifo.CPBreakpoint > fifo.CPWritePointer) ) { @@ -711,6 +725,7 @@ void UpdateFifoRegister() dist = (wp - fifo.CPBase) + ((fifo.CPEnd + GATHER_PIPE_SIZE) - rp); Common::AtomicStore(fifo.CPReadWriteDistance, dist); + Fifo_RunLoop(); if (!g_VideoInitialize.bOnThread) CatchUpGPU(); diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 18ce3208e2..d1193ba2e4 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -35,7 +35,7 @@ namespace { static volatile bool fifoStateRun = false; static u8 *videoBuffer; -static Common::Event fifo_exit_event; +static Common::Event fifo_run_event; // STATE_TO_SAVE static int size = 0; } // namespace @@ -56,14 +56,14 @@ void Fifo_DoState(PointerWrap &p) void Fifo_Init() { videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE); - fifo_exit_event.Init(); + fifo_run_event.Init(); fifoStateRun = false; } void Fifo_Shutdown() { - if (fifoStateRun) - PanicAlert("Fifo shutting down while active"); + if (fifoStateRun) PanicAlert("Fifo shutting down while active"); + fifo_run_event.Shutdown(); FreeMemoryPages(videoBuffer, FIFO_SIZE); } @@ -89,10 +89,7 @@ void Fifo_SetRendering(bool enabled) // the loop. Switch to the video thread and investigate. void Fifo_ExitLoop() { - fifoStateRun = false; - - fifo_exit_event.MsgWait(); - fifo_exit_event.Shutdown(); + Fifo_ExitLoopNonBlocking(); } // May be executed from any thread, even the graphics thread. @@ -100,6 +97,12 @@ void Fifo_ExitLoop() void Fifo_ExitLoopNonBlocking() { fifoStateRun = false; + fifo_run_event.Set(); +} + +void Fifo_RunLoop() +{ + fifo_run_event.Set(); } // Description: Fifo_EnterLoop() sends data through this function. @@ -156,7 +159,9 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) // so careful check is required if ( (readPtr == _fifo.CPBreakpoint) || - (readPtr == _fifo.CPWritePointer) || + //(readPtr <= _fifo.CPBreakpoint && readPtr + 32 > _fifo.CPBreakpoint) || + (readPtr <= _fifo.CPWritePointer && _fifo.CPWritePointer < _fifo.CPBreakpoint) || + (readPtr <= _fifo.CPWritePointer && readPtr > _fifo.CPBreakpoint) || (readPtr > _fifo.CPBreakpoint && _fifo.CPBreakpoint > _fifo.CPWritePointer) ) { @@ -200,11 +205,12 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) // leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down. VideoFifo_CheckEFBAccess(); VideoFifo_CheckSwapRequest(); + + CommandProcessor::SetFifoIdleFromVideoPlugin(); } CommandProcessor::SetFifoIdleFromVideoPlugin(); - Common::YieldCPU(); + fifo_run_event.MsgWait(); } - fifo_exit_event.Set(); } diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h index 9243725b79..48b94f3bdd 100644 --- a/Source/Core/VideoCommon/Src/Fifo.h +++ b/Source/Core/VideoCommon/Src/Fifo.h @@ -36,6 +36,7 @@ void Fifo_SendFifoData(u8* _uData, u32 len); void Fifo_EnterLoop(const SVideoInitialize &video_initialize); void Fifo_ExitLoop(); void Fifo_ExitLoopNonBlocking(); +void Fifo_RunLoop(); void Fifo_DoState(PointerWrap &f);