This commit fix games hanging because of my prior Revision c2e6fdf09f

The external exceptions in dolphin are checking frequently but is different to real HW, so sometime the game is in a loop checking GPU STATUS, the exceptions doesn't checked, and the game hang.\
For solve this I need a trick: still waiting for the exception handler be linked but if CommandProcecsor is reading the GPStatus, resume this.

This fixed "TimeSplitters: Future Perfect" broken in the Revision c2e6fdf09f and surely others games.
This commit is contained in:
marcosvitali 2012-03-09 18:58:23 -03:00
parent 41652d6b1f
commit 104603467b
3 changed files with 16 additions and 9 deletions

View File

@ -574,7 +574,7 @@ void ProcessFifoAllDistance()
if (IsOnThread()) if (IsOnThread())
{ {
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
fifo.CPReadWriteDistance && !AtBreakpoint()) fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
Common::YieldCPU(); Common::YieldCPU();
} }
bProcessFifoAllDistance = false; bProcessFifoAllDistance = false;
@ -597,10 +597,12 @@ void SetCpStatusRegister()
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint; m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
m_CPStatusReg.ReadIdle = (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ; m_CPStatusReg.ReadIdle = (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ;
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance || (IsOnThread() && PixelEngine::WaitingForPEInterrupt()); m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance;
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark; m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark; m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
PixelEngine::ResumeWaitingForPEInterrupt();
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex); INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s" DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
, m_CPStatusReg.Breakpoint ? "ON" : "OFF" , m_CPStatusReg.Breakpoint ? "ON" : "OFF"
@ -609,6 +611,8 @@ void SetCpStatusRegister()
, m_CPStatusReg.OverflowHiWatermark ? "ON" : "OFF" , m_CPStatusReg.OverflowHiWatermark ? "ON" : "OFF"
, m_CPStatusReg.UnderflowLoWatermark ? "ON" : "OFF" , m_CPStatusReg.UnderflowLoWatermark ? "ON" : "OFF"
); );
} }
void SetCpControlRegister() void SetCpControlRegister()

View File

@ -356,22 +356,16 @@ void UpdateInterrupts()
void UpdateTokenInterrupt(bool active) void UpdateTokenInterrupt(bool active)
{ {
if(interruptSetToken != active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active); ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
interruptSetToken = active; interruptSetToken = active;
}
} }
void UpdateFinishInterrupt(bool active) void UpdateFinishInterrupt(bool active)
{ {
if(interruptSetFinish != active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active); ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
interruptSetFinish = active; interruptSetFinish = active;
if (active) if (active)
State::ProcessRequestedStates(0); State::ProcessRequestedStates(0);
}
} }
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate). // TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
@ -473,4 +467,12 @@ bool WaitingForPEInterrupt()
{ {
return CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken; return CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken;
} }
void ResumeWaitingForPEInterrupt()
{
interruptSetFinish = false;
interruptSetToken = false;
CommandProcessor::interruptFinishWaiting = false;
CommandProcessor::interruptTokenWaiting = false;
}
} // end of namespace PixelEngine } // end of namespace PixelEngine

View File

@ -81,6 +81,7 @@ void SetFinish(void);
void ResetSetFinish(void); void ResetSetFinish(void);
void ResetSetToken(void); void ResetSetToken(void);
bool WaitingForPEInterrupt(); bool WaitingForPEInterrupt();
void ResumeWaitingForPEInterrupt();
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it. // Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
extern u16 bbox[4]; extern u16 bbox[4];