* SIGNAL! Pretty sure I got it handled accurately now, minus GIF stalling.

* Re-added a trace log for the GIFtag parse optimization; Fixed some mVU warnings.

DevNotes:
Places where GIF needs stalled and resumed are marked with [TODO]'s.  We also need to add a way for SIGNAL to abort the currently processing GIFtag, which might need a return code added to the callbacks.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3373 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-07-02 15:32:03 +00:00
parent 501cb676bc
commit 362294ab8b
4 changed files with 68 additions and 50 deletions

View File

@ -134,6 +134,17 @@
# define pxDebugCode(code)
#endif
#ifdef PCSX2_DEVBUILD
# define pxDevelCode(code) code
#else
# define pxDevelCode(code)
#endif
#if !defined(PCSX2_DEBUG) && !defined(PCSX2_DEVEL)
# define pxReleaseCode(code)
#else
# define pxReleaseCode(code) code
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// __aligned / __aligned16 / __pagealigned

View File

@ -51,7 +51,8 @@ void gsInit()
memzero(g_RealGSMem);
}
extern bool CSR_SIGNAL_Pending;
extern bool SIGNAL_IMR_Pending;
extern u32 SIGNAL_Data_Pending[2];
void gsGIFReset()
{
@ -68,7 +69,7 @@ void gsReset()
GSTransferStatus = (STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE;
memzero(g_RealGSMem);
CSR_SIGNAL_Pending = false;
SIGNAL_IMR_Pending = false;
CSRreg.Reset();
GSIMR = 0x7f00;
@ -96,7 +97,7 @@ static __forceinline void gsCSRwrite( const tGS_CSR& csr )
GetMTGS().SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
}
CSR_SIGNAL_Pending = false;
SIGNAL_IMR_Pending = false;
CSRreg.Reset();
GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1
}
@ -109,13 +110,21 @@ static __forceinline void gsCSRwrite( const tGS_CSR& csr )
if(csr.SIGNAL)
{
// SIGNAL : What's not known here is whether or not the SIGID register should be updated
// here or when the IMR is cleared (below).
GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x\n",SIGNAL_Data_Pending[0], SIGNAL_Data_Pending[1], GSIMR, GSCSRr);
GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~SIGNAL_Data_Pending[1])|(SIGNAL_Data_Pending[0]&SIGNAL_Data_Pending[1]);
CSRreg.SIGNAL = false;
// [TODO] (SIGNAL) : Re-enable GIFpath DMAs here!
}
if(csr.FINISH) CSRreg.FINISH = false;
if(csr.HSINT) CSRreg.HSINT = false;
if(csr.VSINT) CSRreg.VSINT = false;
if(csr.EDWINT) CSRreg.EDWINT = false;
if(csr.EDWINT) CSRreg.EDWINT = false;
}
static __forceinline void IMRwrite(u32 value)
@ -125,17 +134,19 @@ static __forceinline void IMRwrite(u32 value)
if(CSRreg.GetInterruptMask() & (~(GSIMR >> 8) & 0x1f))
gsIrq();
if( CSR_SIGNAL_Pending && !(GSIMR & 0x100))
if( SIGNAL_IMR_Pending && !(GSIMR & 0x100))
{
// (note: PS2 apps are expected to write a successive 1 and 0 to the IMR in order to
// Note: PS2 apps are expected to write a successive 1 and 0 to the IMR in order to
// trigger the gsInt and clear the second pending SIGNAL interrupt -- if they fail
// to do so, the GS will freeze again upon the very next SIGNAL).
//
// What's not known here is whether or not the SIGID register should be updated
// here or when the GS is resumed during CSR write (above).
// It's yet unclear if the SIGNAL should be set back to TRUE or not when the IRQ is
// raised here. Neither setting it nor leaving it be seemed to keep Soul Calibur 3 from
// dying. This could be the fault of other emulation/timing errors in the DMA though --air
//GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x\n",CSR_SIGNAL_Data[0], CSR_SIGNAL_Data[1], GSIMR, GSCSRr);
//GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~CSR_SIGNAL_Data[1])|(CSR_SIGNAL_Data[0]&CSR_SIGNAL_Data[1]);
//CSRreg.SIGNAL = true;
CSRreg.SIGNAL = true;
gsIrq();
}
}
@ -441,7 +452,7 @@ void gsResetFrameSkip()
void SaveStateBase::gsFreeze()
{
FreezeMem(PS2MEM_GS, 0x2000);
Freeze(CSR_SIGNAL_Pending);
Freeze(SIGNAL_IMR_Pending);
if( GetVersion() > 0 )
Freeze(gsRegionMode);

View File

@ -80,7 +80,7 @@ struct GIFTAG
struct GIFPath
{
const GIFTAG tag; // The "original tag -- modification allowed only by SetTag(), so let's make it const.
const GIFTAG tag; // A copy of the "original" tag -- modification allowed only by SetTag(), so let's make it const.
u8 regs[16]; // positioned after tag ensures 16-bit aligned (in case we SSE optimize later)
u32 nloop; // local copy nloop counts toward zero, and leaves the tag copy unmodified.
@ -113,59 +113,56 @@ struct GifPathStruct
// --------------------------------------------------------------------------------------
// SIGNAL / FINISH / LABEL (WIP!!)
// SIGNAL / FINISH / LABEL
// --------------------------------------------------------------------------------------
// The current implementation for these is very incomplete, especially SIGNAL, which needs
// an extra VM-state status var to be handled correctly.
//
// [TODO] -- Apparently all gs writes should be ignored when this little flag is TRUE.
// (not that any game's emulation accuracy probably depends on such a 'feature') --air
bool CSR_SIGNAL_Pending = false;
bool SIGNAL_IMR_Pending = false;
u32 SIGNAL_Data_Pending[2];
// SIGNAL : This register is a double-throw. If the SIGNAL bit in CSR is clear, set the CSR
// and raise a gsIrq. If CSR is already *set*, then ignore all subsequent drawing operations
// and writes to general purpose registers to the GS. (note: I'm pretty sure this includes
// direct GS and GSreg accesses, as well as those coming through the GIFpath -- but that
// behavior isn't confirmed yet). Privileged writes are still active.
// and raise a gsIrq. If CSR is already *set*, then do not raise a gsIrq, and ignore all
// subsequent drawing operations and writes to general purpose registers to the GS. (note:
// I'm pretty sure this includes direct GS and GSreg accesses, as well as those coming
// through the GIFpath -- but that behavior isn't confirmed yet). Privileged writes are
// still active.
//
// Ignorance continues until the SIGNAL bit in CSR is manually cleared by the EE. And here's
// the tricky part: the interrupt from the second SIGNAL is still pending, and should be
// raised once the EE has reset the *IMR* mask for SIGNAL -- meaning setting the bit to 1
// (disabled/masked) and then back to 0 (enabled/unmasked).
// (disabled/masked) and then back to 0 (enabled/unmasked). Until the *IMR* is cleared, the
// SIGNAL is still in the second throw stage, and will freeze the GS upon being written.
//
static void __fastcall RegHandlerSIGNAL(const u32* data)
{
GIF_LOG("GS SIGNAL data=%x_%x IMR=%x CSRr=%x\n",data[0], data[1], GSIMR, GSCSRr);
GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~data[1])|(data[0]&data[1]);
// HACK:
// Soul Calibur 3 has missing geometry on the Vs select screen if we only setup
// SIGNAL when the CSR flag is cleared. It seems to be doing SIGNALs on PATH2 and
// PATH3 simultaneously, and isn't too happy with the results. It properly clears the
// SIGNAL interrupt but seems to get suck on a VBLANK OVERLAP loop.
// Investigating the game's internals more deeply may prove to be revealing. --air
// Soul Calibur 3 seems to be doing SIGNALs on PATH2 and PATH3 simultaneously, and isn't
// too happy with the results (dies on bootup). It properly clears the SIGNAL interrupt
// but seems to get stuck on a VBLANK OVERLAP loop. Fixing SIGNAL so that it properly
// stalls the GIF might fix it. Investigating the game's internals more deeply may also
// be revealing. --air
if (false)
//if (CSRreg.SIGNAL) // breaks SC3
if (CSRreg.SIGNAL)
{
// Time to ignore all subsequent drawing operations. (which is not yet supported)
if (!CSR_SIGNAL_Pending)
if (!SIGNAL_IMR_Pending)
{
DevCon.WriteLn( Color_StrongOrange, "GS SIGNAL double throw encountered!" );
CSR_SIGNAL_Pending = true;
SIGNAL_IMR_Pending = true;
SIGNAL_Data_Pending[0] = data[0];
SIGNAL_Data_Pending[1] = data[1];
// [TODO] (SIGNAL) : Disable GIFpath DMAs here!
// All PATHs and DMAs should be disabled until the CSR is written and the
// SIGNAL bit cleared.
}
}
else
{
// notes:
// * DDS SMT however crashes at the first FMV if SIGNAL raises IRQs constantly,
// so that's why we only raise an IRQ if both signal and GSIMR are prepped.
// (this might be correct behavior-- hard to tell yet) --air
GIF_LOG("GS SIGNAL data=%x_%x IMR=%x CSRr=%x\n",data[0], data[1], GSIMR, GSCSRr);
GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~data[1])|(data[0]&data[1]);
if (!CSRreg.SIGNAL && !(GSIMR&0x100) )
if (!(GSIMR&0x100))
gsIrq();
CSRreg.SIGNAL = true;
@ -472,7 +469,7 @@ __forceinline int GIFPath::ParseTagQuick(GIF_PATH pathidx, const u8* pMem, u32 s
}
else
{
// Note: The BIOS does an XGKICK on the VU1 and lets yt DMA to the GS without an EOP
// Note: The BIOS does an XGKICK on the VU1 and lets it DMA to the GS without an EOP
// (seemingly to loop forever), only to write an EOP later on. No other game is known to
// do anything of the sort.
// So lets just cap the DMA at 16k, and force it to "look" like it's terminated for now.
@ -482,7 +479,6 @@ __forceinline int GIFPath::ParseTagQuick(GIF_PATH pathidx, const u8* pMem, u32 s
Console.Warning("GIFTAG error, size exceeded VU memory size %x", startSize);
nloop = 0;
const_cast<GIFTAG&>(tag).EOP = 0;
}
}
}
@ -580,6 +576,8 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
}
else
{
//DevCon.WriteLn(Color_Orange, "No E detected on Path%d: nloop=%x, numregs=%x, curreg=%x, size=%x", pathidx + 1, nloop, numregs, curreg, size);
// Note: curreg is *usually* zero here, but can be non-zero if a previous fragment was
// handled via this optimized copy code below.
@ -670,7 +668,6 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
Console.Warning("GIFTAG error, size exceeded VU memory size %x", startSize);
nloop = 0;
const_cast<GIFTAG&>(tag).EOP = 0;
}
}
}
@ -683,10 +680,9 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size)
// FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active
// drawing *and* image transfer actions must be finished before the IRQ raises.
if (!s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive())
if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive())
{
if (!(GSIMR&0x200))
gsIrq();
gsIrq();
}
}
break;

View File

@ -295,9 +295,9 @@ _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState) {
return entryPoint;
} catch( BaseException& ex ) {
} catch( BaseException& pxDevelCode(ex) ) {
pxFailDev( wxsFormat(L"microVU%d recompiler exception: " + ex.FormatDiagnosticMessage(), mVU->index) );
} catch( std::exception& ex ) {
} catch( std::exception& pxDevelCode(ex) ) {
pxFailDev( wxsFormat(L"microVU%d recompiler exception: " + Exception::RuntimeError(ex).FormatDiagnosticMessage(), mVU->index) );
}