I've observed that "FIFO is overflown by GatherPipe" is not real overflow.

Really that happens because the fifo.CPReadWriteDistance is negative.
Example: CPReadWriteDistance: -864 CPEnd: 10092672 fifo.CPBase: 9568416
In SMG this is because  PI_FIFO_RESET is writing and after fifo.CPReadWriteDistance will be setted to 0.
To Prevent that, I've Implemented AbortFrame function in the CommmandProcessor. It should fix overflown because of that. 
Note: There is other issue (Issue 2846) where the fifo.CPReadWriteDistance is negative too but the effect is different.
I'm working to solve this.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6083 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Marcos Vitali 2010-08-10 07:25:35 +00:00
parent 2b45e87b3e
commit 3b7a6ce336
12 changed files with 59 additions and 2 deletions

View File

@ -39,6 +39,7 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
Video_GatherPipeBursted = 0;
Video_WaitForFrameFinish = 0;
Video_IsFifoBusy = 0;
Video_AbortFrame = 0;
Video_Prepare = reinterpret_cast<TVideo_Prepare>
(LoadSymbol("Video_Prepare"));
@ -74,6 +75,8 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
(LoadSymbol("Video_WaitForFrameFinish"));
Video_IsFifoBusy = reinterpret_cast<TVideo_IsFifoBusy>
(LoadSymbol("Video_IsFifoBusy"));
Video_AbortFrame = reinterpret_cast<TVideo_AbortFrame>
(LoadSymbol("Video_AbortFrame"));
if ((Video_Prepare != 0) &&
(Video_BeginField != 0) &&
(Video_EndField != 0) &&
@ -91,7 +94,8 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
(Video_PixelEngineWrite32 != 0) &&
(Video_GatherPipeBursted != 0) &&
(Video_WaitForFrameFinish != 0) &&
(Video_IsFifoBusy != 0))
(Video_IsFifoBusy != 0) &&
(Video_AbortFrame != 0))
validVideo = true;
}

View File

@ -40,6 +40,7 @@ typedef void (__cdecl* TVideo_Write32)(const u32 _Data, const u32 _Address);
typedef void (__cdecl* TVideo_GatherPipeBursted)();
typedef void (__cdecl* TVideo_WaitForFrameFinish)();
typedef bool (__cdecl* TVideo_IsFifoBusy)();
typedef void (__cdecl* TVideo_AbortFrame)();
class PluginVideo : public CPlugin
{
@ -68,6 +69,7 @@ public:
TVideo_GatherPipeBursted Video_GatherPipeBursted;
TVideo_WaitForFrameFinish Video_WaitForFrameFinish;
TVideo_IsFifoBusy Video_IsFifoBusy;
TVideo_AbortFrame Video_AbortFrame;
private:
bool validVideo;
};

View File

@ -24,7 +24,7 @@
#include "../CoreTiming.h"
#include "ProcessorInterface.h"
#include "GPFifo.h"
#include "../PluginManager.h"
namespace ProcessorInterface
{
@ -181,6 +181,8 @@ void Write32(const u32 _uValue, const u32 _iAddress)
break;
case PI_FIFO_RESET:
//Abort the actual frame
CPluginManager::GetInstance().GetVideo()->Video_AbortFrame();
//Fifo_CPUWritePointer = Fifo_CPUBase; ??
//PanicAlert("Unknown write to PI_FIFO_RESET (%08x)", _uValue);
WARN_LOG(PROCESSORINTERFACE, "Fifo reset (%08x)", _uValue);

View File

@ -701,4 +701,18 @@ void SetFifoIdleFromVideoPlugin()
s_fifoIdleEvent.Set();
}
// This is called by the ProcessorInterface when PI_FIFO_RESET is writed,
// the general idea is abort all commands in the FIFO.
// This prevent Negative fifo.CPReadWriteDistance because when PI_FIFO_RESET happens
// the fifo.CPReadWriteDistance is writed to 0
void AbortFrame()
{
Fifo_SetRendering(false);
while(!fifo.CPCmdIdle)
Common::YieldCPU();
Fifo_SetRendering(true);
PixelEngine::ResetSetToken();
PixelEngine::ResetSetFinish();
}
} // end of namespace CommandProcessor

View File

@ -162,6 +162,7 @@ void WaitForFrameFinish();
void FifoCriticalEnter();
void FifoCriticalLeave();
void AbortFrame();
} // namespace CommandProcessor
#endif // _COMMANDPROCESSOR_H

View File

@ -393,4 +393,16 @@ void ResetSetFinish()
}
}
void ResetSetToken()
{
if (g_bSignalTokenInterrupt)
{
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false);
g_bSignalTokenInterrupt = false;
}else
{
g_VideoInitialize.pRemoveEvent(et_SetTokenOnMainThread);
}
}
} // end of namespace PixelEngine

View File

@ -68,6 +68,7 @@ void Write32(const u32 _iValue, const u32 _iAddress);
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish(void);
void ResetSetFinish(void);
void ResetSetToken(void);
bool AllowIdleSkipping();
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.

View File

@ -189,5 +189,7 @@ EXPORT void CALL Video_WaitForFrameFinish(void);
//
EXPORT bool CALL Video_IsFifoBusy(void);
EXPORT void CALL Video_AbortFrame(void);
#include "ExportEpilog.h"
#endif

View File

@ -453,3 +453,8 @@ bool Video_IsFifoBusy(void)
{
return CommandProcessor::isFifoBusy;
}
void Video_AbortFrame(void)
{
CommandProcessor::AbortFrame();
}

View File

@ -479,3 +479,8 @@ bool Video_IsFifoBusy(void)
{
return CommandProcessor::isFifoBusy;
}
void Video_AbortFrame(void)
{
CommandProcessor::AbortFrame();
}

View File

@ -510,3 +510,8 @@ bool Video_IsFifoBusy(void)
{
return CommandProcessor::isFifoBusy;
}
void Video_AbortFrame(void)
{
CommandProcessor::AbortFrame();
}

View File

@ -220,3 +220,7 @@ bool Video_IsFifoBusy(void)
{
return false;
}
void Video_AbortFrame(void)
{
}