From 362294ab8b55d27d7658745862ec5b937d7cfab2 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Fri, 2 Jul 2010 15:32:03 +0000 Subject: [PATCH] * 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 --- common/include/Pcsx2Defs.h | 11 ++++++ pcsx2/GS.cpp | 33 ++++++++++++------ pcsx2/ps2/GIFpath.cpp | 70 ++++++++++++++++++-------------------- pcsx2/x86/microVU.cpp | 4 +-- 4 files changed, 68 insertions(+), 50 deletions(-) diff --git a/common/include/Pcsx2Defs.h b/common/include/Pcsx2Defs.h index 6158b53d28..b181e8ac48 100644 --- a/common/include/Pcsx2Defs.h +++ b/common/include/Pcsx2Defs.h @@ -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 diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 8e897be8b8..b7cd68795e 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -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); diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp index 65e51606bf..d50be071ed 100644 --- a/pcsx2/ps2/GIFpath.cpp +++ b/pcsx2/ps2/GIFpath.cpp @@ -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(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(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; diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 7026d51cde..c23be38f91 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -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) ); }