More GPFifo works. PEToken management as I think it should be. Super Monkey Ball Adventures fix (the token check loop was stuck in one JITed block without any Advance() call).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1224 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
memberTwo.mb2 2008-11-20 12:16:51 +00:00
parent ba7f7cd8b7
commit 337ff1f56b
3 changed files with 58 additions and 27 deletions

View File

@ -25,6 +25,10 @@
// - ZTP: seems to use PEfinish only
// - Animal Crossing: PEfinish at start but there's a bug...
// There's tons of HiWmk/LoWmk ping pong -> Another sync fashion?
// - Super Monkey Ball Adventures: PEToken. Oddity: read&check-PEToken-value-loop stays
// in its JITed block (never fall in Advance() until the game-watchdog's stuff).
// That's why we can't let perform the AdvanceCallBack as usual.
// The PEToken is volatile now and in the fifo struct.
// *What I guess (thx to asynchronous DualCore mode):
// PPC have a frame-finish watchdog. Handled by system timming stuff like the decrementer.
@ -144,6 +148,7 @@ int m_bboxbottom;
u16 m_tokenReg;
SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread
static u32 fake_GPWatchdogLastToken = 0;
void DoState(PointerWrap &p)
{
@ -181,15 +186,10 @@ void IncrementGPWDToken()
// Check every FAKE_GP_WATCHDOG_PERIOD if a PE-frame-finish occured
// if not then lock CPUThread until GP finish a frame.
u32 fake_GPWatchdogLastToken = 0;
void WaitForFrameFinish()
{
while (fake_GPWatchdogLastToken == fifo.Fake_GPWDToken && fifo.bFF_GPReadEnable && (fifo.CPReadWriteDistance > 0) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint))
while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && (fifo.CPReadWriteDistance > 0) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint))
;
// oh well, should be safe.
// Assuming: time between 2 GP-frame-finish (ie. increment of fifo.Fake_GPWDToken)
// will be EVER way superior to time between
// "while (g_FAKE_GPWatchdogToken == fifo.Fake_GPWDToken..." and this line. :p
fake_GPWatchdogLastToken = fifo.Fake_GPWDToken;
}
@ -217,9 +217,10 @@ void Init()
fifo.bFF_GPReadEnable = FALSE;
fifo.bFF_GPLinkEnable = FALSE;
fifo.bFF_BPEnable = FALSE;
fifo.PEToken = 0;
// for GP watchdog hack
fifo.Fake_GPWDInterrupt = FALSE;
fifo.Fake_GPWDToken = 0;
fake_GPWatchdogLastToken = 0;
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
}
@ -376,7 +377,7 @@ void Write16(const u16 _Value, const u32 _Address)
// update interrupts
UpdateInterrupts();
LOG(COMMANDPROCESSOR,"write to STATUS_REGISTER : %04x", _Value);
LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value);
}
break;
@ -413,14 +414,16 @@ void Write16(const u16 _Value, const u32 _Address)
}
}/**/
UpdateInterrupts();
LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || CPIntEnable %s"
LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || CPIntEnable %s | OvF %s | UndF %s"
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
, fifo.bFF_GPLinkEnable ? "ON" : "OFF"
, fifo.bFF_BPEnable ? "ON" : "OFF"
, m_CPCtrlReg.CPIntEnable ? "ON" : "OFF"
, m_CPCtrlReg.FifoOverflowIntEnable ? "ON" : "OFF"
, m_CPCtrlReg.FifoUnderflowIntEnable ? "ON" : "OFF"
);
LOG(COMMANDPROCESSOR,"write to CTRL_REGISTER : %04x", _Value);
}
break;
@ -429,12 +432,15 @@ void Write16(const u16 _Value, const u32 _Address)
UCPClearReg tmpClearReg(_Value);
m_CPClearReg.Hex = 0;
LOG(COMMANDPROCESSOR,"write to CLEAR_REGISTER : %04x",_Value);
LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
}
break;
// Fifo Registers
case FIFO_TOKEN_REGISTER: m_tokenReg = _Value; break;
case FIFO_TOKEN_REGISTER:
m_tokenReg = _Value;
LOG(COMMANDPROCESSOR,"write to FIFO_TOKEN_REGISTER : %04x", _Value);
break;
case FIFO_BASE_LO: WriteLow ((u32 &)fifo.CPBase, _Value); fifo.CPBase &= 0xFFFFFFE0; break;
case FIFO_BASE_HI: WriteHigh((u32 &)fifo.CPBase, _Value); fifo.CPBase &= 0xFFFFFFE0; break;
@ -543,6 +549,7 @@ void GatherPipeBursted()
// - CPU can write to fifo
// - disable Underflow interrupt
LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached");
// Wait for GPU to catch up
//while (!(fifo.bFF_BPEnable && fifo.bFF_Breakpoint) && fifo.CPReadWriteDistance > (s32)fifo.CPLoWatermark)
while (fifo.CPReadWriteDistance > fifo.CPLoWatermark)

View File

@ -55,7 +55,6 @@ union UPECtrlReg
// STATE_TO_SAVE
static UPECtrlReg g_ctrlReg;
static u16 g_token = 0;
static bool g_bSignalTokenInterrupt;
static bool g_bSignalFinishInterrupt;
@ -66,7 +65,7 @@ int et_SetFinishOnMainThread;
void DoState(PointerWrap &p)
{
p.Do(g_ctrlReg);
p.Do(g_token);
p.Do(CommandProcessor::fifo.PEToken);
p.Do(g_bSignalTokenInterrupt);
p.Do(g_bSignalFinishInterrupt);
}
@ -78,7 +77,6 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
void Init()
{
g_token = 0;
g_ctrlReg.Hex = 0;
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
@ -93,10 +91,12 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
{
case CTRL_REGISTER:
_uReturnValue = g_ctrlReg.Hex;
LOG(PIXELENGINE,"\t CTRL_REGISTER : %04x", _uReturnValue);
return;
case TOKEN_REG:
_uReturnValue = g_token;
_uReturnValue = CommandProcessor::fifo.PEToken;
LOG(PIXELENGINE,"\t TOKEN_REG : %04x", _uReturnValue);
return;
default:
@ -135,9 +135,10 @@ void Write16(const u16 _iValue, const u32 _iAddress)
break;
case TOKEN_REG:
LOG(PIXELENGINE,"WEIRD: program wrote token: %i",_iValue);
//LOG(PIXELENGINE,"WEIRD: program wrote token: %i",_iValue);
PanicAlert("PIXELENGINE : (w16) WTF? program wrote token: %i",_iValue);
//only the gx pipeline is supposed to be able to write here
g_token = _iValue;
//g_token = _iValue;
break;
}
}
@ -162,15 +163,19 @@ void UpdateInterrupts()
CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_PE_FINISH, false);
}
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate). Cleanup++
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
{
// In the future: schedule callback that does the rest of this function
// This way we will be threadsafe
if (userdata >> 16)
//if (userdata >> 16)
//{
g_bSignalTokenInterrupt = true;
g_token = (u16)(userdata & 0xFFFF);
LOGV(PIXELENGINE, 1, "VIDEO Plugin wrote token: %i", g_token);
_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
LOGV(PIXELENGINE, 1, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
UpdateInterrupts();
//}
//else
// LOGV(PIXELENGINE, 1, "VIDEO Plugin wrote token: %i", CommandProcessor::fifo.PEToken);
}
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
@ -183,9 +188,24 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
// THIS IS EXECUTED FROM VIDEO THREAD
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
{
// TODO?: set-token-value and set-token-INT could be merged since set-token-INT own the token value.
if (_bSetTokenAcknowledge) // set token INT
{
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack since PEToken seems to be a frame-finish too
CoreTiming::ScheduleEvent_Threadsafe(
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
}
else // set token value
{
// we do it directly from videoThread because of
// Super Monkey Ball Advance
#ifdef _WIN32
InterlockedExchange((LONG*)&CommandProcessor::fifo.PEToken, _token);
#else
Common::InterlockedExchange((int*)&CommandProcessor::fifo.PEToken, _token);
#endif
}
}
// SetFinish
// THIS IS EXECUTED FROM VIDEO THREAD

View File

@ -35,13 +35,17 @@ typedef struct
volatile u32 CPReadPointer;
volatile u32 CPBreakpoint;
// Super Monkey Ball Adventure require this.
// Because the read&check-PEToken-loop stays in its JITed block I suppose.
// So no possiblity to ack the Token irq by the scheduler until some sort of PPC watchdog do its mess.
volatile u16 PEToken;
volatile BOOL bFF_GPReadEnable;
volatile BOOL bFF_BPEnable;
volatile BOOL bFF_GPLinkEnable;
volatile BOOL bFF_Breakpoint;
// for GP watchdog hack
volatile BOOL Fake_GPWDInterrupt;
volatile u32 Fake_GPWDToken; // cicular incrementer
} SCPFifoStruct;