Fixed Issue 1711 (a bug that prevents some games from booting)

Thanks to chuvit's help

Added safety check for CFrame::Update

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4759 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
ayuanx
2009-12-31 16:25:12 +00:00
parent d4a1b97ac9
commit 40f4dd30c2
6 changed files with 190 additions and 150 deletions

View File

@ -309,6 +309,8 @@ CFrame::CFrame(wxFrame* parent,
#endif #endif
{ {
m_bControlsCreated = false;
if (ShowLogWindow) SConfig::GetInstance().m_InterfaceLogWindow = true; if (ShowLogWindow) SConfig::GetInstance().m_InterfaceLogWindow = true;
// Give it a console early to show potential messages from this onward // Give it a console early to show potential messages from this onward
@ -461,6 +463,7 @@ CFrame::CFrame(wxFrame* parent,
// ---------- // ----------
// Update controls // Update controls
m_bControlsCreated = true;
UpdateGUI(); UpdateGUI();
//if we are ever going back to optional iso caching: //if we are ever going back to optional iso caching:
@ -477,6 +480,8 @@ CFrame::CFrame(wxFrame* parent,
// Destructor // Destructor
CFrame::~CFrame() CFrame::~CFrame()
{ {
m_bControlsCreated = false;
cdio_free_device_list(drives); cdio_free_device_list(drives);
/* The statbar sample has this so I add this to, but I guess timer will be deleted after /* The statbar sample has this so I add this to, but I guess timer will be deleted after
this anyway */ this anyway */

View File

@ -195,6 +195,7 @@ class CFrame : public wxFrame
bool m_bTabSplit; bool m_bTabSplit;
bool m_bNoDocking; bool m_bNoDocking;
bool m_bModalDialogOpen; bool m_bModalDialogOpen;
bool m_bControlsCreated;
char **drives; char **drives;

View File

@ -915,6 +915,9 @@ void CFrame::OnFrameSkip(wxCommandEvent& event)
// Update the enabled/disabled status // Update the enabled/disabled status
void CFrame::UpdateGUI() void CFrame::UpdateGUI()
{ {
if (!m_bControlsCreated)
return;
// Save status // Save status
bool Initialized = Core::isRunning(); bool Initialized = Core::isRunning();
bool Running = Core::GetState() == Core::CORE_RUN; bool Running = Core::GetState() == Core::CORE_RUN;

View File

@ -83,6 +83,11 @@ namespace CommandProcessor
int et_UpdateInterrupts; int et_UpdateInterrupts;
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
{
UpdateInterrupts((userdata) ? true : false);
}
// 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
@ -151,12 +156,12 @@ void Init()
fake_GPWatchdogLastToken = 0; fake_GPWatchdogLastToken = 0;
memset(&fifo,0,sizeof(fifo)); memset(&fifo,0,sizeof(fifo));
//fifo.CPCmdIdle = 1 ; fifo.CPCmdIdle = 1 ;
fifo.CPReadIdle = 1; fifo.CPReadIdle = 1;
s_fifoIdleEvent.Init(); s_fifoIdleEvent.Init();
// et_UpdateInterrupts = g_VideoInitialize.pRegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); et_UpdateInterrupts = g_VideoInitialize.pRegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
} }
void Shutdown() void Shutdown()
@ -179,14 +184,14 @@ void Read16(u16& _rReturnValue, const u32 _Address)
//m_CPStatusReg.ReadIdle = 1; //m_CPStatusReg.ReadIdle = 1;
//m_CPStatusReg.CommandIdle = 1; //m_CPStatusReg.CommandIdle = 1;
m_CPStatusReg.ReadIdle = fifo.CPReadIdle; // This seems not necessary though //m_CPStatusReg.ReadIdle = fifo.CPReadIdle; // This seems not necessary though
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint; m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
// Clear on Read
UpdateInterrupts(false);
_rReturnValue = m_CPStatusReg.Hex; _rReturnValue = m_CPStatusReg.Hex;
DEBUG_LOG(COMMANDPROCESSOR, "\t iBP %s | fREADIDLE %s | fCMDIDLE %s | iOvF %s | iUndF %s" // Clear on read
UpdateInterrupts(false);
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"
, m_CPStatusReg.ReadIdle ? "ON" : "OFF" , m_CPStatusReg.ReadIdle ? "ON" : "OFF"
, m_CPStatusReg.CommandIdle ? "ON" : "OFF" , m_CPStatusReg.CommandIdle ? "ON" : "OFF"
@ -196,7 +201,10 @@ void Read16(u16& _rReturnValue, const u32 _Address)
return; return;
case CTRL_REGISTER: _rReturnValue = m_CPCtrlReg.Hex; return; case CTRL_REGISTER: _rReturnValue = m_CPCtrlReg.Hex; return;
case CLEAR_REGISTER: _rReturnValue = m_CPClearReg.Hex; return; case CLEAR_REGISTER:
_rReturnValue = m_CPClearReg.Hex;
DEBUG_LOG(COMMANDPROCESSOR, "(r) clear: 0x%04x", _rReturnValue);
return;
case FIFO_TOKEN_REGISTER: _rReturnValue = m_tokenReg; return; case FIFO_TOKEN_REGISTER: _rReturnValue = m_tokenReg; return;
case FIFO_BOUNDING_BOX_LEFT: _rReturnValue = m_bboxleft; return; case FIFO_BOUNDING_BOX_LEFT: _rReturnValue = m_bboxleft; return;
@ -256,32 +264,86 @@ void Read16(u16& _rReturnValue, const u32 _Address)
case FIFO_BP_LO: _rReturnValue = ReadLow (fifo.CPBreakpoint); return; case FIFO_BP_LO: _rReturnValue = ReadLow (fifo.CPBreakpoint); return;
case FIFO_BP_HI: _rReturnValue = ReadHigh(fifo.CPBreakpoint); return; case FIFO_BP_HI: _rReturnValue = ReadHigh(fifo.CPBreakpoint); return;
case CP_PERF0_L: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF0_L: %04x", _rReturnValue); break; // XF counters // AyuanX: Lots of games read the followings (e.g. Mario Power Tennis)
case CP_PERF0_H: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF0_H: %04x", _rReturnValue); break; case XF_RASBUSY_L:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_RASBUSY_L: %04x", _rReturnValue);
return;
case XF_RASBUSY_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_RASBUSY_H: %04x", _rReturnValue);
return;
case CP_PERF1_L: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF1_L: %04x", _rReturnValue); break; case XF_CLKS_L:
case CP_PERF1_H: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF1_H: %04x", _rReturnValue); break; _rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_CLKS_L: %04x", _rReturnValue);
return;
case XF_CLKS_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_CLKS_H: %04x", _rReturnValue);
return;
case CP_PERF2_L: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF2_L: %04x", _rReturnValue); break; case XF_WAIT_IN_L:
case CP_PERF2_H: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF2_H: %04x", _rReturnValue); break; _rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_IN_L: %04x", _rReturnValue);
return;
case XF_WAIT_IN_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_IN_H: %04x", _rReturnValue);
return;
case CP_PERF3_L: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF3_L: %04x", _rReturnValue); break; case XF_WAIT_OUT_L:
case CP_PERF3_H: _rReturnValue = 0; WARN_LOG(COMMANDPROCESSOR, "Read from PERF3_H: %04x", _rReturnValue); break; _rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_OUT_L: %04x", _rReturnValue);
return;
case XF_WAIT_OUT_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_OUT_H: %04x", _rReturnValue);
return;
case VCACHE_METRIC_CHECK_L:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_CHECK_L: %04x", _rReturnValue);
return;
case VCACHE_METRIC_CHECK_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_CHECK_H: %04x", _rReturnValue);
return;
case VCACHE_METRIC_MISS_L:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_MISS_L: %04x", _rReturnValue);
return;
case VCACHE_METRIC_MISS_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_MISS_H: %04x", _rReturnValue);
return;
case VCACHE_METRIC_STALL_L:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_STALL_L: %04x", _rReturnValue);
return;
case VCACHE_METRIC_STALL_H:
_rReturnValue = 0; // TODO: Figure out the true value
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_STALL_H: %04x", _rReturnValue);
return;
case CLKS_PER_VTX_OUT: case CLKS_PER_VTX_OUT:
_rReturnValue = 4; //Number of clocks per vertex.. TODO: Calculate properly _rReturnValue = 4; //Number of clocks per vertex.. TODO: Calculate properly
WARN_LOG(COMMANDPROCESSOR, "Read from CLKS_PER_VTX_OUT: %04x", _rReturnValue); WARN_LOG(COMMANDPROCESSOR, "Read from CLKS_PER_VTX_OUT: %04x", _rReturnValue);
break; return;
//add all the other regs here? are they ever read? //add all the other regs here? are they ever read?
default: default:
_rReturnValue = 0; _rReturnValue = 0;
WARN_LOG(COMMANDPROCESSOR, "(r16) unknown CP reg @ %08x", _Address); WARN_LOG(COMMANDPROCESSOR, "(r16) unknown CP reg @ %08x", _Address);
return;
} }
return; return;
} }
void Write16(const u16 _Value, const u32 _Address) void Write16(const u16 _Value, const u32 _Address)
{ {
bool bUpdate = false;
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address); INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
//Spin until queue is empty - it WILL become empty because this is the only thread //Spin until queue is empty - it WILL become empty because this is the only thread
@ -335,41 +397,17 @@ void Write16(const u16 _Value, const u32 _Address)
case CTRL_REGISTER: case CTRL_REGISTER:
{ {
// TOCHECK (mb2): could BP irq be cleared with w16 to STATUS_REGISTER?
// funny hack: eg in MP1 if we disable the clear breakpoint ability by commenting this block
// the game is of course faster but looks stable too.
// Well, the hack is more stable than the "proper" way actualy :p ... it breaks MP2 when ship lands
// So I let the hack for now.
// Checkmate re-enabled it, so please test
// TODO (mb2): fix this!
UCPCtrlReg tmpCtrl(_Value); UCPCtrlReg tmpCtrl(_Value);
m_CPCtrlReg.Hex = tmpCtrl.Hex; m_CPCtrlReg.Hex = tmpCtrl.Hex;
Common::AtomicStore(fifo.bFF_GPLinkEnable, tmpCtrl.GPLinkEnable); Common::AtomicStore(fifo.bFF_GPLinkEnable, tmpCtrl.GPLinkEnable);
Common::AtomicStore(fifo.bFF_GPReadEnable, tmpCtrl.GPReadEnable); Common::AtomicStore(fifo.bFF_GPReadEnable, tmpCtrl.GPReadEnable);
Common::AtomicStore(fifo.bFF_BPEnable, tmpCtrl.BPEnable);
if (g_VideoInitialize.bOnThread) if (tmpCtrl.BPInit && tmpCtrl.BPEnable && tmpCtrl.GPReadEnable)
{ {
// Instant Breakpoint and Interrupt, since we haven't implemented accurate BP on dual core // Clear old BP and initiate new BP
// Most likely the Read thread has already exceeded BP here, but it seems we are still cool Common::AtomicStore(fifo.bFF_Breakpoint, 0);
if (tmpCtrl.BPEnable && tmpCtrl.CPIntEnable && tmpCtrl.GPReadEnable && tmpCtrl.GPLinkEnable)
{
Common::AtomicStore(fifo.bFF_Breakpoint, 1);
UpdateInterrupts(true);
}
else
{
Common::AtomicStore(fifo.bFF_Breakpoint, 0);
}
}
else
{
// fifo.bFF_BPEnable is only used in single core
Common::AtomicStore(fifo.bFF_BPEnable, tmpCtrl.BPEnable && tmpCtrl.CPIntEnable && tmpCtrl.GPReadEnable && tmpCtrl.GPLinkEnable);
if (!tmpCtrl.BPEnable || !tmpCtrl.CPIntEnable || !tmpCtrl.GPReadEnable || !tmpCtrl.GPLinkEnable)
Common::AtomicStore(fifo.bFF_Breakpoint, 0);
} }
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
@ -385,8 +423,8 @@ void Write16(const u16 _Value, const u32 _Address)
break; break;
case PERF_SELECT: case PERF_SELECT:
// Seems to select which set of perf counters should be exposed. // Seems to select which set of perf registers should be exposed.
WARN_LOG(COMMANDPROCESSOR, "write to PERF_SELECT: %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR, "write to PERF_SELECT: %04x", _Value);
break; break;
case CLEAR_REGISTER: case CLEAR_REGISTER:
@ -404,38 +442,46 @@ void Write16(const u16 _Value, const u32 _Address)
break; break;
case FIFO_BASE_LO: case FIFO_BASE_LO:
// Oh hell, somtimes this value is not aligned with 32B, like New Super Mario Bros. Wii bUpdate = true;
WriteLow ((u32 &)fifo.CPBase, _Value & 0xFFE0); WriteLow ((u32 &)fifo.CPBase, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO : %04x", _Value);
break; break;
case FIFO_BASE_HI: case FIFO_BASE_HI:
bUpdate = true;
WriteHigh((u32 &)fifo.CPBase, _Value); WriteHigh((u32 &)fifo.CPBase, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI : %04x", _Value);
break; break;
case FIFO_END_LO: case FIFO_END_LO:
bUpdate = true;
// Somtimes this value is not aligned with 32B, e.g. New Super Mario Bros. Wii
WriteLow ((u32 &)fifo.CPEnd, _Value & 0xFFE0); WriteLow ((u32 &)fifo.CPEnd, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO : %04x", _Value);
break; break;
case FIFO_END_HI: case FIFO_END_HI:
bUpdate = true;
WriteHigh((u32 &)fifo.CPEnd, _Value); WriteHigh((u32 &)fifo.CPEnd, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI : %04x", _Value);
break; break;
case FIFO_WRITE_POINTER_LO: case FIFO_WRITE_POINTER_LO:
bUpdate = true;
WriteLow ((u32 &)fifo.CPWritePointer, _Value & 0xFFE0); WriteLow ((u32 &)fifo.CPWritePointer, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO : %04x", _Value);
break; break;
case FIFO_WRITE_POINTER_HI: case FIFO_WRITE_POINTER_HI:
bUpdate = true;
WriteHigh((u32 &)fifo.CPWritePointer, _Value); WriteHigh((u32 &)fifo.CPWritePointer, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI : %04x", _Value);
break; break;
case FIFO_READ_POINTER_LO: case FIFO_READ_POINTER_LO:
bUpdate = true;
WriteLow ((u32 &)fifo.CPReadPointer, _Value & 0xFFE0); WriteLow ((u32 &)fifo.CPReadPointer, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO : %04x", _Value);
break; break;
case FIFO_READ_POINTER_HI: case FIFO_READ_POINTER_HI:
bUpdate = true;
WriteHigh((u32 &)fifo.CPReadPointer, _Value); WriteHigh((u32 &)fifo.CPReadPointer, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value);
break; break;
@ -484,14 +530,11 @@ void Write16(const u16 _Value, const u32 _Address)
WARN_LOG(COMMANDPROCESSOR, "(w16) unknown CP reg write %04x @ %08x", _Value, _Address); WARN_LOG(COMMANDPROCESSOR, "(w16) unknown CP reg write %04x @ %08x", _Value, _Address);
} }
// TODO(mb2): better. Check if it help: avoid CPReadPointer overwrites when stupidly done like in Super Monkey Ball if (bUpdate || !g_VideoInitialize.bOnThread) // TOCHECK(mb2): check again if thread safe?
if ((!fifo.bFF_GPReadEnable && fifo.CPReadIdle) || !g_VideoInitialize.bOnThread) // TOCHECK(mb2): check again if thread safe?
{ {
// Disabling this thread synchronization check does boost the speed if (g_VideoInitialize.bOnThread) FifoCriticalEnter(); // This may not be necessary, just for safety
// Hope it is safe to skip this check
// if (g_VideoInitialize.bOnThread) FifoCriticalEnter(); // This may not be necessary, just for safety
UpdateFifoRegister(); UpdateFifoRegister();
// if (g_VideoInitialize.bOnThread) FifoCriticalLeave(); if (g_VideoInitialize.bOnThread) FifoCriticalLeave();
} }
} }
@ -514,7 +557,7 @@ void IncrementGPWDToken()
bool AllowIdleSkipping() bool AllowIdleSkipping()
{ {
return !g_VideoInitialize.bOnThread || (!m_CPCtrlReg.CPIntEnable && !m_CPCtrlReg.BPEnable); return !g_VideoInitialize.bOnThread || !m_CPCtrlReg.BPEnable;
} }
// Check every FAKE_GP_WATCHDOG_PERIOD if a PE-frame-finish occured // Check every FAKE_GP_WATCHDOG_PERIOD if a PE-frame-finish occured
@ -562,7 +605,7 @@ void STACKALIGN GatherPipeBursted()
// - CPU can write to fifo // - CPU can write to fifo
// - disable Underflow interrupt // - disable Underflow interrupt
INFO_LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached"); INFO_LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached, 0x%04X, 0x%04X", fifo.CPReadWriteDistance, fifo.CPLoWatermark);
// Wait for GPU to catch up // Wait for GPU to catch up
while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && !fifo.bFF_Breakpoint) while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && !fifo.bFF_Breakpoint)
s_fifoIdleEvent.MsgWait(); s_fifoIdleEvent.MsgWait();
@ -591,7 +634,7 @@ void STACKALIGN GatherPipeBursted()
void CatchUpGPU() void CatchUpGPU()
{ {
// check if we are able to run this buffer // check if we are able to run this buffer
if (fifo.bFF_GPReadEnable && !fifo.bFF_Breakpoint) if (fifo.bFF_GPReadEnable && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint))
{ {
// HyperIris: Memory_GetPtr is an expensive call, call it less, run faster // HyperIris: Memory_GetPtr is an expensive call, call it less, run faster
u8 *ptr = Memory_GetPtr(fifo.CPReadPointer); u8 *ptr = Memory_GetPtr(fifo.CPReadPointer);
@ -678,18 +721,11 @@ void UpdateInterrupts(bool active)
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, active); g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, active);
} }
/* void UpdateInterruptsFromVideoPlugin(bool active)
void UpdateInterruptsFromVideoPlugin()
{ {
g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, 0); g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, active);
} }
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
{
UpdateInterrupts();
}
*/
void SetFifoIdleFromVideoPlugin() void SetFifoIdleFromVideoPlugin()
{ {
s_fifoIdleEvent.Set(); s_fifoIdleEvent.Set();

View File

@ -36,7 +36,7 @@ enum
STATUS_REGISTER = 0x00, STATUS_REGISTER = 0x00,
CTRL_REGISTER = 0x02, CTRL_REGISTER = 0x02,
CLEAR_REGISTER = 0x04, CLEAR_REGISTER = 0x04,
PERF_SELECT = 0x06, PERF_SELECT = 0x06,
FIFO_TOKEN_REGISTER = 0x0E, FIFO_TOKEN_REGISTER = 0x0E,
FIFO_BOUNDING_BOX_LEFT = 0x10, FIFO_BOUNDING_BOX_LEFT = 0x10,
FIFO_BOUNDING_BOX_RIGHT = 0x12, FIFO_BOUNDING_BOX_RIGHT = 0x12,
@ -58,23 +58,23 @@ enum
FIFO_READ_POINTER_HI = 0x3A, FIFO_READ_POINTER_HI = 0x3A,
FIFO_BP_LO = 0x3C, FIFO_BP_LO = 0x3C,
FIFO_BP_HI = 0x3E, FIFO_BP_HI = 0x3E,
CP_PERF0_L = 0x40, XF_RASBUSY_L = 0x40,
CP_PERF0_H = 0x42, XF_RASBUSY_H = 0x42,
CP_PERF1_L = 0x44, XF_CLKS_L = 0x44,
CP_PERF1_H = 0x46, XF_CLKS_H = 0x46,
CP_PERF2_L = 0x48, XF_WAIT_IN_L = 0x48,
CP_PERF2_H = 0x4a, XF_WAIT_IN_H = 0x4a,
CP_PERF3_L = 0x4c, XF_WAIT_OUT_L = 0x4c,
CP_PERF3_H = 0x4e, XF_WAIT_OUT_H = 0x4e,
VCACHE_METRIC_CHECK_LO = 0x50, VCACHE_METRIC_CHECK_L = 0x50,
VCACHE_METRIC_CHECK_HI = 0x52, VCACHE_METRIC_CHECK_H = 0x52,
VCACHE_METRIC_MISS_LO = 0x54, VCACHE_METRIC_MISS_L = 0x54,
VCACHE_METRIC_MISS_HI = 0x56, VCACHE_METRIC_MISS_H = 0x56,
VCACHE_METRIC_STALL_LO = 0x58, VCACHE_METRIC_STALL_L = 0x58,
VCACHE_METRIC_STALL_HI = 0x5A, VCACHE_METRIC_STALL_H = 0x5A,
CLKS_PER_VTX_IN0 = 0x60, CLKS_PER_VTX_IN_L = 0x60,
CLKS_PER_VTX_IN1 = 0x62, CLKS_PER_VTX_IN_H = 0x62,
CLKS_PER_VTX_OUT = 0x64, CLKS_PER_VTX_OUT = 0x64,
}; };
enum enum
@ -106,11 +106,11 @@ union UCPCtrlReg
struct struct
{ {
unsigned GPReadEnable : 1; unsigned GPReadEnable : 1;
unsigned CPIntEnable : 1; unsigned BPEnable : 1;
unsigned FifoOverflowIntEnable : 1; unsigned FifoOverflowIntEnable : 1;
unsigned FifoUnderflowIntEnable : 1; unsigned FifoUnderflowIntEnable : 1;
unsigned GPLinkEnable : 1; unsigned GPLinkEnable : 1;
unsigned BPEnable : 1; unsigned BPInit : 1;
unsigned : 10; unsigned : 10;
}; };
u16 Hex; u16 Hex;
@ -149,7 +149,7 @@ void CatchUpGPU();
void GatherPipeBursted(); void GatherPipeBursted();
void UpdateFifoRegister(); void UpdateFifoRegister();
void UpdateInterrupts(bool active); void UpdateInterrupts(bool active);
//void UpdateInterruptsFromVideoPlugin(); void UpdateInterruptsFromVideoPlugin(bool active);
void SetFifoIdleFromVideoPlugin(); void SetFifoIdleFromVideoPlugin();
bool AllowIdleSkipping(); bool AllowIdleSkipping();

View File

@ -138,78 +138,73 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
VideoFifo_CheckSwapRequest(); VideoFifo_CheckSwapRequest();
// check if we are able to run this buffer // check if we are able to run this buffer
if (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance && !_fifo.bFF_Breakpoint) while (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint))
{ {
Common::AtomicStore(_fifo.CPReadIdle, 0); if (!fifoStateRun)
break;
while (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance) CommandProcessor::FifoCriticalEnter();
// Create pointer to video data and send it to the VideoPlugin
u32 readPtr = _fifo.CPReadPointer;
u8 *uData = video_initialize.pGetMemoryPointer(readPtr);
// If we are in BP mode we only send 32B chunks to Video plugin for BP checking
if (_fifo.bFF_BPEnable)
{ {
if (!fifoStateRun) // Sometimes we have already exceeded the BP even before it is set
break; // so careful check is required
if (
// Create pointer to video data and send it to the VideoPlugin (readPtr == _fifo.CPBreakpoint) ||
u32 readPtr = _fifo.CPReadPointer; (readPtr == _fifo.CPWritePointer) ||
u8 *uData = video_initialize.pGetMemoryPointer(readPtr); (_fifo.CPWritePointer < _fifo.CPBreakpoint)
)
CommandProcessor::FifoCriticalEnter();
// It looks like even in BP mode, we still can send all the chunks we have
/*
// 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);
{ CommandProcessor::UpdateInterruptsFromVideoPlugin(true);
Common::AtomicStore(_fifo.bFF_Breakpoint, 1); break;
CommandProcessor::UpdateInterruptsFromVideoPlugin(); }
break;
}
distToSend = 32; distToSend = 32;
if ( readPtr >= _fifo.CPEnd) if ( readPtr >= _fifo.CPEnd)
readPtr = _fifo.CPBase; readPtr = _fifo.CPBase;
else else
readPtr += 32; readPtr += 32;
}
else
{
distToSend = _fifo.CPReadWriteDistance;
// send 1024B chunk max length to have better control over PeekMessages' period
distToSend = distToSend > 1024 ? 1024 : distToSend;
// add 32 bytes because the cp end points to the start of the last 32 byte chunk
if ((distToSend + readPtr) >= (_fifo.CPEnd + 32)) // TODO: better?
{
distToSend =(_fifo.CPEnd + 32) - readPtr;
readPtr = _fifo.CPBase;
} }
else else
*/ readPtr += distToSend;
{
distToSend = _fifo.CPReadWriteDistance;
// send 1024B chunk max length to have better control over PeekMessages' period
distToSend = distToSend > 1024 ? 1024 : distToSend;
// add 32 bytes because the cp end points to the start of the last 32 byte chunk
if ((distToSend + readPtr) >= (_fifo.CPEnd + 32)) // TODO: better?
{
distToSend =(_fifo.CPEnd + 32) - readPtr;
readPtr = _fifo.CPBase;
}
else
readPtr += distToSend;
}
// Execute new instructions found in uData
Fifo_SendFifoData(uData, distToSend);
Common::AtomicStore(_fifo.CPReadPointer, readPtr);
Common::AtomicAdd(_fifo.CPReadWriteDistance, -distToSend);
CommandProcessor::FifoCriticalLeave();
// Those two are pretty important and must be called in the FIFO Loop.
// If we don't, s_swapRequested (OGL only) or s_efbAccessRequested won't be set to false
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down.
VideoFifo_CheckEFBAccess();
VideoFifo_CheckSwapRequest();
} }
Common::AtomicStore(_fifo.CPReadIdle, 1);
CommandProcessor::SetFifoIdleFromVideoPlugin(); // Execute new instructions found in uData
Fifo_SendFifoData(uData, distToSend);
Common::AtomicStore(_fifo.CPReadPointer, readPtr);
Common::AtomicAdd(_fifo.CPReadWriteDistance, -distToSend);
CommandProcessor::FifoCriticalLeave();
// Those two are pretty important and must be called in the FIFO Loop.
// If we don't, s_swapRequested (OGL only) or s_efbAccessRequested won't be set to false
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down.
VideoFifo_CheckEFBAccess();
VideoFifo_CheckSwapRequest();
CommandProcessor::SetFifoIdleFromVideoPlugin();
} }
else
{ Common::YieldCPU();
Common::YieldCPU();
}
} }
fifo_exit_event.Set(); fifo_exit_event.Set();
} }