More CP/GPFifo work. Fix Super Monkey Ball SC/DC. SMB force us to hack CP differently: CPU really thinks the fifo is always empty and on idle now.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1242 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
145f80fc00
commit
36bf2fedf6
|
@ -29,6 +29,8 @@
|
||||||
// in its JITed block (never fall in Advance() until the game-watchdog's stuff).
|
// 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.
|
// That's why we can't let perform the AdvanceCallBack as usual.
|
||||||
// The PEToken is volatile now and in the fifo struct.
|
// The PEToken is volatile now and in the fifo struct.
|
||||||
|
// - Super Monkey Ball: PEFinish. This game has the lamest way to deal with fifo sync for our MT's stuff.
|
||||||
|
// A hack is mandatory. DONE and should be ok for other games.
|
||||||
|
|
||||||
// *What I guess (thx to asynchronous DualCore mode):
|
// *What I guess (thx to asynchronous DualCore mode):
|
||||||
// PPC have a frame-finish watchdog. Handled by system timming stuff like the decrementer.
|
// PPC have a frame-finish watchdog. Handled by system timming stuff like the decrementer.
|
||||||
|
@ -167,8 +169,10 @@ void DoState(PointerWrap &p)
|
||||||
void UpdateFifoRegister();
|
void UpdateFifoRegister();
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
|
|
||||||
inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;}
|
//inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;}
|
||||||
inline void WriteHigh(u32& _reg, u16 highbits) {_reg = (_reg & 0x0000FFFF) | ((u32)highbits << 16);}
|
//inline void WriteHigh(u32& _reg, u16 highbits) {_reg = (_reg & 0x0000FFFF) | ((u32)highbits << 16);}
|
||||||
|
inline void WriteLow (volatile u32& _reg, u16 lowbits) {InterlockedExchange((LONG*)&_reg,(_reg & 0xFFFF0000) | lowbits);}
|
||||||
|
inline void WriteHigh(volatile u32& _reg, u16 highbits) {InterlockedExchange((LONG*)&_reg,(_reg & 0x0000FFFF) | ((u32)highbits << 16));}
|
||||||
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
|
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
|
||||||
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
|
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
|
||||||
|
|
||||||
|
@ -214,13 +218,11 @@ void Init()
|
||||||
|
|
||||||
m_tokenReg = 0;
|
m_tokenReg = 0;
|
||||||
|
|
||||||
fifo.bFF_GPReadEnable = FALSE;
|
|
||||||
fifo.bFF_GPLinkEnable = FALSE;
|
|
||||||
fifo.bFF_BPEnable = FALSE;
|
|
||||||
fifo.PEToken = 0;
|
|
||||||
// for GP watchdog hack
|
|
||||||
fifo.Fake_GPWDToken = 0;
|
|
||||||
fake_GPWatchdogLastToken = 0;
|
fake_GPWatchdogLastToken = 0;
|
||||||
|
memset(&fifo,0,sizeof(fifo));
|
||||||
|
fifo.CPCmdIdle = 1 ;
|
||||||
|
fifo.CPReadIdle = 1;
|
||||||
|
|
||||||
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -237,7 +239,25 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
||||||
LOGV(COMMANDPROCESSOR, 1, "(r): 0x%08x", _Address);
|
LOGV(COMMANDPROCESSOR, 1, "(r): 0x%08x", _Address);
|
||||||
switch (_Address & 0xFFF)
|
switch (_Address & 0xFFF)
|
||||||
{
|
{
|
||||||
case STATUS_REGISTER: _rReturnValue = m_CPStatusReg.Hex; return;
|
case STATUS_REGISTER:
|
||||||
|
//TODO?: if really needed
|
||||||
|
//m_CPStatusReg.CommandIdle = fifo.CPCmdIdle;
|
||||||
|
// uncomment: change a bit the behaviour MP1. Not very useful though
|
||||||
|
//m_CPStatusReg.ReadIdle = fifo.CPReadIdle;
|
||||||
|
|
||||||
|
// hack: CPU will always believe fifo is empty and on idle
|
||||||
|
m_CPStatusReg.ReadIdle = 1;
|
||||||
|
m_CPStatusReg.CommandIdle = 1;
|
||||||
|
|
||||||
|
_rReturnValue = m_CPStatusReg.Hex;
|
||||||
|
LOG(COMMANDPROCESSOR, "\t iBP %s | fREADIDLE %s | fCMDIDLE %s | iOvF %s | iUndF %s"
|
||||||
|
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
|
||||||
|
, m_CPStatusReg.ReadIdle ? "ON" : "OFF"
|
||||||
|
, m_CPStatusReg.CommandIdle ? "ON" : "OFF"
|
||||||
|
, m_CPStatusReg.OverflowHiWatermark ? "ON" : "OFF"
|
||||||
|
, m_CPStatusReg.UnderflowLoWatermark ? "ON" : "OFF"
|
||||||
|
);
|
||||||
|
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; return;
|
||||||
|
|
||||||
|
@ -255,29 +275,39 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
||||||
case FIFO_HI_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPHiWatermark); return;
|
case FIFO_HI_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPHiWatermark); return;
|
||||||
case FIFO_LO_WATERMARK_LO: _rReturnValue = ReadLow (fifo.CPLoWatermark); return;
|
case FIFO_LO_WATERMARK_LO: _rReturnValue = ReadLow (fifo.CPLoWatermark); return;
|
||||||
case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
|
case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
|
||||||
|
|
||||||
|
// TODO: cases cleanup
|
||||||
case FIFO_RW_DISTANCE_LO:
|
case FIFO_RW_DISTANCE_LO:
|
||||||
_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
|
//_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
|
||||||
//LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
|
// hack: CPU will always believe fifo is empty and on idle
|
||||||
|
_rReturnValue = 0;
|
||||||
|
LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
|
||||||
return;
|
return;
|
||||||
case FIFO_RW_DISTANCE_HI:
|
case FIFO_RW_DISTANCE_HI:
|
||||||
_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
|
//_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
|
||||||
//LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
|
// hack: CPU will always believe fifo is empty and on idle
|
||||||
|
_rReturnValue = 0;
|
||||||
|
LOG(COMMANDPROCESSOR,"read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
|
||||||
return;
|
return;
|
||||||
case FIFO_WRITE_POINTER_LO:
|
case FIFO_WRITE_POINTER_LO:
|
||||||
_rReturnValue = ReadLow (fifo.CPWritePointer);
|
_rReturnValue = ReadLow (fifo.CPWritePointer);
|
||||||
//LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue);
|
LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue);
|
||||||
return;
|
return;
|
||||||
case FIFO_WRITE_POINTER_HI:
|
case FIFO_WRITE_POINTER_HI:
|
||||||
_rReturnValue = ReadHigh(fifo.CPWritePointer);
|
_rReturnValue = ReadHigh(fifo.CPWritePointer);
|
||||||
//LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue);
|
LOG(COMMANDPROCESSOR,"read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue);
|
||||||
return;
|
return;
|
||||||
case FIFO_READ_POINTER_LO:
|
case FIFO_READ_POINTER_LO:
|
||||||
_rReturnValue = ReadLow (fifo.CPReadPointer);
|
//_rReturnValue = ReadLow (fifo.CPReadPointer);
|
||||||
//LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_LO : %04x", _rReturnValue);
|
// hack: CPU will always believe fifo is empty and on idle
|
||||||
|
_rReturnValue = ReadLow (fifo.CPWritePointer);
|
||||||
|
LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_LO : %04x", _rReturnValue);
|
||||||
return;
|
return;
|
||||||
case FIFO_READ_POINTER_HI:
|
case FIFO_READ_POINTER_HI:
|
||||||
_rReturnValue = ReadHigh(fifo.CPReadPointer);
|
//_rReturnValue = ReadHigh(fifo.CPReadPointer);
|
||||||
//LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_HI : %04x", _rReturnValue);
|
// hack: CPU will always believe fifo is empty and on idle
|
||||||
|
_rReturnValue = ReadHigh(fifo.CPWritePointer);
|
||||||
|
LOG(COMMANDPROCESSOR,"read FIFO_READ_POINTER_HI : %04x", _rReturnValue);
|
||||||
return;
|
return;
|
||||||
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;
|
||||||
|
@ -321,9 +351,9 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
// TODO: HLE for GX fifo's APIs?
|
// TODO: HLE for GX fifo's APIs?
|
||||||
// Here is the hack:
|
// Here is the hack:
|
||||||
// - if (attempt to overwrite CTRL_REGISTER by 0x0000)
|
// - if (attempt to overwrite CTRL_REGISTER by 0x0000)
|
||||||
// // then we assume CPReadWriteDistance will be reset to 0x00000000 very soon.
|
// // then we assume CPReadWriteDistance will be overwrited very soon.
|
||||||
// - if (fifo is not empty)
|
// - if (fifo is not empty)
|
||||||
// // (not 100% sure): shouln't happens unless PPC think having trouble with the sync
|
// // (not 100% sure): shouln't happen unless PPC think having trouble with the sync
|
||||||
// // and it attempt a fifo recovery (look for PI_FIFO_RESET in log).
|
// // and it attempt a fifo recovery (look for PI_FIFO_RESET in log).
|
||||||
// // If we want to emulate self fifo recovery we need proper GX metrics emulation... yeah sure :p
|
// // If we want to emulate self fifo recovery we need proper GX metrics emulation... yeah sure :p
|
||||||
// - spin until fifo is empty
|
// - spin until fifo is empty
|
||||||
|
@ -333,7 +363,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
if (((_Address&0xFFF) == CTRL_REGISTER) && (_Value == 0)) // API hack
|
if (((_Address&0xFFF) == CTRL_REGISTER) && (_Value == 0)) // API hack
|
||||||
{
|
{
|
||||||
// weird MP1 redo that right after linking fifo with GP... hmmm
|
// weird MP1 redo that right after linking fifo with GP... hmmm
|
||||||
// maybe waiting for an irq like ReadIdle... dunno
|
|
||||||
/*_dbg_assert_msg_(COMMANDPROCESSOR, fifo.CPReadWriteDistance == 0,
|
/*_dbg_assert_msg_(COMMANDPROCESSOR, fifo.CPReadWriteDistance == 0,
|
||||||
"WTF! Something went wrong with GP/PPC the sync! -> CPReadWriteDistance: 0x%08X\n"
|
"WTF! Something went wrong with GP/PPC the sync! -> CPReadWriteDistance: 0x%08X\n"
|
||||||
" - The fifo is not empty but we are going to lock it anyway.\n"
|
" - The fifo is not empty but we are going to lock it anyway.\n"
|
||||||
|
@ -343,6 +372,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
" - Anyway, fifo flush will be forced if you press OK and dolphin might continue to work...\n"
|
" - Anyway, fifo flush will be forced if you press OK and dolphin might continue to work...\n"
|
||||||
" - We aren't betting on that :)", fifo.CPReadWriteDistance);
|
" - We aren't betting on that :)", fifo.CPReadWriteDistance);
|
||||||
/**/
|
/**/
|
||||||
|
LOG(COMMANDPROCESSOR, "*********************** GXSetGPFifo very soon? ***********************");
|
||||||
u32 ct=0;
|
u32 ct=0;
|
||||||
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance > 0 )
|
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance > 0 )
|
||||||
ct++;
|
ct++;
|
||||||
|
@ -359,8 +389,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
// set the flags to "all is okay"
|
// set the flags to "all is okay"
|
||||||
m_CPStatusReg.OverflowHiWatermark = 0;
|
m_CPStatusReg.OverflowHiWatermark = 0;
|
||||||
m_CPStatusReg.UnderflowLoWatermark = 0;
|
m_CPStatusReg.UnderflowLoWatermark = 0;
|
||||||
m_CPStatusReg.ReadIdle = 1;
|
|
||||||
m_CPStatusReg.CommandIdle = 1;
|
|
||||||
|
|
||||||
// TOCHECK (mb2): could BP irq be cleared here too?
|
// TOCHECK (mb2): could BP irq be cleared here too?
|
||||||
//if (tmpStatus.Breakpoint!=m_CPStatusReg.Breakpoint) _asm int 3
|
//if (tmpStatus.Breakpoint!=m_CPStatusReg.Breakpoint) _asm int 3
|
||||||
|
@ -383,16 +411,16 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
|
|
||||||
case CTRL_REGISTER:
|
case CTRL_REGISTER:
|
||||||
{
|
{
|
||||||
m_CPCtrlReg.Hex = _Value;
|
UCPCtrlReg tmpCtrl(_Value);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
InterlockedExchange((LONG*)&fifo.bFF_GPReadEnable, m_CPCtrlReg.GPReadEnable);
|
InterlockedExchange((LONG*)&fifo.bFF_GPReadEnable, tmpCtrl.GPReadEnable);
|
||||||
InterlockedExchange((LONG*)&fifo.bFF_GPLinkEnable, m_CPCtrlReg.GPLinkEnable);
|
InterlockedExchange((LONG*)&fifo.bFF_GPLinkEnable, tmpCtrl.GPLinkEnable);
|
||||||
InterlockedExchange((LONG*)&fifo.bFF_BPEnable, m_CPCtrlReg.BPEnable);
|
InterlockedExchange((LONG*)&fifo.bFF_BPEnable, tmpCtrl.BPEnable);
|
||||||
#else
|
#else
|
||||||
Common::InterlockedExchange((int*)&fifo.bFF_GPReadEnable, m_CPCtrlReg.GPReadEnable);
|
Common::InterlockedExchange((int*)&fifo.bFF_GPReadEnable, tmpCtrl.GPReadEnable);
|
||||||
Common::InterlockedExchange((int*)&fifo.bFF_GPLinkEnable, m_CPCtrlReg.GPLinkEnable);
|
Common::InterlockedExchange((int*)&fifo.bFF_GPLinkEnable, tmpCtrl.GPLinkEnable);
|
||||||
Common::InterlockedExchange((int*)&fifo.bFF_BPEnable, m_CPCtrlReg.BPEnable);
|
Common::InterlockedExchange((int*)&fifo.bFF_BPEnable, tmpCtrl.BPEnable);
|
||||||
#endif
|
#endif
|
||||||
// TOCHECK (mb2): could BP irq be cleared with w16 to STATUS_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
|
// funny hack: eg in MP1 if we disable the clear breakpoint ability by commenting this block
|
||||||
|
@ -402,7 +430,10 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
// TODO (mb2): fix this!
|
// TODO (mb2): fix this!
|
||||||
|
|
||||||
// BP interrupt is cleared here
|
// BP interrupt is cleared here
|
||||||
/*if (m_CPCtrlReg.CPIntEnable)
|
/*
|
||||||
|
//if (tmpCtrl.CPIntEnable)
|
||||||
|
//if (!m_CPCtrlReg.CPIntEnable && tmpCtrl.Hex) // raising edge
|
||||||
|
//if (m_CPCtrlReg.CPIntEnable && !tmpCtrl.Hex) // falling edge
|
||||||
{
|
{
|
||||||
LOG(COMMANDPROCESSOR,"\t ClearBreakpoint interrupt");
|
LOG(COMMANDPROCESSOR,"\t ClearBreakpoint interrupt");
|
||||||
// yes an SC hack, single core mode isn't very gc spec compliant :D
|
// yes an SC hack, single core mode isn't very gc spec compliant :D
|
||||||
|
@ -413,6 +444,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
InterlockedExchange((LONG*)&fifo.bFF_Breakpoint, 0);
|
InterlockedExchange((LONG*)&fifo.bFF_Breakpoint, 0);
|
||||||
}
|
}
|
||||||
}/**/
|
}/**/
|
||||||
|
m_CPCtrlReg.Hex = tmpCtrl.Hex;
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
||||||
LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || CPIntEnable %s | OvF %s | UndF %s"
|
LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || CPIntEnable %s | OvF %s | UndF %s"
|
||||||
|
@ -439,38 +471,66 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
// Fifo Registers
|
// Fifo Registers
|
||||||
case FIFO_TOKEN_REGISTER:
|
case FIFO_TOKEN_REGISTER:
|
||||||
m_tokenReg = _Value;
|
m_tokenReg = _Value;
|
||||||
LOG(COMMANDPROCESSOR,"write to FIFO_TOKEN_REGISTER : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_BASE_LO: WriteLow ((u32 &)fifo.CPBase, _Value); fifo.CPBase &= 0xFFFFFFE0; break;
|
case FIFO_BASE_LO:
|
||||||
case FIFO_BASE_HI: WriteHigh((u32 &)fifo.CPBase, _Value); fifo.CPBase &= 0xFFFFFFE0; break;
|
WriteLow ((u32 &)fifo.CPBase, _Value);
|
||||||
case FIFO_END_LO: WriteLow ((u32 &)fifo.CPEnd, _Value); fifo.CPEnd &= 0xFFFFFFE0; break;
|
fifo.CPBase &= 0xFFFFFFE0;
|
||||||
case FIFO_END_HI: WriteHigh((u32 &)fifo.CPEnd, _Value); fifo.CPEnd &= 0xFFFFFFE0; break;
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO : %04x", _Value);
|
||||||
|
break;
|
||||||
|
case FIFO_BASE_HI:
|
||||||
|
WriteHigh((u32 &)fifo.CPBase, _Value);
|
||||||
|
fifo.CPBase &= 0xFFFFFFE0;
|
||||||
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI : %04x", _Value);
|
||||||
|
break;
|
||||||
|
case FIFO_END_LO:
|
||||||
|
WriteLow ((u32 &)fifo.CPEnd, _Value);
|
||||||
|
fifo.CPEnd &= 0xFFFFFFE0;
|
||||||
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO : %04x", _Value);
|
||||||
|
break;
|
||||||
|
case FIFO_END_HI:
|
||||||
|
WriteHigh((u32 &)fifo.CPEnd, _Value);
|
||||||
|
fifo.CPEnd &= 0xFFFFFFE0;
|
||||||
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI : %04x", _Value);
|
||||||
|
break;
|
||||||
|
|
||||||
// Hm. Should we really & these with FFFFFFE0?
|
// Hm. Should we really & these with FFFFFFE0?
|
||||||
// (mb2): never seen 32B not aligned values for those following regs.
|
// (mb2): never seen 32B not aligned values for those following regs.
|
||||||
// fifo.CPEnd is the only value that could be not 32B aligned so far.
|
// fifo.CPEnd is the only value that could be not 32B aligned so far.
|
||||||
case FIFO_WRITE_POINTER_LO:
|
case FIFO_WRITE_POINTER_LO:
|
||||||
WriteLow ((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
|
WriteLow ((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
|
||||||
//LOG(COMMANDPROCESSOR,"write to FIFO_WRITE_POINTER_LO : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
case FIFO_WRITE_POINTER_HI:
|
case FIFO_WRITE_POINTER_HI:
|
||||||
WriteHigh((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
|
WriteHigh((u32 &)fifo.CPWritePointer, _Value); fifo.CPWritePointer &= 0xFFFFFFE0;
|
||||||
//LOG(COMMANDPROCESSOR,"write to FIFO_WRITE_POINTER_HI : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
case FIFO_READ_POINTER_LO:
|
case FIFO_READ_POINTER_LO:
|
||||||
WriteLow ((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
|
WriteLow ((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
|
||||||
//LOG(COMMANDPROCESSOR,"write to FIFO_READ_POINTER_LO : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
case FIFO_READ_POINTER_HI:
|
case FIFO_READ_POINTER_HI:
|
||||||
WriteHigh((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
|
WriteHigh((u32 &)fifo.CPReadPointer, _Value); fifo.CPReadPointer &= 0xFFFFFFE0;
|
||||||
//LOG(COMMANDPROCESSOR,"write to FIFO_READ_POINTER_HI : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_HI_WATERMARK_LO: WriteLow ((u32 &)fifo.CPHiWatermark, _Value); break;
|
case FIFO_HI_WATERMARK_LO:
|
||||||
case FIFO_HI_WATERMARK_HI: WriteHigh((u32 &)fifo.CPHiWatermark, _Value); break;
|
WriteLow ((u32 &)fifo.CPHiWatermark, _Value);
|
||||||
case FIFO_LO_WATERMARK_LO: WriteLow ((u32 &)fifo.CPLoWatermark, _Value); break;
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO : %04x", _Value);
|
||||||
case FIFO_LO_WATERMARK_HI: WriteHigh((u32 &)fifo.CPLoWatermark, _Value); break;
|
break;
|
||||||
|
case FIFO_HI_WATERMARK_HI:
|
||||||
|
WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
|
||||||
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI : %04x", _Value);
|
||||||
|
break;
|
||||||
|
case FIFO_LO_WATERMARK_LO:
|
||||||
|
WriteLow ((u32 &)fifo.CPLoWatermark, _Value);
|
||||||
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO : %04x", _Value);
|
||||||
|
break;
|
||||||
|
case FIFO_LO_WATERMARK_HI:
|
||||||
|
WriteHigh((u32 &)fifo.CPLoWatermark, _Value);
|
||||||
|
LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI : %04x", _Value);
|
||||||
|
break;
|
||||||
|
|
||||||
case FIFO_BP_LO:
|
case FIFO_BP_LO:
|
||||||
WriteLow ((u32 &)fifo.CPBreakpoint, _Value);
|
WriteLow ((u32 &)fifo.CPBreakpoint, _Value);
|
||||||
|
@ -481,23 +541,23 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
LOG(COMMANDPROCESSOR,"write to FIFO_BP_HI : %04x", _Value);
|
LOG(COMMANDPROCESSOR,"write to FIFO_BP_HI : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// needed for CPReadWriteDistance reset only
|
// Super monkey try to overwrite CPReadWriteDistance by an old saved RWD value. Which is lame for us.
|
||||||
|
// hack: We have to force CPU to think fifo is alway empty and on idle.
|
||||||
|
// When we fall here CPReadWriteDistance should be always null and the game should always want to overwrite it by 0.
|
||||||
|
// So, we can skip it.
|
||||||
case FIFO_RW_DISTANCE_HI:
|
case FIFO_RW_DISTANCE_HI:
|
||||||
|
//WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value);
|
||||||
|
LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
|
||||||
|
break;
|
||||||
case FIFO_RW_DISTANCE_LO:
|
case FIFO_RW_DISTANCE_LO:
|
||||||
LOG(COMMANDPROCESSOR,"try to write to %s : %04x",((_Address & 0xFFF) == FIFO_RW_DISTANCE_HI) ? "FIFO_RW_DISTANCE_HI" : "FIFO_RW_DISTANCE_LO", _Value);
|
//WriteLow((u32 &)fifo.CPReadWriteDistance, _Value);
|
||||||
_dbg_assert_msg_(COMMANDPROCESSOR, _Value==0, "WTF? attempt to overwrite fifo CPReadWriteDistance with a value(%04x) != 0 ",_Value);
|
LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_LO : %04x", _Value);
|
||||||
|
|
||||||
// This SHOULD NOT be a problem to overwrite here unless this msg appears:
|
|
||||||
_dbg_assert_msg_(COMMANDPROCESSOR, fifo.CPReadWriteDistance==0, "Is that bad? WARNING: reset a non empty fifo.\n CPReadWriteDistance: %08x | fifo.bFF_GPReadEnable: %i",fifo.CPReadWriteDistance,fifo.bFF_GPReadEnable);
|
|
||||||
//_dbg_assert_msg_(COMMANDPROCESSOR, !(fifo.CPReadWriteDistance!=0 && fifo.bFF_GPReadEnable==0), "Is that bad? WARNING: reset a not empty and not readable fifo.\n CPReadWriteDistance: %08x | fifo.bFF_GPReadEnable: %i",fifo.CPReadWriteDistance,fifo.bFF_GPReadEnable);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
//InterlockedExchange((LONG*)&fifo.CPReadWriteDistance, 0);
|
|
||||||
#else
|
|
||||||
//Common::InterlockedExchange((int*)&fifo.CPReadWriteDistance, 0);
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(mb2): better. Check if it help: avoid CPReadPointer overwrites when stupidly done like in Super Monkey Ball
|
||||||
|
if ((!fifo.bFF_GPReadEnable && fifo.CPReadIdle) || !Core::g_CoreStartupParameter.bUseDualCore) // TOCHECK(mb2): check again if thread safe?
|
||||||
|
UpdateFifoRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read32(u32& _rReturnValue, const u32 _Address)
|
void Read32(u32& _rReturnValue, const u32 _Address)
|
||||||
|
@ -551,8 +611,7 @@ void GatherPipeBursted()
|
||||||
|
|
||||||
LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached");
|
LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached");
|
||||||
// Wait for GPU to catch up
|
// Wait for GPU to catch up
|
||||||
//while (!(fifo.bFF_BPEnable && fifo.bFF_Breakpoint) && fifo.CPReadWriteDistance > (s32)fifo.CPLoWatermark)
|
while (!(fifo.bFF_BPEnable && fifo.bFF_Breakpoint) && fifo.CPReadWriteDistance > (s32)fifo.CPLoWatermark)
|
||||||
while (fifo.CPReadWriteDistance > fifo.CPLoWatermark)
|
|
||||||
{
|
{
|
||||||
ct++;
|
ct++;
|
||||||
// dunno if others threads (like the audio thread) really need a forced context switch here
|
// dunno if others threads (like the audio thread) really need a forced context switch here
|
||||||
|
@ -628,7 +687,7 @@ void CatchUpGPU()
|
||||||
}
|
}
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
// !!! only called on single core mode now
|
// !!! Temporary (I hope): re-used in DC mode
|
||||||
// UpdateFifoRegister
|
// UpdateFifoRegister
|
||||||
// It's no problem if the gfx falls behind a little bit. Better make sure to stop the cpu thread
|
// It's no problem if the gfx falls behind a little bit. Better make sure to stop the cpu thread
|
||||||
// when the distance is way huge, though.
|
// when the distance is way huge, though.
|
||||||
|
@ -651,7 +710,9 @@ void UpdateFifoRegister()
|
||||||
dist = wp - rp;
|
dist = wp - rp;
|
||||||
else
|
else
|
||||||
dist = (wp - fifo.CPBase) + (fifo.CPEnd - rp);
|
dist = (wp - fifo.CPBase) + (fifo.CPEnd - rp);
|
||||||
fifo.CPReadWriteDistance = dist;
|
//fifo.CPReadWriteDistance = dist;
|
||||||
|
InterlockedExchange((LONG*)&fifo.CPReadWriteDistance, dist);
|
||||||
|
if (!Core::g_CoreStartupParameter.bUseDualCore)
|
||||||
CatchUpGPU();
|
CatchUpGPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,8 +114,9 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||||
//etc...
|
//etc...
|
||||||
|
|
||||||
// check if we are able to run this buffer
|
// check if we are able to run this buffer
|
||||||
if ((_fifo.bFF_GPReadEnable) && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint))
|
if ((_fifo.bFF_GPReadEnable) && _fifo.CPReadWriteDistance && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint))
|
||||||
{
|
{
|
||||||
|
InterlockedExchange((LONG*)&_fifo.CPReadIdle, 0);
|
||||||
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
||||||
while(_fifo.CPReadWriteDistance > 0)
|
while(_fifo.CPReadWriteDistance > 0)
|
||||||
#else
|
#else
|
||||||
|
@ -167,6 +168,8 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||||
Common::InterlockedExchangeAdd((int*)&_fifo.CPReadWriteDistance, -distToSend);
|
Common::InterlockedExchangeAdd((int*)&_fifo.CPReadWriteDistance, -distToSend);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
//video_initialize.pLog("IDLE",FALSE);
|
||||||
|
InterlockedExchange((LONG*)&_fifo.CPReadIdle, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
|
||||||
|
|
|
@ -45,6 +45,9 @@ typedef struct
|
||||||
volatile BOOL bFF_GPLinkEnable;
|
volatile BOOL bFF_GPLinkEnable;
|
||||||
volatile BOOL bFF_Breakpoint;
|
volatile BOOL bFF_Breakpoint;
|
||||||
|
|
||||||
|
volatile BOOL CPCmdIdle;
|
||||||
|
volatile BOOL CPReadIdle;
|
||||||
|
|
||||||
// for GP watchdog hack
|
// for GP watchdog hack
|
||||||
volatile u32 Fake_GPWDToken; // cicular incrementer
|
volatile u32 Fake_GPWDToken; // cicular incrementer
|
||||||
} SCPFifoStruct;
|
} SCPFifoStruct;
|
||||||
|
|
|
@ -310,6 +310,8 @@ void OpcodeDecoder_Run()
|
||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
while (FifoCommandRunnable())
|
while (FifoCommandRunnable())
|
||||||
{
|
{
|
||||||
|
//TODO?: if really needed, do something like this: "InterlockedExchange((LONG*)&_fifo.CPCmdIdle, 0);"
|
||||||
Decode();
|
Decode();
|
||||||
}
|
}
|
||||||
|
//TODO?: if really needed, do something like this: "InterlockedExchange((LONG*)&_fifo.CPCmdIdle, 1);"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue