Paused the video thread while a save state was being created or loaded. Performed the save state operation after the fifo became idle. Saved the interrupt status of the video thread into the save state. This helps stabilise the save states in dual core mode in games like Super Mario Galaxy.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7112 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
90bae5d57f
commit
855f97841d
|
@ -88,6 +88,7 @@ public:
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
virtual void DoState(PointerWrap &p) = 0;
|
virtual void DoState(PointerWrap &p) = 0;
|
||||||
|
virtual void RunLoop(bool enable) = 0;
|
||||||
|
|
||||||
virtual std::string GetName() = 0;
|
virtual std::string GetName() = 0;
|
||||||
|
|
||||||
|
@ -127,6 +128,7 @@ extern VideoBackend* g_video_backend;
|
||||||
class VideoBackendHLE : public VideoBackend
|
class VideoBackendHLE : public VideoBackend
|
||||||
{
|
{
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
void RunLoop(bool enable);
|
||||||
|
|
||||||
void EmuStateChange(EMUSTATE_CHANGE);
|
void EmuStateChange(EMUSTATE_CHANGE);
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,8 @@ void DoState(PointerWrap &p)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Begin with video plugin, so that it gets a chance to clear it's caches and writeback modified things to RAM
|
// Begin with video plugin, so that it gets a chance to clear it's caches and writeback modified things to RAM
|
||||||
|
// Pause the video thread in multi-threaded mode
|
||||||
|
g_video_backend->RunLoop(false);
|
||||||
g_video_backend->DoState(p);
|
g_video_backend->DoState(p);
|
||||||
|
|
||||||
if (Core::g_CoreStartupParameter.bWii)
|
if (Core::g_CoreStartupParameter.bWii)
|
||||||
|
@ -96,6 +98,9 @@ void DoState(PointerWrap &p)
|
||||||
PowerPC::DoState(p);
|
PowerPC::DoState(p);
|
||||||
HW::DoState(p);
|
HW::DoState(p);
|
||||||
CoreTiming::DoState(p);
|
CoreTiming::DoState(p);
|
||||||
|
|
||||||
|
// Resume the video thread
|
||||||
|
g_video_backend->RunLoop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadBufferStateCallback(u64 userdata, int cyclesLate)
|
void LoadBufferStateCallback(u64 userdata, int cyclesLate)
|
||||||
|
|
|
@ -87,19 +87,8 @@
|
||||||
namespace CommandProcessor
|
namespace CommandProcessor
|
||||||
{
|
{
|
||||||
|
|
||||||
bool IsOnThread()
|
|
||||||
{
|
|
||||||
return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
int et_UpdateInterrupts;
|
int et_UpdateInterrupts;
|
||||||
|
|
||||||
|
|
||||||
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
UpdateInterrupts(userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for 1002 verts, breakpoint there, see why next draw is flushed
|
// look for 1002 verts, breakpoint there, see why next draw is flushed
|
||||||
// TODO(ector): Warn on bbox read/write
|
// TODO(ector): Warn on bbox read/write
|
||||||
|
|
||||||
|
@ -109,8 +98,6 @@ UCPStatusReg m_CPStatusReg;
|
||||||
UCPCtrlReg m_CPCtrlReg;
|
UCPCtrlReg m_CPCtrlReg;
|
||||||
UCPClearReg m_CPClearReg;
|
UCPClearReg m_CPClearReg;
|
||||||
|
|
||||||
u32 HiWatermark_Tighter;
|
|
||||||
|
|
||||||
int m_bboxleft;
|
int m_bboxleft;
|
||||||
int m_bboxtop;
|
int m_bboxtop;
|
||||||
int m_bboxright;
|
int m_bboxright;
|
||||||
|
@ -120,7 +107,7 @@ u16 m_tokenReg;
|
||||||
static u32 fake_GPWatchdogLastToken = 0;
|
static u32 fake_GPWatchdogLastToken = 0;
|
||||||
static Common::EventEx s_fifoIdleEvent;
|
static Common::EventEx s_fifoIdleEvent;
|
||||||
static Common::CriticalSection sFifoCritical;
|
static Common::CriticalSection sFifoCritical;
|
||||||
static bool bProcessFifoToLoWatemark = false;
|
static bool bProcessFifoToLoWatermark = false;
|
||||||
static bool bProcessFifoAllDistance = false;
|
static bool bProcessFifoAllDistance = false;
|
||||||
|
|
||||||
volatile bool isFifoBusy = false; //This state is changed when the FIFO is processing data.
|
volatile bool isFifoBusy = false; //This state is changed when the FIFO is processing data.
|
||||||
|
@ -130,6 +117,16 @@ volatile bool interruptTokenWaiting = false;
|
||||||
volatile bool interruptFinishWaiting = false;
|
volatile bool interruptFinishWaiting = false;
|
||||||
volatile bool OnOverflow = false;
|
volatile bool OnOverflow = false;
|
||||||
|
|
||||||
|
bool IsOnThread()
|
||||||
|
{
|
||||||
|
return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
UpdateInterrupts(userdata);
|
||||||
|
}
|
||||||
|
|
||||||
void FifoCriticalEnter()
|
void FifoCriticalEnter()
|
||||||
{
|
{
|
||||||
sFifoCritical.Enter();
|
sFifoCritical.Enter();
|
||||||
|
@ -144,14 +141,23 @@ void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
p.Do(m_CPStatusReg);
|
p.Do(m_CPStatusReg);
|
||||||
p.Do(m_CPCtrlReg);
|
p.Do(m_CPCtrlReg);
|
||||||
//p.Do(m_CPClearReg);
|
p.Do(m_CPClearReg);
|
||||||
p.Do(m_bboxleft);
|
p.Do(m_bboxleft);
|
||||||
p.Do(m_bboxtop);
|
p.Do(m_bboxtop);
|
||||||
p.Do(m_bboxright);
|
p.Do(m_bboxright);
|
||||||
p.Do(m_bboxbottom);
|
p.Do(m_bboxbottom);
|
||||||
p.Do(m_tokenReg);
|
p.Do(m_tokenReg);
|
||||||
p.Do(fifo);
|
p.Do(fifo);
|
||||||
p.Do(HiWatermark_Tighter);
|
|
||||||
|
p.Do(bProcessFifoToLoWatermark);
|
||||||
|
p.Do(bProcessFifoAllDistance);
|
||||||
|
|
||||||
|
p.Do(isFifoBusy);
|
||||||
|
p.Do(interruptSet);
|
||||||
|
p.Do(interruptWaiting);
|
||||||
|
p.Do(interruptTokenWaiting);
|
||||||
|
p.Do(interruptFinishWaiting);
|
||||||
|
p.Do(OnOverflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
//inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;}
|
//inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;}
|
||||||
|
@ -478,8 +484,8 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
ProcessorInterface::Fifo_CPUEnd = fifo.CPEnd;
|
ProcessorInterface::Fifo_CPUEnd = fifo.CPEnd;
|
||||||
}
|
}
|
||||||
// If overflown happens process the fifo to LoWatemark
|
// If overflown happens process the fifo to LoWatemark
|
||||||
if (bProcessFifoToLoWatemark)
|
if (bProcessFifoToLoWatermark)
|
||||||
ProcessFifoToLoWatemark();
|
ProcessFifoToLoWatermark();
|
||||||
|
|
||||||
|
|
||||||
INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value);
|
INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value);
|
||||||
|
@ -501,7 +507,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
if (IsOnThread())
|
if (IsOnThread())
|
||||||
{
|
{
|
||||||
if (!tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow)
|
if (!tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow)
|
||||||
bProcessFifoToLoWatemark = true;
|
bProcessFifoToLoWatermark = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -890,7 +896,7 @@ void SetStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessFifoToLoWatemark()
|
void ProcessFifoToLoWatermark()
|
||||||
{
|
{
|
||||||
if (IsOnThread())
|
if (IsOnThread())
|
||||||
{
|
{
|
||||||
|
@ -898,7 +904,7 @@ void ProcessFifoToLoWatemark()
|
||||||
fifo.CPReadWriteDistance > fifo.CPLoWatermark && !AtBreakpoint())
|
fifo.CPReadWriteDistance > fifo.CPLoWatermark && !AtBreakpoint())
|
||||||
Common::YieldCPU();
|
Common::YieldCPU();
|
||||||
}
|
}
|
||||||
bProcessFifoToLoWatemark = false;
|
bProcessFifoToLoWatermark = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessFifoAllDistance()
|
void ProcessFifoAllDistance()
|
||||||
|
|
|
@ -171,7 +171,7 @@ void FifoCriticalEnter();
|
||||||
void FifoCriticalLeave();
|
void FifoCriticalLeave();
|
||||||
|
|
||||||
void SetOverflowStatusFromGatherPipe();
|
void SetOverflowStatusFromGatherPipe();
|
||||||
void ProcessFifoToLoWatemark();
|
void ProcessFifoToLoWatermark();
|
||||||
void ProcessFifoAllDistance();
|
void ProcessFifoAllDistance();
|
||||||
void ProcessFifoEvents();
|
void ProcessFifoEvents();
|
||||||
void AbortFrame();
|
void AbortFrame();
|
||||||
|
|
|
@ -194,8 +194,8 @@ void Fifo_EnterLoop()
|
||||||
while (!EmuRunning)
|
while (!EmuRunning)
|
||||||
{
|
{
|
||||||
g_video_backend->PeekMessages();
|
g_video_backend->PeekMessages();
|
||||||
VideoFifo_CheckAsyncRequest();
|
VideoFifo_CheckStateRequest();
|
||||||
Common::SleepCurrentThread(10);
|
Common::SleepCurrentThread(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,5 +44,6 @@ void Fifo_SetRendering(bool bEnabled);
|
||||||
|
|
||||||
// Implemented by the Video Plugin
|
// Implemented by the Video Plugin
|
||||||
void VideoFifo_CheckAsyncRequest();
|
void VideoFifo_CheckAsyncRequest();
|
||||||
|
void VideoFifo_CheckStateRequest();
|
||||||
|
|
||||||
#endif // _FIFO_H
|
#endif // _FIFO_H
|
||||||
|
|
|
@ -179,7 +179,8 @@ static volatile struct
|
||||||
|
|
||||||
// Depending on the threading mode (DC/SC) this can be called
|
// Depending on the threading mode (DC/SC) this can be called
|
||||||
// from either the GPU thread or the CPU thread
|
// from either the GPU thread or the CPU thread
|
||||||
static void check_DoState() {
|
void VideoFifo_CheckStateRequest()
|
||||||
|
{
|
||||||
if (Common::AtomicLoadAcquire(s_doStateRequested))
|
if (Common::AtomicLoadAcquire(s_doStateRequested))
|
||||||
{
|
{
|
||||||
// Clear all caches that touch RAM
|
// Clear all caches that touch RAM
|
||||||
|
@ -215,14 +216,18 @@ void VideoBackendHLE::DoState(PointerWrap& p)
|
||||||
Common::YieldCPU();
|
Common::YieldCPU();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
check_DoState();
|
VideoFifo_CheckStateRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoBackendHLE::RunLoop(bool enable)
|
||||||
|
{
|
||||||
|
VideoCommon_RunLoop(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoFifo_CheckAsyncRequest()
|
void VideoFifo_CheckAsyncRequest()
|
||||||
{
|
{
|
||||||
VideoFifo_CheckSwapRequest();
|
VideoFifo_CheckSwapRequest();
|
||||||
VideoFifo_CheckEFBAccess();
|
VideoFifo_CheckEFBAccess();
|
||||||
check_DoState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackend::Video_GatherPipeBursted()
|
void VideoBackend::Video_GatherPipeBursted()
|
||||||
|
|
|
@ -55,3 +55,8 @@ void VideoCommon_DoState(PointerWrap &p)
|
||||||
DoState(p);
|
DoState(p);
|
||||||
//TODO: search for more data that should be saved and add it here
|
//TODO: search for more data that should be saved and add it here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoCommon_RunLoop(bool enable)
|
||||||
|
{
|
||||||
|
Fifo_RunLoop(enable);
|
||||||
|
}
|
||||||
|
|
|
@ -22,5 +22,6 @@
|
||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
|
|
||||||
void VideoCommon_DoState(PointerWrap &p);
|
void VideoCommon_DoState(PointerWrap &p);
|
||||||
|
void VideoCommon_RunLoop(bool enable);
|
||||||
|
|
||||||
#endif // _VIDEOSTATE_H
|
#endif // _VIDEOSTATE_H
|
||||||
|
|
Loading…
Reference in New Issue