diff --git a/common/include/Pcsx2Defs.h b/common/include/Pcsx2Defs.h index 6bef2c74c7a54..1acf59561cf4d 100644 --- a/common/include/Pcsx2Defs.h +++ b/common/include/Pcsx2Defs.h @@ -309,6 +309,7 @@ static const int __pagesize = PCSX2_PAGESIZE; #define __ri __releaseinline #define __fi __forceinline #define __fc __fastcall +#define elif else if #endif diff --git a/common/include/Utilities/Assertions.h b/common/include/Utilities/Assertions.h index d08fc8510c813..7a1e0536689d5 100644 --- a/common/include/Utilities/Assertions.h +++ b/common/include/Utilities/Assertions.h @@ -84,15 +84,18 @@ extern pxDoAssertFnType* pxDoAssert; // -------------------------------------------------------------------------------------- // pxAssume / pxAssumeDev / pxFail / pxFailDev // -------------------------------------------------------------------------------------- -// Assumptions are like "extra rigid" assertions, which should never fail under any circum- -// stance in release build optimized code. +// Assumptions are hints to the compiler that the condition will always be true, +// the condition should never fail under any circumstance in release builds +// or else you might get incorrect compiler generated code. // // Performance: All assumption/fail types optimize into __assume()/likely() directives in -// Release builds (non-dev varieties optimize as such in Devel builds as well). If using +// Release builds (non-dev varieties optimize as such in Devel builds as well). +// __assume(0) is a special form of __assume() which tells the compiler that the code path +// is not reachable and will cause undefined results if it is reachable... // // Having pxFail and pxFailDev translate into __assume statements is very dangerous, since // it can lead to the compiler optimizing out code and leading to crashes in dev/release -// builds. To have code optimized, explicitly use pxAssume(false) or pxAssumeDev(false,msg); +// builds. To have code optimized, explicitly use pxAssume(false) or pxAssumeDev(false,msg); #define pxDiagSpot DiagnosticOrigin( __TFILE__, __LINE__, __pxFUNCTION__ ) #define pxAssertSpot(cond) DiagnosticOrigin( __TFILE__, __LINE__, __pxFUNCTION__, _T(#cond) ) @@ -119,16 +122,26 @@ extern pxDoAssertFnType* pxDoAssert; #elif defined(PCSX2_DEVBUILD) - // Devel builds use __assume for standard assertions and call pxOnAssertDevel - // for AssertDev brand assertions (which typically throws a LogicError exception). + // Devel builds now will give you a release-mode assertion dialog window if any of the + // following macro's 'cond' field is false. + // Note: Only use pxAssume/Msg/Dev if you know what you're doing, __assume is supposed + // to be used as an optimization hint, yet many devs have been using psAssume + // thinking its the same as an assertion. + // __assume(0) is also very dangerous because it is a special case of __assume() which + // tells the compiler that the code path is not reachable, and it can cause unpredictable + // results if the code path can be reached. + // i.e. if (1) { __assume(0); something(); } + // In the above example, something() may never be called. + // __assume(0)'s real use is in optimizing stuff such as "default:" cases on a switch + // statement. See jNO_DEFAULT -# define pxAssertMsg(cond, msg) (likely(cond)) +# define pxAssertMsg(cond, msg) pxAssertRel(cond, msg) # define pxAssertDev(cond, msg) pxAssertRel(cond, msg) -# define pxAssumeMsg(cond, msg) (__assume(cond)) +# define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg) //(__assume(cond)) # define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg) -# define pxFail(msg) +# define pxFail(msg) pxAssertDev(false, msg) # define pxFailDev(msg) pxAssertDev(false, msg) #else @@ -142,8 +155,8 @@ extern pxDoAssertFnType* pxDoAssert; # define pxAssumeMsg(cond, msg) (__assume(cond)) # define pxAssumeDev(cond, msg) (__assume(cond)) -# define pxFail(msg) -# define pxFailDev(msg) +# define pxFail(msg) do{} while(0) +# define pxFailDev(msg) do{} while(0) #endif @@ -186,7 +199,7 @@ extern void pxOnAssert( const DiagnosticOrigin& origin, const char* msg ); # define jNO_DEFAULT \ default: \ { \ - pxAssumeDev( false, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)" ); \ + pxAssumeDev( 0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)" ); \ break; \ } #endif diff --git a/common/include/Utilities/Dependencies.h b/common/include/Utilities/Dependencies.h index 5011a6d50cbe6..4fec22d5b4c69 100644 --- a/common/include/Utilities/Dependencies.h +++ b/common/include/Utilities/Dependencies.h @@ -195,18 +195,19 @@ class ScopedBool // -------------------------------------------------------------------------------------- // Handy Human-readable constants for common immediate values (_16kb -> _4gb) -static const sptr _64kb = 0x10000; -static const sptr _16kb = _64kb / 4; -static const sptr _128kb = _64kb * 2; -static const sptr _256kb = _128kb * 2; +static const sptr _1kb = 1024 * 1; +static const sptr _16kb = _1kb * 16; +static const sptr _64kb = _1kb * 64; +static const sptr _128kb = _1kb * 128; +static const sptr _256kb = _1kb * 256; -static const s64 _1mb = 0x100000; +static const s64 _1mb = 1024 * 1024; static const s64 _8mb = _1mb * 8; static const s64 _16mb = _1mb * 16; static const s64 _32mb = _1mb * 32; static const s64 _64mb = _1mb * 64; static const s64 _256mb = _1mb * 256; -static const s64 _1gb = _256mb * 4; +static const s64 _1gb = _1mb * 1024; static const s64 _4gb = _1gb * 4; diff --git a/common/include/Utilities/IniInterface.h b/common/include/Utilities/IniInterface.h index e829d04b915d8..c29c3fe30acbc 100644 --- a/common/include/Utilities/IniInterface.h +++ b/common/include/Utilities/IniInterface.h @@ -43,7 +43,7 @@ class IniInterface void SetPath( const wxString& path ); void Flush(); - wxConfigBase& GetConfig() { pxAssume( m_Config ); return *m_Config; } + wxConfigBase& GetConfig() { pxAssert( m_Config ); return *m_Config; } bool IsOk() const { return m_Config != NULL; } virtual bool IsLoading() const=0; diff --git a/common/include/Utilities/PageFaultSource.h b/common/include/Utilities/PageFaultSource.h index 0101d5c4af197..823ef804a8bf0 100644 --- a/common/include/Utilities/PageFaultSource.h +++ b/common/include/Utilities/PageFaultSource.h @@ -199,13 +199,13 @@ class VirtualMemoryReserve u8& operator[](uint idx) { - pxAssume(idx < (m_pages_reserved * __pagesize)); + pxAssert(idx < (m_pages_reserved * __pagesize)); return *((u8*)m_baseptr + idx); } const u8& operator[](uint idx) const { - pxAssume(idx < (m_pages_reserved * __pagesize)); + pxAssert(idx < (m_pages_reserved * __pagesize)); return *((u8*)m_baseptr + idx); } diff --git a/common/include/Utilities/ScopedAlloc.h b/common/include/Utilities/ScopedAlloc.h index 6dcdfa3e9d073..9437495e19a27 100644 --- a/common/include/Utilities/ScopedAlloc.h +++ b/common/include/Utilities/ScopedAlloc.h @@ -107,7 +107,7 @@ class BaseScopedAlloc virtual ~BaseScopedAlloc() throw() { - //pxAssume(m_buffer==NULL); + //pxAssert(m_buffer==NULL); } public: diff --git a/common/include/Utilities/pxCheckBox.h b/common/include/Utilities/pxCheckBox.h index 47480f9811d53..56e56dba812e6 100644 --- a/common/include/Utilities/pxCheckBox.h +++ b/common/include/Utilities/pxCheckBox.h @@ -50,12 +50,12 @@ class pxCheckBox : public wxPanelWithHelpers pxCheckBox& SetIndeterminate(); pxCheckBox& SetState( wxCheckBoxState state ); - wxCheckBoxState GetState() const { pxAssume( m_checkbox != NULL ); return m_checkbox->Get3StateValue(); } - bool GetValue() const { pxAssume( m_checkbox != NULL ); return m_checkbox->GetValue(); } - bool IsChecked() const { pxAssume( m_checkbox != NULL ); return m_checkbox->IsChecked(); } - bool IsIndeterminate() const { pxAssume( m_checkbox != NULL ); return m_checkbox->Get3StateValue() == wxCHK_UNDETERMINED; } - operator wxCheckBox&() { pxAssume( m_checkbox != NULL ); return *m_checkbox; } - operator const wxCheckBox&() const { pxAssume( m_checkbox != NULL ); return *m_checkbox; } + wxCheckBoxState GetState() const { pxAssert( m_checkbox != NULL ); return m_checkbox->Get3StateValue(); } + bool GetValue() const { pxAssert( m_checkbox != NULL ); return m_checkbox->GetValue(); } + bool IsChecked() const { pxAssert( m_checkbox != NULL ); return m_checkbox->IsChecked(); } + bool IsIndeterminate() const { pxAssert( m_checkbox != NULL ); return m_checkbox->Get3StateValue() == wxCHK_UNDETERMINED; } + operator wxCheckBox&() { pxAssert( m_checkbox != NULL ); return *m_checkbox; } + operator const wxCheckBox&() const { pxAssert( m_checkbox != NULL ); return *m_checkbox; } wxCheckBox* GetWxPtr() { return m_checkbox; } const wxCheckBox* GetWxPtr() const { return m_checkbox; } diff --git a/common/include/x86emitter/x86types.h b/common/include/x86emitter/x86types.h index b29170371b0b2..c862ee25c00b4 100644 --- a/common/include/x86emitter/x86types.h +++ b/common/include/x86emitter/x86types.h @@ -501,7 +501,7 @@ template< typename T > void xWrite( T val ); &xmm6, &xmm7 }; - pxAssume(id < iREGCNT_XMM); + pxAssert(id < iREGCNT_XMM); return *m_tbl_xmmRegs[id]; } diff --git a/common/src/Utilities/AlignedMalloc.cpp b/common/src/Utilities/AlignedMalloc.cpp index c895c94972e09..ab2fdf0612441 100644 --- a/common/src/Utilities/AlignedMalloc.cpp +++ b/common/src/Utilities/AlignedMalloc.cpp @@ -28,7 +28,7 @@ static const uint headsize = sizeof(AlignedMallocHeader); void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align) { - pxAssume( align < 0x10000 ); + pxAssert( align < 0x10000 ); u8* p = (u8*)malloc(size+align+headsize); @@ -37,7 +37,7 @@ void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align) uptr aligned = (pasthead + align-1) & ~(align-1); AlignedMallocHeader* header = (AlignedMallocHeader*)(aligned-headsize); - pxAssume( (uptr)header >= (uptr)p ); + pxAssert( (uptr)header >= (uptr)p ); header->baseptr = p; header->size = size; @@ -47,7 +47,7 @@ void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align) void* __fastcall pcsx2_aligned_realloc(void* handle, size_t size, size_t align) { - pxAssume( align < 0x10000 ); + pxAssert( align < 0x10000 ); void* newbuf = pcsx2_aligned_malloc( size, align ); diff --git a/common/src/Utilities/FastFormatString.cpp b/common/src/Utilities/FastFormatString.cpp index 449fe13c18d17..0eed1374d16d0 100644 --- a/common/src/Utilities/FastFormatString.cpp +++ b/common/src/Utilities/FastFormatString.cpp @@ -92,14 +92,14 @@ class FastFormatBuffers BufferType& GrabBuffer() { ++m_curslot; - pxAssume(m_curslot < BufferCount); + pxAssert(m_curslot < BufferCount); return m_buffers[m_curslot]; } void ReleaseBuffer() { --m_curslot; - pxAssume(m_curslot < BufferCount); + pxAssert(m_curslot < BufferCount); } BufferType& operator[](uint i) diff --git a/common/src/Utilities/Mutex.cpp b/common/src/Utilities/Mutex.cpp index f680633e4da24..8ae6cd0e5fa77 100644 --- a/common/src/Utilities/Mutex.cpp +++ b/common/src/Utilities/Mutex.cpp @@ -270,7 +270,7 @@ void Threading::ScopedLock::AssignAndLock( const Mutex& locker ) void Threading::ScopedLock::AssignAndLock( const Mutex* locker ) { - pxAssume(!m_IsLocked); // if we're already locked, changing the lock is bad mojo. + pxAssert(!m_IsLocked); // if we're already locked, changing the lock is bad mojo. m_lock = const_cast(locker); if( !m_lock ) return; diff --git a/common/src/Utilities/VirtualMemory.cpp b/common/src/Utilities/VirtualMemory.cpp index 6a88233fa0ed4..02521f4a5cca4 100644 --- a/common/src/Utilities/VirtualMemory.cpp +++ b/common/src/Utilities/VirtualMemory.cpp @@ -44,7 +44,7 @@ void pxInstallSignalHandler() // -------------------------------------------------------------------------------------- EventListener_PageFault::EventListener_PageFault() { - pxAssume(Source_PageFault); + pxAssert(Source_PageFault); Source_PageFault->Add( *this ); } diff --git a/common/src/Utilities/pxCheckBox.cpp b/common/src/Utilities/pxCheckBox.cpp index c5de27aa4e55b..a3fcda9c6471e 100644 --- a/common/src/Utilities/pxCheckBox.cpp +++ b/common/src/Utilities/pxCheckBox.cpp @@ -83,14 +83,14 @@ pxCheckBox& pxCheckBox::SetToolTip( const wxString& tip ) pxCheckBox& pxCheckBox::SetValue( bool val ) { - pxAssume( m_checkbox ); + pxAssert( m_checkbox ); m_checkbox->SetValue( val ); return *this; } pxCheckBox& pxCheckBox::SetIndeterminate() { - pxAssume( m_checkbox ); + pxAssert( m_checkbox ); m_checkbox->Set3StateValue( wxCHK_UNDETERMINED ); return *this; } @@ -98,7 +98,7 @@ pxCheckBox& pxCheckBox::SetIndeterminate() pxCheckBox& pxCheckBox::SetState( wxCheckBoxState state ) { - pxAssume( m_checkbox ); + pxAssert( m_checkbox ); m_checkbox->Set3StateValue( state ); return *this; } diff --git a/common/src/Utilities/pxStaticText.cpp b/common/src/Utilities/pxStaticText.cpp index 90947b4596bf5..2a0eb617d49f7 100644 --- a/common/src/Utilities/pxStaticText.cpp +++ b/common/src/Utilities/pxStaticText.cpp @@ -116,7 +116,7 @@ pxStaticText& pxStaticText::PaddingPixV( int pixels ) pxStaticText& pxStaticText::PaddingPctH( float pct ) { - pxAssume( pct < 0.5 ); + pxAssert( pct < 0.5 ); m_paddingPct_horiz = pct; UpdateWrapping( false ); @@ -126,7 +126,7 @@ pxStaticText& pxStaticText::PaddingPctH( float pct ) pxStaticText& pxStaticText::PaddingPctV( float pct ) { - pxAssume( pct < 0.5 ); + pxAssert( pct < 0.5 ); m_paddingPct_vert = pct; Refresh(); @@ -152,7 +152,7 @@ int pxStaticText::calcPaddingHeight( int newHeight ) const wxSize pxStaticText::GetBestWrappedSize( const wxClientDC& dc ) const { - pxAssume( m_autowrap ); + pxAssert( m_autowrap ); // Find an ideal(-ish) width, based on a search of all parent controls and their // valid Minimum sizes. diff --git a/common/src/Utilities/pxWindowTextWriter.cpp b/common/src/Utilities/pxWindowTextWriter.cpp index 3da69dff9ccef..bae8a02a20835 100644 --- a/common/src/Utilities/pxWindowTextWriter.cpp +++ b/common/src/Utilities/pxWindowTextWriter.cpp @@ -86,7 +86,7 @@ pxWindowTextWriter& pxWindowTextWriter::MoveY( int ydelta ) void pxWindowTextWriter::_DoWriteLn( const wxChar* msg ) { - pxAssume( msg ); + pxAssert( msg ); int tWidth, tHeight; m_dc.GetMultiLineTextExtent( msg, &tWidth, &tHeight ); @@ -110,7 +110,7 @@ void pxWindowTextWriter::_DoWriteLn( const wxChar* msg ) // to the text writer. void pxWindowTextWriter::_DoWrite( const wxChar* msg ) { - pxAssume( msg ); + pxAssert( msg ); wxArrayString parts; SplitString( parts, msg, L'\n' ); diff --git a/common/src/Utilities/wxAppWithHelpers.cpp b/common/src/Utilities/wxAppWithHelpers.cpp index a0a174bae7133..7b87bd85fcc0d 100644 --- a/common/src/Utilities/wxAppWithHelpers.cpp +++ b/common/src/Utilities/wxAppWithHelpers.cpp @@ -44,7 +44,7 @@ ConsoleLogSource_App pxConLog_App; void BaseDeletableObject::DoDeletion() { wxAppWithHelpers* app = wxDynamicCast( wxApp::GetInstance(), wxAppWithHelpers ); - pxAssume( app != NULL ); + pxAssert( app != NULL ); app->DeleteObject( *this ); } diff --git a/common/src/Utilities/wxGuiTools.cpp b/common/src/Utilities/wxGuiTools.cpp index 21bcd1af98a2b..5233324701420 100644 --- a/common/src/Utilities/wxGuiTools.cpp +++ b/common/src/Utilities/wxGuiTools.cpp @@ -616,6 +616,6 @@ wxFont pxGetFixedFont( int ptsize, int weight ) wxString pxGetAppName() { - pxAssume( wxTheApp ); + pxAssert( wxTheApp ); return wxTheApp->GetAppName(); } diff --git a/common/src/Utilities/wxHelpers.cpp b/common/src/Utilities/wxHelpers.cpp index 3d00dcadc798c..345a02fe2cdf4 100644 --- a/common/src/Utilities/wxHelpers.cpp +++ b/common/src/Utilities/wxHelpers.cpp @@ -368,7 +368,7 @@ void wxDialogWithHelpers::AddOkCancel( wxSizer &sizer, bool hasApply ) void wxDialogWithHelpers::AddOkCancel( wxSizer *sizer, bool hasApply ) { if( sizer == NULL ) sizer = GetSizer(); - pxAssume( sizer ); + pxAssert( sizer ); AddOkCancel( *sizer, hasApply ); } diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 45340dcf5612b..7fe440cc3fb3b 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -831,7 +831,7 @@ __fi void cdvdReadInterrupt() // Any other value besides 0 should be considered invalid here (wtf is that wacky // plugin trying to do?) - pxAssume( cdvd.RErr == 0 ); + pxAssert( cdvd.RErr == 0 ); } if (cdvd.nSectors > 0) @@ -844,7 +844,7 @@ __fi void cdvdReadInterrupt() // An arbitrary delay of some number of cycles probably makes more sense here, // but for now it's based on the cdvd.ReadTime value. -- air - pxAssume((int)cdvd.ReadTime > 0 ); + pxAssert((int)cdvd.ReadTime > 0 ); CDVDREAD_INT(cdvd.ReadTime/4); return; } diff --git a/pcsx2/CDVD/IsoFileFormats.cpp b/pcsx2/CDVD/IsoFileFormats.cpp index 3cb11359d49f7..453cf28ed92ff 100644 --- a/pcsx2/CDVD/IsoFileFormats.cpp +++ b/pcsx2/CDVD/IsoFileFormats.cpp @@ -185,14 +185,14 @@ void isoFile::_ReadBlockD(u8* dst, uint lsn) void isoFile::_ReadBlock(u8* dst, uint lsn) { - pxAssumeMsg(lsn <= m_blocks, "Invalid lsn passed into isoFile::_ReadBlock."); - pxAssumeMsg(m_numparts, "Invalid isoFile object state; an iso file needs at least one part!"); + pxAssertMsg(lsn <= m_blocks, "Invalid lsn passed into isoFile::_ReadBlock."); + pxAssertMsg(m_numparts, "Invalid isoFile object state; an iso file needs at least one part!"); uint i; for (i = 0; i < m_numparts-1; ++i) { // lsn indexes should always go in order; use an assertion just to be sure: - pxAssume(lsn >= m_parts[i].slsn); + pxAssert(lsn >= m_parts[i].slsn); if (lsn <= m_parts[i].elsn) break; } diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index 2a30dfda3e242..eb8a821942b6e 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -18,6 +18,7 @@ #include "Common.h" #include "Gif.h" +#include "Gif_Unit.h" #include "GS.h" #include "Vif.h" #include "Vif_Dma.h" @@ -55,6 +56,9 @@ void __fastcall ReadFIFO_VIF1(mem128_t* out) GetMTGS().WaitGS(); GSreadFIFO((u64*)out); vif1.GSLastDownloadSize--; +#if USE_OLD_GIF == 0 // d + GUNIT_LOG("ReadFIFO_VIF1"); +#endif if (vif1.GSLastDownloadSize <= 16) gifRegs.stat.OPH = false; vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize); @@ -100,12 +104,15 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value) if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 FIFO start!"); bool ret = VIF1transfer((u32*)value, 4); +#if USE_OLD_GIF == 1 // d if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2) { if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false; gifRegs.stat.APATH = GIF_APATH_IDLE; if(gifRegs.stat.P1Q) gsPath1Interrupt(); } +#endif + if (vif1.cmd) { if(vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING; @@ -120,6 +127,7 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value) void __fastcall WriteFIFO_GIF(const mem128_t *value) { +#if USE_OLD_GIF == 1 // d GIF_LOG("WriteFIFO/GIF <- %ls", value->ToString().c_str()); //CopyQWC(&psHu128(GIF_FIFO), value); @@ -139,4 +147,9 @@ void __fastcall WriteFIFO_GIF(const mem128_t *value) if(gifRegs.stat.P1Q) gsPath1Interrupt(); } } +#else + GUNIT_LOG("WriteFIFO_GIF()"); + gifUnit.TransferGSPacketData(GIF_TRANS_FIFO, (u8*)value, 16); +#endif } + diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 1e7c742c644a1..85152eb79400a 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -20,6 +20,7 @@ #include "GS.h" #include "Gif.h" +#include "Gif_Unit.h" #include "Counters.h" using namespace Threading; @@ -51,38 +52,35 @@ void gsInit() memzero(g_RealGSMem); } +#if USE_OLD_GIF == 1 // d extern bool SIGNAL_IMR_Pending; extern u32 SIGNAL_Data_Pending[2]; - -void gsGIFReset() -{ - gifRegs.stat.reset(); - gifRegs.ctrl.reset(); - gifRegs.mode.reset(); -} +#endif void gsReset() { GetMTGS().ResetGS(); UpdateVSyncRate(); - GSTransferStatus = (STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE; memzero(g_RealGSMem); +#if USE_OLD_GIF == 1 // d + GSTransferStatus = (STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE; SIGNAL_IMR_Pending = false; - CSRreg.Reset(); - GSIMR = 0x7f00; - // FIXME: This really doesn't belong here, and I seriously doubt it's needed. // If it is needed it should be in the GIF portion of hwReset(). --air - gsGIFReset(); + gifUnit.ResetRegs(); +#endif + + CSRreg.Reset(); + GSIMR = 0x7f00; } static __fi void gsCSRwrite( const tGS_CSR& csr ) { if (csr.RESET) { - +#if USE_OLD_GIF == 1 // ... // perform a soft reset -- which is a clearing of all GIFpaths -- and fall back to doing // a full reset if the plugin doesn't support soft resets. @@ -98,6 +96,13 @@ static __fi void gsCSRwrite( const tGS_CSR& csr ) } SIGNAL_IMR_Pending = false; +#else + GUNIT_WARN("csr.RESET"); + //gifUnit.Reset(true); // Don't think gif should be reset... + gifUnit.gsSIGNAL.queued = false; + GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0); +#endif + CSRreg.Reset(); GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 } @@ -110,6 +115,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr ) if(csr.SIGNAL) { +#if USE_OLD_GIF == 1 // d // SIGNAL : What's not known here is whether or not the SIGID register should be updated // here or when the IMR is cleared (below). @@ -119,8 +125,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr ) GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x",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]); - if (!(GSIMR&0x100)) - gsIrq(); + if (!(GSIMR&0x100)) gsIrq(); CSRreg.SIGNAL = true; //Just to be sure :P } @@ -129,6 +134,20 @@ static __fi void gsCSRwrite( const tGS_CSR& csr ) SIGNAL_IMR_Pending = false; if(gifRegs.stat.P1Q && gifRegs.stat.APATH <= GIF_APATH1) gsPath1Interrupt(); +#else + GUNIT_LOG("csr.SIGNAL"); + if (gifUnit.gsSIGNAL.queued) { + //DevCon.Warning("Firing pending signal"); + GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID & ~gifUnit.gsSIGNAL.data[1]) + | (gifUnit.gsSIGNAL.data[0]&gifUnit.gsSIGNAL.data[1]); + + if (!(GSIMR&0x100)) gsIrq(); + CSRreg.SIGNAL = true; // Just to be sure :P + } + else CSRreg.SIGNAL = false; + gifUnit.gsSIGNAL.queued = false; + gifUnit.Execute(); +#endif } if(csr.FINISH) CSRreg.FINISH = false; @@ -144,6 +163,7 @@ static __fi void IMRwrite(u32 value) if(CSRreg.GetInterruptMask() & (~(GSIMR >> 8) & 0x1f)) gsIrq(); +#if USE_OLD_GIF == 1 // d if( SIGNAL_IMR_Pending && !(GSIMR & 0x100)) { // Note: PS2 apps are expected to write a successive 1 and 0 to the IMR in order to @@ -159,6 +179,13 @@ static __fi void IMRwrite(u32 value) CSRreg.SIGNAL = true; gsIrq(); } +#else + GUNIT_LOG("IMRwrite()"); + if (gifUnit.gsSIGNAL.queued && !(GSIMR & 0x100)) { + CSRreg.SIGNAL = true; + gsIrq(); + } +#endif } __fi void gsWrite8(u32 mem, u8 value) @@ -166,7 +193,7 @@ __fi void gsWrite8(u32 mem, u8 value) switch (mem) { // CSR 8-bit write handlers. - // I'm quite sure these whould just write the CSR portion with the other + // I'm quite sure these would just write the CSR portion with the other // bits set to 0 (no action). The previous implementation masked the 8-bit // write value against the previous CSR write value, but that really doesn't // make any sense, given that the real hardware's CSR circuit probably has no @@ -280,8 +307,8 @@ void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value ) switch( mem ) { - case 0x12001040: //busdir - + case GS_BUSDIR: +#if USE_OLD_GIF == 1 // d //This is probably a complete hack, however writing to BUSDIR "should" start a transfer //Only problem is it kills killzone :(. // (yes it *is* a complete hack; both lines here in fact --air) @@ -294,12 +321,22 @@ void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value ) // // Yup folks. BUSDIR is evil. The only safe way to handle it is to flush the whole MTGS // and ensure complete MTGS and EEcore thread synchronization This is very slow, no doubt, - // but on the birght side BUSDIR is used quite rately, indeed. + // but on the bright side BUSDIR is used quite rarely, indeed. // Important: writeback to gsRegs area *prior* to flushing the MTGS. The flush will sync // the GS and MTGS register states, and upload our screwy busdir register in the process. :) gsWrite64_generic( mem, value ); GetMTGS().WaitGS(); +#else + GUNIT_LOG("GIF - busdir"); + gifRegs.stat.DIR = value[0] & 1; + if (gifRegs.stat.DIR) { // Assume will do local->host transfer? + gifRegs.stat.OPH = true; // Is OPH set on local->host transfers? + DevCon.WriteLn("Busdir - Local->Host Transfer"); + } + gsWrite64_generic( mem, value ); + GetMTGS().WaitGS(); +#endif return; case GS_CSR: @@ -461,7 +498,9 @@ void gsResetFrameSkip() void SaveStateBase::gsFreeze() { FreezeMem(PS2MEM_GS, 0x2000); +#if USE_OLD_GIF == 1 // d Freeze(SIGNAL_IMR_Pending); +#endif Freeze(gsRegionMode); gifPathFreeze(); diff --git a/pcsx2/GS.h b/pcsx2/GS.h index d79cbd9def51c..e3fac7b2c8ffa 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -17,6 +17,7 @@ #include "Common.h" #include "System/SysThreads.h" +#include "Gif.h" extern __aligned16 u8 g_RealGSMem[Ps2MemSize::GSregs]; @@ -222,19 +223,6 @@ enum GS_RegionMode Region_PAL }; -enum GIF_PATH -{ - GIF_PATH_1 = 0, - GIF_PATH_2, - GIF_PATH_3, -}; - -extern void GIFPath_Initialize(); -extern int GIFPath_CopyTag(GIF_PATH pathidx, const u128* pMem, u32 size); -extern int GIFPath_ParseTagQuick(GIF_PATH pathidx, const u8* pMem, u32 size); -extern void GIFPath_Reset(); -extern void GIFPath_Clear( GIF_PATH pathidx ); - extern GS_RegionMode gsRegionMode; ///////////////////////////////////////////////////////////////////////////// @@ -256,6 +244,7 @@ enum MTGS_RingCommand , GS_RINGTYPE_SOFTRESET // issues a soft reset for the GIF , GS_RINGTYPE_MODECHANGE // for issued mode changes. , GS_RINGTYPE_CRC +, GS_RINGTYPE_GSPACKET }; @@ -326,6 +315,7 @@ class SysMtgsThread : public SysThreadBase void WaitForOpen(); void Freeze( int mode, MTGS_FreezeData& data ); + void SendSimpleGSPacket( MTGS_RingCommand type, u32 offset, u32 size, GIF_PATH path ); void SendSimplePacket( MTGS_RingCommand type, int data0, int data1, int data2 ); void SendPointerPacket( MTGS_RingCommand type, u32 data0, void* data1 ); @@ -377,10 +367,6 @@ extern void gsFrameSkip(); // Some functions shared by both the GS and MTGS extern void _gs_ResetFrameskip(); - -// used for resetting GIF fifo -extern void gsGIFReset(); - extern void gsWrite8(u32 mem, u8 value); extern void gsWrite16(u32 mem, u16 value); extern void gsWrite32(u32 mem, u32 value); @@ -449,5 +435,30 @@ extern __aligned(32) MTGS_BufferedData RingBuffer; // FIXME: These belong in common with other memcpy tools. Will move them there later if no one // else beats me to it. --air -extern void MemCopy_WrappedDest( const u128* src, u128* destBase, uint& destStart, uint destSize, uint len ); -extern void MemCopy_WrappedSrc( const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len ); +inline void MemCopy_WrappedDest( const u128* src, u128* destBase, uint& destStart, uint destSize, uint len ) { + uint endpos = destStart + len; + if ( endpos < destSize ) { + memcpy_qwc(&destBase[destStart], src, len ); + destStart += len; + } + else { + uint firstcopylen = destSize - destStart; + memcpy_qwc(&destBase[destStart], src, firstcopylen ); + destStart = endpos % destSize; + memcpy_qwc(destBase, src+firstcopylen, destStart ); + } +} + +inline void MemCopy_WrappedSrc( const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len ) { + uint endpos = srcStart + len; + if ( endpos < srcSize ) { + memcpy_qwc(dest, &srcBase[srcStart], len ); + srcStart += len; + } + else { + uint firstcopylen = srcSize - srcStart; + memcpy_qwc(dest, &srcBase[srcStart], firstcopylen ); + srcStart = endpos % srcSize; + memcpy_qwc(dest+firstcopylen, srcBase, srcStart ); + } +} diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 804fe9ea7244b..2b9fba5cb4d9a 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -18,6 +18,7 @@ #include "GS.h" #include "Gif.h" +#include "Gif_Unit.h" #include "Vif_Dma.h" #include "iR5900.h" @@ -26,71 +27,54 @@ using std::min; // A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished). // Should be a gifstate_t rather then int, but I don't feel like possibly interfering with savestates right now. -static int gifstate = GIF_STATE_READY; - +static int gifstate = GIF_STATE_READY; static bool gspath3done = false; static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0; static u32 gifqwc = 0; static bool gifmfifoirq = false; +#if USE_OLD_GIF == 1 // d + //Just some temporary bits to store Path1 transfers if another is in progress. __aligned16 u8 Path1Buffer[0x1000000]; u32 Path1WritePos = 0; u32 Path1ReadPos = 0; -static __fi void clearFIFOstuff(bool full) -{ - if (full) - CSRreg.FIFO = CSR_FIFO_FULL; - else - CSRreg.FIFO = CSR_FIFO_EMPTY; -} extern bool SIGNAL_IMR_Pending; void gsPath1Interrupt() { - //DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos); - - - - if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true)) && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false) - { + if ((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true)) + && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false) { gifRegs.stat.P1Q = false; - if (uint size = (Path1WritePos - Path1ReadPos)) - { + if (uint size = (Path1WritePos - Path1ReadPos)) { GetMTGS().PrepDataPacket(GIF_PATH_1, size); //DevCon.Warning("Flush Size = %x", size); - while(size > 0 && SIGNAL_IMR_Pending == false) - { + while(size > 0 && SIGNAL_IMR_Pending == false) { uint count = GIFPath_CopyTag(GIF_PATH_1, ((u128*)Path1Buffer) + Path1ReadPos, size); Path1ReadPos += count; size -= count; - if(GSTransferStatus.PTH1 == STOPPED_MODE) - { + if(GSTransferStatus.PTH1 == STOPPED_MODE) { gifRegs.stat.OPH = false; gifRegs.stat.APATH = GIF_APATH_IDLE; } } GetMTGS().SendDataPacket(); - if(Path1ReadPos == Path1WritePos) - { + if (Path1ReadPos == Path1WritePos) { Path1WritePos = Path1ReadPos = 0; } - else - { + else { //DevCon.Warning("Queue quitting early due to signal or EOP %x", size); gifRegs.stat.P1Q = true; } } } - else - { + else { if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL"); - if(gifRegs.stat.P1Q == false && Path1ReadPos != Path1WritePos) - { + if(gifRegs.stat.P1Q == false && Path1ReadPos != Path1WritePos) { DevCon.Warning("Wa's Goin on ere then?"); gifRegs.stat.P1Q = true; } @@ -99,51 +83,59 @@ void gsPath1Interrupt() } } +#endif -extern bool SIGNAL_IMR_Pending; +static __fi void clearFIFOstuff(bool full) { + if (full) CSRreg.FIFO = CSR_FIFO_FULL; + else CSRreg.FIFO = CSR_FIFO_EMPTY; +} + +void incGifChAddr(u32 qwc) { + if (gifch.chcr.STR) { + gifch.madr += qwc * 16; + gifch.qwc -= qwc; + hwDmacSrcTadrInc(gifch); + } + else DevCon.Error("incGifAddr() Error!"); +} -__fi void gsInterrupt() +__fi void gifInterrupt() { - GIF_LOG("gsInterrupt caught!"); + GIF_LOG("gifInterrupt caught!"); - if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO - { + if (dmacRegs.ctrl.MFD == MFD_GIF) { // GIF MFIFO //Console.WriteLn("GIF MFIFO"); gifMFIFOInterrupt(); return; } - if(SIGNAL_IMR_Pending == true) - { +#if USE_OLD_GIF == 1 // d + if(SIGNAL_IMR_Pending == true) { //DevCon.Warning("Path 3 Paused"); CPU_INT(DMAC_GIF, 128); return; } - if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE) - { + if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE) { GSTransferStatus.PTH3 = STOPPED_MODE; - - if(gifRegs.stat.APATH == GIF_APATH3) - { + if(gifRegs.stat.APATH == GIF_APATH3) { gifRegs.stat.APATH = GIF_APATH_IDLE; gifRegs.stat.OPH = false; if(gifRegs.stat.P1Q) gsPath1Interrupt(); } } - - - if (!(gifch.chcr.STR)) - { - //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gifch.chcr._u32, gifch.qwc, done); +#else + if (gifUnit.gsSIGNAL.queued) { + //DevCon.WriteLn("Path 3 Paused"); + CPU_INT(DMAC_GIF, 128); return; } +#endif + + if (!(gifch.chcr.STR)) return; - - if ((gifch.qwc > 0) || (!gspath3done)) - { - if (!dmacRegs.ctrl.DMAE) - { + if ((gifch.qwc > 0) || (!gspath3done)) { + if (!dmacRegs.ctrl.DMAE) { Console.Warning("gs dma masked, re-scheduling..."); // re-raise the int shortly in the future CPU_INT( DMAC_GIF, 64 ); @@ -154,16 +146,11 @@ __fi void gsInterrupt() return; } - gspath3done = false; - gscycles = 0; - gifch.chcr.STR = false; - - //// - /*gifRegs.stat.OPH = false; - GSTransferStatus.PTH3 = STOPPED_MODE; - gifRegs.stat.APATH = GIF_APATH_IDLE;*/ - //// gifRegs.stat.clear_flags(GIF_STAT_FQC); + + gscycles = 0; + gspath3done = false; + gifch.chcr.STR = false; clearFIFOstuff(false); hwDmacIrq(DMAC_GIF); DMA_LOG("GIF DMA End"); @@ -171,15 +158,16 @@ __fi void gsInterrupt() static u32 WRITERING_DMA(u32 *pMem, u32 qwc) { +#if USE_OLD_GIF == 1 // d GetMTGS().PrepDataPacket(GIF_PATH_3, qwc); - uint size = GIFPath_CopyTag(GIF_PATH_3, (u128*)pMem, qwc ); + uint size = GIFPath_CopyTag(GIF_PATH_3, (u128*)pMem, qwc); GetMTGS().SendDataPacket(); return size; -} - -static u32 WRITERING_DMA(tDMA_TAG *pMem, u32 qwc) -{ - return WRITERING_DMA((u32*)pMem, qwc); +#else + uint size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc*16) / 16; + incGifChAddr(size); + return size; +#endif } int _GIFchain() @@ -187,23 +175,23 @@ int _GIFchain() tDMA_TAG *pMem; pMem = dmaGetAddr(gifch.madr, false); - if (pMem == NULL) - { + if (pMem == NULL) { + +#if USE_OLD_GIF == 1 // d // reset path3, fixes dark cloud 2 GIFPath_Clear( GIF_PATH_3 ); - +#endif //must increment madr and clear qwc, else it loops gifch.madr += gifch.qwc * 16; gifch.qwc = 0; - Console.Warning( "Hackfix - NULL GIFchain" ); + Console.Warning("Hackfix - NULL GIFchain"); return -1; } - return WRITERING_DMA(pMem, gifch.qwc); + return WRITERING_DMA((u32*)pMem, gifch.qwc); } -static __fi void GIFchain() -{ +static __fi void GIFchain() { // qwc check now done outside this function // Voodoocycles // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge.. @@ -212,13 +200,11 @@ static __fi void GIFchain() static __fi bool checkTieBit(tDMA_TAG* &ptag) { - if (gifch.chcr.TIE && ptag->IRQ) - { + if (gifch.chcr.TIE && ptag->IRQ) { GIF_LOG("dmaIrq Set"); gspath3done = true; return true; } - return false; } @@ -246,27 +232,24 @@ static __fi tDMA_TAG* ReadTag2() return ptag; } -bool CheckPaths(int Channel) +bool CheckPaths(EE_EventType Channel) { - if((GSTransferStatus.PTH3 == IMAGE_MODE && gifRegs.mode.IMT) /*|| GSTransferStatus.PTH3 == WAITING_MODE*/) - { - if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3)) - { - if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true) - { - //DevCon.Warning("GIF Stall 1 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd); - gifRegs.stat.IP3 = true; - if(gifRegs.stat.P1Q) gsPath1Interrupt(); - CPU_INT(DMAC_GIF, 16); - return false; +#if USE_OLD_GIF == 1 // d + if((GSTransferStatus.PTH3 == IMAGE_MODE && gifRegs.mode.IMT) /*|| GSTransferStatus.PTH3 == WAITING_MODE*/) { + if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3)) { + if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true) { + //DevCon.Warning("GIF Stall 1 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd); + gifRegs.stat.IP3 = true; + if(gifRegs.stat.P1Q) gsPath1Interrupt(); + CPU_INT(DMAC_GIF, 16); + return false; } } } - else if(GSTransferStatus.PTH3 == STOPPED_MODE) - { - //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed). - if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3) || vif1Regs.stat.VGW == true) - { + else if(GSTransferStatus.PTH3 == STOPPED_MODE) { + //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == finished). + if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) + || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3) || vif1Regs.stat.VGW == true) { //DevCon.Warning("GIF Stall 2 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd); gifRegs.stat.IP3 = true; if(gifRegs.stat.P1Q) gsPath1Interrupt(); @@ -274,41 +257,40 @@ bool CheckPaths(int Channel) return false; } } - + gifRegs.stat.IP3 = false; +#else + // Can't do Path 3, so try dma again later... + if(!gifUnit.CanDoPath3()) { + CPU_INT(Channel, 128); + return false; + } +#endif return true; } void GIFdma() { tDMA_TAG *ptag; - gscycles = prevcycles; - if (gifRegs.ctrl.PSE) // temporarily stop - { + if (gifRegs.ctrl.PSE) { // temporarily stop Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)"); CPU_INT(DMAC_GIF, 16); return; } - if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0)) - { + if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0)) { //Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR)); - - if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) - { + if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) { CPU_INT(DMAC_GIF, 4); gscycles = 0; return; } - prevcycles = 0; gifch.qwc = 0; } - - if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done) && gifch.qwc == 0) // Chain Mode { ptag = ReadTag(); @@ -340,10 +322,9 @@ void GIFdma() clearFIFOstuff(true); gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] - if (vif1Regs.mskpath3 || gifRegs.mode.M3R) - { - if (GSTransferStatus.PTH3 == STOPPED_MODE) - { +#if USE_OLD_GIF == 1 // ... + if (vif1Regs.mskpath3 || gifRegs.mode.M3R) { + if (GSTransferStatus.PTH3 == STOPPED_MODE) { MSKPATH3_LOG("Path3 Paused by VIF QWC %x", gifch.qwc); if(gifch.qwc == 0) CPU_INT(DMAC_GIF, 4); @@ -351,18 +332,20 @@ void GIFdma() return; } } +#endif // Transfer Dn_QWC from Dn_MADR to GIF if (gifch.qwc > 0) // Normal Mode { gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] +#if USE_OLD_GIF == 1 // ... gifRegs.stat.set_flags(GIF_STAT_P3Q); - - if(CheckPaths(DMAC_GIF) == false) - return; - + if(CheckPaths(DMAC_GIF) == false) return; gifRegs.stat.clear_flags(GIF_STAT_P3Q); +#else + if(CheckPaths(DMAC_GIF) == false) return; +#endif GIFchain(); //Transfers the data set by the switch CPU_INT(DMAC_GIF, gscycles); @@ -389,34 +372,27 @@ void dmaGIF() } clearFIFOstuff(true); - if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) - { + if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) { //DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc()); - if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END)) - { + if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END)) { gspath3done = true; } } - - - gsInterrupt(); + gifInterrupt(); } static u16 QWCinGIFMFIFO(u32 DrainADDR) { u32 ret; - GIF_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR); //Calculate what we have in the fifo. - if(DrainADDR <= spr0ch.madr) - { + if(DrainADDR <= spr0ch.madr) { //Drain is below the tadr, calculate the difference between them ret = (spr0ch.madr - DrainADDR) >> 4; } - else - { + else { u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16; //Drain is higher than SPR so it has looped round, //calculate from base to the SPR tag addr and what is left in the top of the ring @@ -427,14 +403,13 @@ static u16 QWCinGIFMFIFO(u32 DrainADDR) return ret; } -// called from only one location, so forceinline it: static __fi bool mfifoGIFrbTransfer() { u16 mfifoqwc = min(QWCinGIFMFIFO(gifch.madr), gifch.qwc); - u32 *src; - - if(mfifoqwc == 0) return true; //Lets skip all this, we don't have the data + if (mfifoqwc == 0) return true; //Lets skip all this, we don't have the data +#if USE_OLD_GIF == 1 // d + u32 *src; GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc); // TODO (minor optimization): The new GIFpath parser can do rather efficient wrapping of @@ -442,8 +417,8 @@ static __fi bool mfifoGIFrbTransfer() // memory similarly to how it wraps VU1 memory on PATH1. GIF_LOG("MFIFO QWC to Transfer %x", mfifoqwc); /* Check if the transfer should wrap around the ring buffer */ - if ( (gifch.madr + (mfifoqwc * 16)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) - { + if ( (gifch.madr + (mfifoqwc * 16)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) { + DevCon.Warning("0mfifoGIFrbTransfer() - Wrap [%d]", mfifoqwc); uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4; uint s2 = (mfifoqwc - s1); GIF_LOG("Split transfer doing %x QWC of %x Total QWC", s1, mfifoqwc); @@ -455,8 +430,7 @@ static __fi bool mfifoGIFrbTransfer() if (src == NULL) return false; uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1); - if (copied == s1) // but only copy second if first didn't abort prematurely for some reason. - { + if (copied == s1) { // but only copy second if first didn't abort prematurely for some reason. GIF_LOG("Transferring last %x QWC", s2); src = (u32*)PSM(dmacRegs.rbor.ADDR); gifch.madr = dmacRegs.rbor.ADDR; @@ -466,9 +440,10 @@ static __fi bool mfifoGIFrbTransfer() mfifoqwc = copied; GIF_LOG("Copied %x QWC, %x QWC Left", mfifoqwc, gifch.qwc); + DevCon.Warning("1mfifoGIFrbTransfer() - Wrap [%d]", mfifoqwc); } - else - { + else { + //DevCon.WriteLn("mfifoGIFrbTransfer() - Norm[%d]", mfifoqwc*16); GIF_LOG("Direct MFIFO transfer doing %x Total QWC", mfifoqwc); /* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */ @@ -480,20 +455,45 @@ static __fi bool mfifoGIFrbTransfer() } GetMTGS().SendDataPacket(); - //gifqwc -= mfifoqwc; - mfifocycles += (mfifoqwc) * 2; /* guessing */ - + mfifocycles += (mfifoqwc) * 2; // guessing +#else + if(!gifUnit.CanDoPath3()) { + DevCon.Warning("mfifoGIFrbTransfer() - Can't do path3"); + return true; // Skip if can't do path3 + } + + bool needWrap = (gifch.madr + (mfifoqwc * 16)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16); + uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4; + uint s2 = mfifoqwc - s1; + uint s3 = needWrap ? s1 : mfifoqwc; + + gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK); + u8* src = (u8*)PSM(gifch.madr); + if (src == NULL) return false; + u32 t1 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s3*16) / 16; // First part + incGifChAddr(t1); + mfifocycles += t1 * 2; // guessing + + if (needWrap && t1) { // Need to do second transfer to wrap around + GUNIT_WARN("mfifoGIFrbTransfer() - Wrap"); + src = (u8*)PSM(dmacRegs.rbor.ADDR); + gifch.madr = dmacRegs.rbor.ADDR; + if (src == NULL) return false; + u32 t2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s2*16) / 16; // Second part + incGifChAddr(t2); + mfifocycles += t2 * 2; // guessing + } +#endif return true; } -// called from only one location, so forceinline it: static __fi bool mfifoGIFchain() { /* Is QWC = 0? if so there is nothing to transfer */ if (gifch.qwc == 0) return true; if (gifch.madr >= dmacRegs.rbor.ADDR && - gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) + gifch.madr <=(dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) { bool ret = true; // if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF"); @@ -505,57 +505,47 @@ static __fi bool mfifoGIFchain() gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK); //Check this too, tadr can suffer the same issue. return ret; - } - else - { + else { int mfifoqwc; GIF_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc); tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false); if (pMem == NULL) return false; - mfifoqwc = WRITERING_DMA(pMem, gifch.qwc); + mfifoqwc = WRITERING_DMA((u32*)pMem, gifch.qwc); mfifocycles += (mfifoqwc) * 2; /* guessing */ } return true; } -static u32 qwctag(u32 mask) -{ +static u32 qwctag(u32 mask) { return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK)); } void mfifoGIFtransfer(int qwc) { tDMA_TAG *ptag; - mfifocycles = 0; gifmfifoirq = false; - if(qwc > 0 ) - { - if ((gifstate & GIF_STATE_EMPTY)) - { + if (qwc > 0 ) { + if ((gifstate & GIF_STATE_EMPTY)) { if(gifch.chcr.STR == true && !(cpuRegs.interrupt & (1<IRQ)) - { + if ((gifch.chcr.TIE) && (ptag->IRQ)) { SPR_LOG("dmaIrq Set"); gifstate = GIF_STATE_DONE; gifmfifoirq = true; @@ -581,6 +570,7 @@ void mfifoGIFtransfer(int qwc) if (QWCinGIFMFIFO(gifch.tadr) == 0) gifstate |= GIF_STATE_EMPTY; } +#if USE_OLD_GIF == 1 // ... if (vif1Regs.mskpath3 || gifRegs.mode.M3R) { if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate |= GIF_STATE_STALL; @@ -594,8 +584,9 @@ void mfifoGIFtransfer(int qwc) return; } } - if (!mfifoGIFchain()) - { +#endif + + if (!mfifoGIFchain()) { Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr); gifstate = GIF_STATE_STALL; } @@ -611,38 +602,42 @@ void gifMFIFOInterrupt() GIF_LOG("gifMFIFOInterrupt"); mfifocycles = 0; - if (dmacRegs.ctrl.MFD != MFD_GIF) - { + if (dmacRegs.ctrl.MFD != MFD_GIF) { DevCon.Warning("Not in GIF MFIFO mode! Stopping GIF MFIFO"); return; } - if(SIGNAL_IMR_Pending == true) - { +#if USE_OLD_GIF == 1 // d + if(SIGNAL_IMR_Pending == true) { //DevCon.Warning("Path 3 Paused"); CPU_INT(DMAC_MFIFO_GIF, 128); return; } - if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE) - { + if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE) { GSTransferStatus.PTH3 = STOPPED_MODE; - - if(gifRegs.stat.APATH == GIF_APATH3) - { + if(gifRegs.stat.APATH == GIF_APATH3) { gifRegs.stat.APATH = GIF_APATH_IDLE; gifRegs.stat.OPH = false; if(gifRegs.stat.P1Q) gsPath1Interrupt(); } } +#else + if (gifUnit.gsSIGNAL.queued) { + //DevCon.WriteLn("Path 3 Paused"); + CPU_INT(DMAC_MFIFO_GIF, 128); + return; + } +#endif - if((gifstate & GIF_STATE_EMPTY)) - { + if((gifstate & GIF_STATE_EMPTY)) { FireMFIFOEmpty(); if(!(gifstate & GIF_STATE_STALL)) return; } - if(CheckPaths(11) == false) return; +#if USE_OLD_GIF == 1 // d +#endif + if(CheckPaths(DMAC_MFIFO_GIF) == false) return; if (!(gifch.chcr.STR)) { @@ -665,8 +660,7 @@ void gifMFIFOInterrupt() } #ifdef PCSX2_DEVBUILD - if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0)) - { + if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0)) { Console.Error("gifMFIFO Panic > Shouldn't go here!"); return; } @@ -677,9 +671,13 @@ void gifMFIFOInterrupt() gspath3done = false; gscycles = 0; +#if USE_OLD_GIF == 1 // d gifRegs.stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0 - vif1Regs.stat.VGW = false; +#else + gifRegs.stat.clear_flags(GIF_STAT_FQC); // FQC = 0 +#endif + gifch.chcr.STR = false; gifstate = GIF_STATE_READY; hwDmacIrq(DMAC_GIF); @@ -687,7 +685,7 @@ void gifMFIFOInterrupt() clearFIFOstuff(false); } -void SaveStateBase::gifFreeze() +void SaveStateBase::gifDmaFreeze() { FreezeTag( "GIFdma" ); @@ -697,21 +695,21 @@ void SaveStateBase::gifFreeze() Freeze( gscycles ); // Note: mfifocycles is not a persistent var, so no need to save it here. +#if USE_OLD_GIF == 1 // d int bufsize = Path1WritePos - Path1ReadPos; Freeze(bufsize); - if (IsSaving()) - { + if(!IsSaving()) { // We can just load the queued Path1 data into the front of the buffer, and // reset the ReadPos and WritePos accordingly. FreezeMem(Path1Buffer, bufsize); Path1ReadPos = 0; Path1WritePos = bufsize; } - else - { + else { // Only want to save the actual Path1 data between readpos and writepos. The // rest of the buffer is just unused-ness! FreezeMem(&Path1Buffer[Path1ReadPos], bufsize); } +#endif } diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index d02ddf14c9f68..cb546483ab648 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -13,19 +13,57 @@ * If not, see . */ -#ifndef __GIF_H__ -#define __GIF_H__ +#pragma once -enum gifstate_t -{ +#define USE_OLD_GIF 0 +#define COPY_GS_PACKET_TO_MTGS 0 + +//#define GUNIT_LOG DevCon.WriteLn +#define GUNIT_LOG(...) do {} while(0) + +//#define GUNIT_WARN DevCon.WriteLn +#define GUNIT_WARN(...) do {} while(0) + +enum GIF_PATH { + GIF_PATH_1 = 0, + GIF_PATH_2, + GIF_PATH_3, +}; + +// Lower byte contains path minus 1 +enum GIF_TRANSFER_TYPE { + GIF_TRANS_INVALID = 0x000, // Invalid + GIF_TRANS_XGKICK = 0x100, // Path 1 + GIF_TRANS_DIRECT = 0x201, // Path 2 + GIF_TRANS_DIRECTHL = 0x301, // Path 2 + GIF_TRANS_DMA = 0x402, // Path 3 + GIF_TRANS_FIFO = 0x502 // Path 3 +}; + +static const char Gif_TransferStr[6][32] = { + "Invalid Transfer Type", + "GIF_TRANS_XGKICK", + "GIF_TRANS_DIRECT", + "GIF_TRANS_DIRECTHL", + "GIF_TRANS_DMA", + "GIF_TRANS_FIFO" +}; + +enum GIF_PATH_STATE { + GIF_PATH_IDLE = 0, // Path is idle (hasn't started a GS packet) + GIF_PATH_PACKED = 1, // Path is on a PACKED gif tag + GIF_PATH_REGLIST = 2, // Path is on a REGLIST gif tag + GIF_PATH_IMAGE = 3 // Path is on a IMAGE gif tag +}; + +enum gifstate_t { GIF_STATE_READY = 0, GIF_STATE_STALL = 1, - GIF_STATE_DONE = 2, + GIF_STATE_DONE = 2, GIF_STATE_EMPTY = 0x10 }; -enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet -{ +enum GSTransferModes { // 0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet WAITING_MODE = 0, IMAGE_MODE = 1, TRANSFER_MODE = 2, @@ -50,9 +88,9 @@ union tGSTransferStatus { void reset() { _u32 = 0; } wxString desc() const { return wxsFormat(L"GSTransferStatus.PTH3: 0x%x", _u32); } }; + //GIF_STAT -enum gif_stat_flags -{ +enum gif_stat_flags { GIF_STAT_M3R = (1), // GIF_MODE Mask GIF_STAT_M3P = (1<<1), // VIF PATH3 Mask GIF_STAT_IMT = (1<<2), // Intermittent Transfer Mode @@ -69,16 +107,40 @@ enum gif_stat_flags GIF_STAT_FQC = (31<<24) // QWC in GIF-FIFO }; -enum gif_mode_flags -{ +enum gif_mode_flags { GIF_MODE_M3R = (1), - GIF_MODE_IMT = (1<<2) + GIF_MODE_IMT = (1<<2) +}; + +enum GIF_FLG { + GIF_FLG_PACKED = 0, + GIF_FLG_REGLIST = 1, + GIF_FLG_IMAGE = 2, + GIF_FLG_IMAGE2 = 3 +}; + +enum GIF_REG { + GIF_REG_PRIM = 0x00, + GIF_REG_RGBA = 0x01, + GIF_REG_STQ = 0x02, + GIF_REG_UV = 0x03, + GIF_REG_XYZF2 = 0x04, + GIF_REG_XYZ2 = 0x05, + GIF_REG_TEX0_1 = 0x06, + GIF_REG_TEX0_2 = 0x07, + GIF_REG_CLAMP_1 = 0x08, + GIF_REG_CLAMP_2 = 0x09, + GIF_REG_FOG = 0x0a, + GIF_REG_INVALID = 0x0b, + GIF_REG_XYZF3 = 0x0c, + GIF_REG_XYZ3 = 0x0d, + GIF_REG_A_D = 0x0e, + GIF_REG_NOP = 0x0f, }; union tGIF_CTRL { - struct - { + struct { u32 RST : 1; u32 reserved1 : 2; u32 PSE : 1; @@ -88,6 +150,7 @@ union tGIF_CTRL tGIF_CTRL(u32 val) { _u32 = val; } + void write(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } @@ -97,8 +160,7 @@ union tGIF_CTRL union tGIF_MODE { - struct - { + struct { u32 M3R : 1; u32 reserved1 : 1; u32 IMT : 1; @@ -116,8 +178,7 @@ union tGIF_MODE wxString desc() { return wxsFormat(L"Mode: 0x%x", _u32); } }; -enum gif_paths -{ +enum gif_paths { GIF_APATH_IDLE = 0, GIF_APATH1, GIF_APATH2, @@ -126,28 +187,28 @@ enum gif_paths union tGIF_STAT { - struct - { - u32 M3R : 1; - u32 M3P : 1; - u32 IMT : 1; - u32 PSE : 1; - u32 reserved1 : 1; - u32 IP3 : 1; - u32 P3Q : 1; - u32 P2Q : 1; - u32 P1Q : 1; - u32 OPH : 1; - u32 APATH : 2; - u32 DIR : 1; - u32 reserved2 : 11; - u32 FQC : 5; - u32 reserved3 : 3; + struct { + u32 M3R : 1; // GIF_MODE Mask + u32 M3P : 1; // VIF PATH3 Mask + u32 IMT : 1; // Intermittent Transfer Mode + u32 PSE : 1; // Temporary Transfer Stop + u32 reserved1 : 1; // ... + u32 IP3 : 1; // Interrupted PATH3 + u32 P3Q : 1; // PATH3 request Queued + u32 P2Q : 1; // PATH2 request Queued + u32 P1Q : 1; // PATH1 request Queued + u32 OPH : 1; // Output Path (Outputting Data) + u32 APATH : 2; // Data Transfer Path (In progress) + u32 DIR : 1; // Transfer Direction + u32 reserved2 : 11; // ... + u32 FQC : 5; // QWC in GIF-FIFO + u32 reserved3 : 3; // ... }; u32 _u32; tGIF_STAT(u32 val) { _u32 = val; } + void write(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } @@ -157,8 +218,7 @@ union tGIF_STAT union tGIF_TAG0 { - struct - { + struct { u32 NLOOP : 15; u32 EOP : 1; u32 TAG : 16; @@ -176,8 +236,7 @@ union tGIF_TAG0 union tGIF_TAG1 { - struct - { + struct { u32 TAG : 14; u32 PRE : 1; u32 PRIM : 11; @@ -197,8 +256,7 @@ union tGIF_TAG1 union tGIF_CNT { - struct - { + struct { u32 LOOPCNT : 15; u32 reserved1 : 1; u32 REGCNT : 4; @@ -219,8 +277,7 @@ union tGIF_CNT union tGIF_P3CNT { - struct - { + struct { u32 P3CNT : 15; u32 reserved1 : 17; }; @@ -234,8 +291,7 @@ union tGIF_P3CNT union tGIF_P3TAG { - struct - { + struct { u32 LOOPCNT : 15; u32 EOP : 1; u32 reserved1 : 16; @@ -279,18 +335,28 @@ struct GIFregisters static GIFregisters& gifRegs = (GIFregisters&)eeHw[0x3000]; -extern tGSTransferStatus GSTransferStatus; - -extern void gsInterrupt(); +extern void gifInterrupt(); extern int _GIFchain(); extern void GIFdma(); extern void dmaGIF(); extern void mfifoGIFtransfer(int qwc); extern void gifMFIFOInterrupt(); +#if USE_OLD_GIF == 1 // d +extern u8 schedulepath3msk; +extern tGSTransferStatus GSTransferStatus; +extern bool CheckPath2GIF(EE_EventType channel); + //Just some temporary bits to store Path1 transfers if another is in progress. extern void gsPath1Interrupt(); extern __aligned16 u8 Path1Buffer[0x1000000]; extern u32 Path1WritePos; extern u32 Path1ReadPos; + +extern void GIFPath_Initialize(); +extern int GIFPath_CopyTag(GIF_PATH pathidx, const u128* pMem, u32 size); +extern int GIFPath_ParseTagQuick(GIF_PATH pathidx, const u8* pMem, u32 size); +extern void GIFPath_Reset(); +extern void GIFPath_Clear( GIF_PATH pathidx ); #endif + diff --git a/pcsx2/Gif_Unit.cpp b/pcsx2/Gif_Unit.cpp new file mode 100644 index 0000000000000..0fc899005013d --- /dev/null +++ b/pcsx2/Gif_Unit.cpp @@ -0,0 +1,136 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#include "PrecompiledHeader.h" +#include "Common.h" + +#include "GS.h" +#include "Gif_Unit.h" +#include "Vif_Dma.h" + +Gif_Unit gifUnit; + +// Returns true on stalling SIGNAL +bool Gif_HandlerAD(u8* pMem) { + u32 reg = pMem[8]; + u32* data = (u32*)pMem; + if (reg == 0x50) vif1.BITBLTBUF._u64 = *(u64*)pMem; + elif (reg == 0x52) vif1.TRXREG._u64 = *(u64*)pMem; + elif (reg == 0x53) { + if ((pMem[0] & 3) == 1) { // local -> host + u8 bpp = 32; + switch(vif1.BITBLTBUF.SPSM & 7) { + case 0: bpp = 32; break; + case 1: bpp = 24; break; + case 2: bpp = 16; break; + case 3: bpp = 8; break; + default: // 4 is 4 bit but this is forbidden + Console.Error("Illegal format for GS upload: SPSM=0%02o", vif1.BITBLTBUF.SPSM); + break; + } + // qwords, rounded down; any extra bits are lost + // games must take care to ensure transfer rectangles are exact multiples of a qword + vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7; + } + } + elif (reg == 0x60) { // SIGNAL + if (CSRreg.SIGNAL) { // Time to ignore all subsequent drawing operations. + GUNIT_WARN(Color_Orange, "GIF Handler - Stalling SIGNAL"); + if(!gifUnit.gsSIGNAL.queued) { + gifUnit.gsSIGNAL.queued = true; + gifUnit.gsSIGNAL.data[0] = data[0]; + gifUnit.gsSIGNAL.data[1] = data[1]; + return true; // Stalling SIGNAL + } + } + else { + GUNIT_WARN("GIF Handler - SIGNAL"); + GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~data[1])|(data[0]&data[1]); + if (!(GSIMR&0x100)) gsIrq(); + CSRreg.SIGNAL = true; + } + } + elif (reg == 0x61) { // FINISH + GUNIT_WARN("GIF Handler - FINISH"); + CSRreg.FINISH = true; + } + elif (reg == 0x62) { // LABEL + GUNIT_WARN("GIF Handler - LABEL"); + GSSIGLBLID.LBLID = (GSSIGLBLID.LBLID&~data[1])|(data[0]&data[1]); + } + elif (reg >= 0x63 && reg != 0x7f) { + DevCon.Warning("GIF Handler - Write to unknown register! [reg=%x]", reg); + } + return false; +} + +void Gif_FinishIRQ() { + if (CSRreg.FINISH && !(GSIMR&0x200)) { + gsIrq(); + } +} + +void Gif_AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path) { + //DevCon.WriteLn("Adding Completed Gif Packet [size=%x]", gsPack.size); + if (COPY_GS_PACKET_TO_MTGS) { + GetMTGS().PrepDataPacket(path, gsPack.size/16); + MemCopy_WrappedDest((u128*)&gifUnit.gifPath[path].buffer[gsPack.offset], RingBuffer.m_Ring, + GetMTGS().m_packet_writepos, RingBufferSize, gsPack.size/16); + GetMTGS().SendDataPacket(); + } + else { + AtomicExchangeAdd(gifUnit.gifPath[path].readAmount, gsPack.size); + GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, gsPack.offset, gsPack.size, path); + } +} + +void Gif_AddBlankGSPacket(u32 size, GIF_PATH path) { + //DevCon.WriteLn("Adding Blank Gif Packet [size=%x]", size); + AtomicExchangeAdd(gifUnit.gifPath[path].readAmount, size); + GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, ~0u, size, path); +} + +void Gif_MTGS_Wait() { + GetMTGS().WaitGS(); +} + +void Gif_Execute() { + gifUnit.Execute(); +} + +void SaveStateBase::gifPathFreeze(u32 path) { + + Gif_Path& gifPath = gifUnit.gifPath[path]; + pxAssertDev(gifPath.readAmount==0, "Gif Path readAmount should be 0!"); + if (IsSaving()) { // Move all the buffered data to the start of buffer + gifPath.RealignPacket(); // May add readAmount which we need to clear on load + } + u8* bufferPtr = gifPath.buffer; // Backup current buffer ptr + Freeze(gifPath); + FreezeMem(bufferPtr, gifPath.curSize); + gifPath.buffer = bufferPtr; + if (!IsSaving()) gifPath.readAmount = 0; +} + +void SaveStateBase::gifFreeze() { + Gif_MTGS_Wait(); + FreezeTag("Gif Unit"); + Freeze(gifUnit.stat); + Freeze(gifUnit.gsSIGNAL); + Freeze(gifUnit.lastTranType); + gifPathFreeze(GIF_PATH_1); + gifPathFreeze(GIF_PATH_2); + gifPathFreeze(GIF_PATH_3); +} diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h new file mode 100644 index 0000000000000..f49207a7daf62 --- /dev/null +++ b/pcsx2/Gif_Unit.h @@ -0,0 +1,451 @@ + +#pragma once +#include "System/SysThreads.h" +extern void Gif_FinishIRQ(); +extern bool Gif_HandlerAD(u8* pMem); + +struct Gif_Tag { + struct HW_Gif_Tag { + u16 NLOOP : 15; + u16 EOP : 1; + u16 _dummy0 : 16; + u32 _dummy1 : 14; + u32 PRE : 1; + u32 PRIM : 11; + u32 FLG : 2; + u32 NREG : 4; + u32 REGS[2]; + } tag; + + u32 nLoop; // NLOOP left to process + u32 nRegs; // NREG (1~16) + u32 nRegIdx; // Current nReg Index (packed mode processing) + u32 len; // Packet Length in Bytes (not including tag) + u32 cycles; // Time needed to process packet data in ee-cycles + u8 regs[16]; // Regs + bool hasAD; // Has an A+D Write + bool isValid; // Tag is valid + + Gif_Tag() { Reset(); } + Gif_Tag(u8* pMem, bool analyze = false) { + setTag (pMem, analyze); + } + + void Reset() { memzero(*this); } + u8 curReg() { return regs[nRegIdx&0xf]; } + + void packedStep() { + if (nLoop > 0) { + nRegIdx++; + if (nRegIdx >= nRegs) { + nRegIdx = 0; + nLoop--; + } + } + } + + void setTag(u8* pMem, bool analyze = false) { + tag = *(HW_Gif_Tag*)pMem; + nLoop = tag.NLOOP; + hasAD = false; + nRegIdx = 0; + isValid = 1; + switch(tag.FLG) { + case GIF_FLG_PACKED: + nRegs = ((tag.NREG-1)&0xf) + 1; + len = (nRegs * tag.NLOOP)* 16; + cycles = len << 1; // Packed Mode takes 2 ee-cycles + if (analyze) analyzeTag(); + break; + case GIF_FLG_REGLIST: + nRegs = ((tag.NREG-1)&0xf) + 1; + len =((nRegs * tag.NLOOP + 1) >> 1) * 16; + cycles = len << 2; // Reg-list Mode takes 4 ee-cycles + break; + case GIF_FLG_IMAGE: + case GIF_FLG_IMAGE2: + nRegs = 0; + len = tag.NLOOP * 16; + cycles = len << 2; // Image Mode takes 4 ee-cycles + tag.FLG = GIF_FLG_IMAGE; + break; + jNO_DEFAULT; + } + } + + void analyzeTag() { + hasAD = false; + u32 t = tag.REGS[0]; + for(u32 i = 0; i < nRegs; i++) { + if (i == 8) t = tag.REGS[1]; + regs[i] = t & 0xf; + hasAD |= (regs[i] == GIF_REG_A_D); + t >>= 4; + } + } +}; + +struct GS_Packet { + u32 offset; // Path buffer offset for start of packet + u32 size; // Full size of GS-Packet + s32 cycles; // EE Cycles taken to process this GS packet + bool done; // 0 = Incomplete, 1 = Complete + GS_Packet() { Reset(); } + void Reset() { memzero(*this); } +}; + +struct GS_SIGNAL { + u32 data[2]; + bool queued; + void Reset() { memzero(*this); } +}; + +__fi void incTag(u32& offset, u32& size, u32 incAmount) { + size += incAmount; + offset += incAmount; +} + +struct Gif_Path { + volatile s32 __aligned(4) readAmount; // Amount of data MTGS still needs to read + u8* buffer; // Path packet buffer + u32 buffSize; // Full size of buffer + u32 buffLimit; // Cut off limit to wrap around + u32 curSize; // Used buffer in bytes + u32 curOffset; // Offset of current gifTag + Gif_Tag gifTag; // Current GS Primitive tag + GS_Packet gsPack; // Current GS Packet info + GIF_PATH idx; // Gif Path Index + GIF_PATH_STATE state; // Path State + + Gif_Path() {} + ~Gif_Path() { _aligned_free(buffer); } + + void Init(GIF_PATH _idx, u32 _buffSize, u32 _buffSafeZone) { + idx = _idx; + buffSize = _buffSize; + buffLimit = _buffSize - _buffSafeZone; + buffer = (u8*)_aligned_malloc(buffSize, 16); + Reset(); + } + + void Reset(bool softReset = false) { + state = GIF_PATH_IDLE; + if (softReset) { + GUNIT_WARN("Gif Path %d - Soft Reset", idx+1); + //gifTag.Reset(); + //gsPack.Reset(); + //curOffset = curSize; + return; + } + curSize = 0; + curOffset = 0; + readAmount = 0; + gifTag.Reset(); + gsPack.Reset(); + } + + bool hasDataRemaining() { return curOffset < curSize; } + bool isDone() { return !hasDataRemaining() && state == GIF_PATH_IDLE; } + + // Waits on the MTGS to process gs packets + void mtgsReadWait() { + //pxAssertDev(AtomicExchangeAdd(readAmount, 0) != 0, "Gif Path Buffer Overflow!"); + DevCon.WriteLn(Color_Red, "Gif Path[%d] - MTGS Wait! [r=0x%x]", + idx+1, AtomicExchangeAdd(readAmount, 0)); + extern void Gif_MTGS_Wait(); + Gif_MTGS_Wait(); + } + + // Moves packet data to start of buffer + void RealignPacket() { + extern void Gif_AddBlankGSPacket(u32 size, GIF_PATH path); + GUNIT_LOG("Path Buffer: Realigning packet!"); + s32 offset = curOffset - gsPack.size; + s32 sizeToAdd = curSize - offset; + s32 intersect = sizeToAdd - offset; + if (intersect < 0) intersect = 0; + for(;;) { + s32 frontFree = offset - AtomicExchangeAdd(readAmount, 0); + if (frontFree >= sizeToAdd - intersect) break; + mtgsReadWait(); + } + if (offset < (s32)buffLimit) { // Needed for correct readAmount values + Gif_AddBlankGSPacket(buffLimit - offset, idx); + } + //DevCon.WriteLn("Realign Packet [%d]", curSize - offset); + if (intersect) memmove(buffer, &buffer[offset], curSize - offset); + else memcpy_fast(buffer, &buffer[offset], curSize - offset); + curSize -= offset; + curOffset = gsPack.size; + gsPack.offset = 0; + } + + void CopyGSPacketData(u8* pMem, u32 size, bool aligned = false) { + if (curSize + size > buffSize) { // Move gsPack to front of buffer + DevCon.Warning("CopyGSPacketData: Realigning packet!"); + RealignPacket(); + } + for(;;) { + s32 offset = curOffset - gsPack.size; + s32 readPos = offset - AtomicExchangeAdd(readAmount, 0); + if (readPos >= 0) break; // MTGS is reading in back of curOffset + if ((s32)buffLimit + readPos > (s32)curSize + (s32)size) break; // Enough free front space + mtgsReadWait(); // Let MTGS run to free up buffer space + } + pxAssertDev(curSize+size<=buffSize, "Gif Path Buffer Overflow!"); + if (aligned) memcpy_qwc (&buffer[curSize], pMem, size/16); + else memcpy_fast(&buffer[curSize], pMem, size); + curSize += size; + } + + // If completed a GS packet (with EOP) then returned GS_Packet.done = 1 + GS_Packet ExecuteGSPacket() { + for(;;) { + if (!gifTag.isValid) { // Need new Gif Tag + // We don't have enough data for a Gif Tag + if (curOffset + 16 > curSize) { + GUNIT_LOG("Path Buffer: Not enough data for gif tag! [%d]", curSize-curOffset); + return gsPack; + } + + // Move packet to start of buffer + if (curOffset > buffLimit) { + RealignPacket(); + } + + gifTag.setTag(&buffer[curOffset], 1); + state = (GIF_PATH_STATE)(gifTag.tag.FLG + 1); + + // We don't have enough data for a complete GS packet + if (curOffset + 16 + gifTag.len > curSize) { + gifTag.isValid = false; // So next time we test again + return gsPack; + } + + incTag(curOffset, gsPack.size, 16); // Tag Size + gsPack.cycles += 2 + gifTag.cycles; // Tag + Len ee-cycles + } + + if (gifTag.hasAD) { // Only can be true if GIF_FLG_PACKED + bool dblSIGNAL = false; + while(gifTag.nLoop && !dblSIGNAL) { + if (gifTag.curReg() == GIF_REG_A_D) { + dblSIGNAL = Gif_HandlerAD(&buffer[curOffset]); + } + incTag(curOffset, gsPack.size, 16); // 1 QWC + gifTag.packedStep(); + } + if (dblSIGNAL && !(gifTag.tag.EOP && !gifTag.nLoop)) return gsPack; // Exit Early + } + else incTag(curOffset, gsPack.size, gifTag.len); // Data length + + // Reload gif tag next loop + gifTag.isValid = false; + + if (gifTag.tag.EOP) { + GS_Packet t = gsPack; + t.done = 1; + state = GIF_PATH_IDLE; + gsPack.Reset(); + gsPack.offset = curOffset; + return t; // Complete GS packet + } + } + } +}; + +struct Gif_Unit { + Gif_Path gifPath[3]; + GS_SIGNAL gsSIGNAL; // Stalling Signal + tGIF_STAT& stat; + GIF_TRANSFER_TYPE lastTranType; // Last Transfer Type + + Gif_Unit() : stat(gifRegs.stat) { + gifPath[0].Init(GIF_PATH_1, _1mb*8, _16kb + _1kb); + gifPath[1].Init(GIF_PATH_2, _1mb*8, _1mb + _1kb); + gifPath[2].Init(GIF_PATH_3, _1mb*9, _1mb + _1kb); + } + + // Enable softReset when resetting during game emulation + void Reset(bool softReset = false) { + GUNIT_WARN(Color_Red, "Gif Unit Reset!!! [soft=%d]", softReset); + ResetRegs(); + gsSIGNAL.Reset(); + gifPath[0].Reset(softReset); + gifPath[1].Reset(softReset); + gifPath[2].Reset(softReset); + if(!softReset) { + lastTranType = GIF_TRANS_INVALID; + } + } + + // Resets Gif HW Regs + void ResetRegs() { + gifRegs.stat.reset(); + gifRegs.ctrl.reset(); + gifRegs.mode.reset(); + } + + // Adds a finished GS Packet to the MTGS ring buffer + __fi void AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path) { + extern void Gif_AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path); + Gif_AddCompletedGSPacket(gsPack, path); + } + + // Returns GS Packet Size in bytes + u32 GetGSPacketSize(GIF_PATH pathIdx, u8* pMem, u32 offset = 0) { + u32 memMask = pathIdx ? 0xffffffffu : 0x3fffu; + u32 size = 0; + for(;;) { + Gif_Tag gifTag(&pMem[offset & memMask]); + incTag(offset, size, 16 + gifTag.len); // Tag + Data length + if (pathIdx == GIF_PATH_1 && size >= 0x4000) { + Console.Warning("Gif Unit - GS packet size exceeded VU memory size!"); + return 0; // Bios does this... (Fixed if you delay vu1's xgkick by 103 vu cycles) + } + if (gifTag.tag.EOP) { + return size; + } + } + } + + // Specify the transfer type you are initiating + // The return value is the amount of data (in bytes) that was processed + // If transfer cannot take place at this moment the return value is 0 + u32 TransferGSPacketData(GIF_TRANSFER_TYPE tranType, u8* pMem, u32 size, bool aligned=false) { + + GIF_LOG("%s - [path=%d][size=%d]", Gif_TransferStr[(tranType>>8)&0xf], (tranType&3)+1, size); + if (size == 0) { GUNIT_WARN("Gif Unit - Size == 0"); return 0; } + if(!CanDoGif()) { GUNIT_WARN("Gif Unit - PSE Set or Dir = GS to EE"); } + pxAssertDev((stat.APATH==0) || checkPaths(1,1,1), "Gif Unit - APATH wasn't cleared?"); + lastTranType = tranType; // Used for Vif FlushA hack + + if (tranType == GIF_TRANS_FIFO) { + if(!CanDoPath3()) DevCon.Warning("Gif Unit - Path 3 FIFO transfer while !CanDoPath3()"); + } + if (tranType == GIF_TRANS_DMA) { + if(!CanDoPath3()) { if (!Path3Masked()) stat.P3Q = 1; return 0; } // DMA Stall + } + if (tranType == GIF_TRANS_XGKICK) { + if(!CanDoPath1()) { stat.P1Q = 1; } // We always buffer path1 packets + } + if (tranType == GIF_TRANS_DIRECT) { + if(!CanDoPath2()) { stat.P2Q = 1; return 0; } // Direct Stall + } + if (tranType == GIF_TRANS_DIRECTHL) { + if(!CanDoPath2HL()) { stat.P2Q = 1; return 0; } // DirectHL Stall + } + + gifPath[tranType&3].CopyGSPacketData(pMem, size, aligned); + Execute(); + return size; + } + + // Checks path activity for the given paths + // Returns an int with a bit enabled if the corresponding + // path is not finished (needs more data/processing for an EOP) + __fi int checkPaths(bool p1, bool p2, bool p3, bool checkQ=false) { + int ret = 0; + ret |= (p1 && !gifPath[GIF_PATH_1].isDone()) << 0; + ret |= (p2 && !gifPath[GIF_PATH_2].isDone()) << 1; + ret |= (p3 && !gifPath[GIF_PATH_3].isDone()) << 2; + return ret | (checkQ ? checkQueued(p1,p2,p3) : 0); + } + + __fi int checkQueued(bool p1, bool p2, bool p3) { + int ret = 0; + ret |= (p1 && stat.P1Q) << 0; + ret |= (p2 && stat.P2Q) << 1; + ret |= (p3 && stat.P3Q) << 2; + return ret; + } + + // Processes gif packets and performs path arbitration + // according to path priority... + void Execute() { + if (!CanDoGif()) { DevCon.Error("Gif Unit - Signal or PSE Set or Dir = GS to EE"); return; } + bool didPath3 = false; + stat.OPH = 1; + for(;;) { + if (stat.APATH) { // Some Transfer is happening + GS_Packet gsPack = gifPath[stat.APATH-1].ExecuteGSPacket(); + if(!gsPack.done) { + if (stat.APATH == 3 && CanDoP3Slice() && !gsSIGNAL.queued) { + if(!didPath3 && checkPaths(1,1,0)) { // Path3 slicing + didPath3 = true; + stat.APATH = 0; + stat.IP3 = 1; + GUNIT_LOG(Color_Magenta, "Gif Unit - Path 3 slicing arbitration"); + if (gsPack.size > 16) { // Packet had other tags which we already processed + Gif_Path& p3 = gifPath[GIF_PATH_3]; + u32 subOffset = p3.gifTag.isValid ? 16 : 0; // if isValid, image-primitive not finished + gsPack.size -= subOffset; // Remove the image-tag (should be last thing read) + AddCompletedGSPacket(gsPack, GIF_PATH_3); // Consider current packet complete + p3.gsPack.Reset(); // Reset gs packet info + p3.curOffset -= subOffset; // Start the next GS packet at the image-tag + p3.gsPack.offset = p3.curOffset; // Set to image-tag + p3.gifTag.isValid = false; // Reload tag next ExecuteGSPacket() + pxAssert((s32)p3.curOffset >= 0); + pxAssert(p3.state == GIF_PATH_IMAGE); + GUNIT_LOG(Color_Magenta, "Gif Unit - Sending path 3 sliced gs packet!"); + } + continue; + } + } + //DevCon.WriteLn("Incomplete GS Packet for path %d", stat.APATH); + break; // Not finished with GS packet + } + //DevCon.WriteLn("Adding GS Packet for path %d", stat.APATH); + AddCompletedGSPacket(gsPack, (GIF_PATH)(stat.APATH-1)); + } + if (!gsSIGNAL.queued && checkPaths(1,0,0,0)) { stat.APATH = 1; stat.P1Q = 0; } + elif (!gsSIGNAL.queued && checkPaths(0,1,0,0)) { stat.APATH = 2; stat.P2Q = 0; } + elif (!gsSIGNAL.queued && checkPaths(0,0,1,0) && !Path3Masked()) + { stat.APATH = 3; stat.P3Q = 0; stat.IP3 = 0; } + else { stat.APATH = 0; stat.OPH = 0; break; } + } + Gif_FinishIRQ(); // hmm + //DevCon.WriteLn("APATH = %d [%d,%d,%d]", stat.APATH, !!checkPaths(1,0,0,0),!!checkPaths(0,1,0,0),!!checkPaths(0,0,1,0)); + } + + // XGkick + bool CanDoPath1() { return (stat.APATH == 0 || stat.APATH == 1 + || (stat.APATH == 3 && CanDoP3Slice())) + && (CanDoGif() == 1); } + // Direct + bool CanDoPath2() { return (stat.APATH == 0 || stat.APATH == 2 + || (stat.APATH == 3 && CanDoP3Slice())) + && (CanDoGif() == 1); } + // DirectHL + bool CanDoPath2HL() { return (stat.APATH == 0 || stat.APATH == 2) + && (CanDoGif() == 1); } + // Gif DMA + bool CanDoPath3() { return((stat.APATH == 0 && !Path3Masked()) + || stat.APATH == 3) + && (CanDoGif() == 1); } + + bool CanDoP3Slice() { return stat.IMT == 1 && gifPath[GIF_PATH_3].state == GIF_PATH_IMAGE; } + bool CanDoGif() { return stat.PSE == 0 && stat.DIR == 0 && gsSIGNAL.queued == 0; } + bool Path3Masked() { return stat.M3R || stat.M3P; } + + void PrintInfo(bool printP1=1, bool printP2=1, bool printP3=1) { + u32 a = checkPaths(1,1,1), b = checkQueued(1,1,1); + GUNIT_LOG("Gif Unit - LastTransfer = %s, Paths = [%d,%d,%d], Queued = [%d,%d,%d]", + Gif_TransferStr[(lastTranType>>8)&0xf], + !!(a&1),!!(a&2),!!(a&4),!!(b&1),!!(b&2),!!(b&4)); + GUNIT_LOG("Gif Unit - [APATH = %d][Signal = %d][PSE = %d][DIR = %d]", + stat.APATH, gsSIGNAL.queued, stat.PSE, stat.DIR); + GUNIT_LOG("Gif Unit - [CanDoGif = %d][CanDoPath3 = %d][CanDoP3Slice = %d]", + CanDoGif(), CanDoPath3(), CanDoP3Slice()); + if (printP1) PrintPathInfo(GIF_PATH_1); + if (printP2) PrintPathInfo(GIF_PATH_2); + if (printP3) PrintPathInfo(GIF_PATH_3); + } + + void PrintPathInfo(GIF_PATH path) { + GUNIT_LOG("Gif Path %d - [hasData = %d][state = %d]", path, + gifPath[path].hasDataRemaining(), gifPath[path].state); + } +}; + +extern Gif_Unit gifUnit; diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 0b0650839438c..a009de4a1cd61 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -19,6 +19,8 @@ #include "Hardware.h" #include "newVif.h" #include "IPU/IPUdma.h" +#include "Gif.h" +#include "Gif_Unit.h" using namespace R5900; @@ -73,6 +75,7 @@ void hwReset() sprInit(); gsReset(); + gifUnit.Reset(); ipuReset(); vif0Reset(); vif1Reset(); @@ -145,14 +148,14 @@ void FireMFIFOEmpty() hwDmacIrq(DMAC_MFIFO_EMPTY); if (dmacRegs.ctrl.MFD == MFD_VIF1) vif1Regs.stat.FQC = 0; - else if (dmacRegs.ctrl.MFD == MFD_GIF) gifRegs.stat.FQC = 0; + if (dmacRegs.ctrl.MFD == MFD_GIF) gifRegs.stat.FQC = 0; } // Write 'size' bytes to memory address 'addr' from 'data'. __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc) { // all FIFO addresses should always be QWC-aligned. - pxAssume((dmacRegs.rbor.ADDR & 15) == 0); - pxAssume((addr & 15) == 0); + pxAssert((dmacRegs.rbor.ADDR & 15) == 0); + pxAssert((addr & 15) == 0); if(qwc > ((dmacRegs.rbsr.RMSK + 16) >> 4)) DevCon.Warning("MFIFO Write bigger than MFIFO! QWC=%x FifoSize=%x", qwc, ((dmacRegs.rbsr.RMSK + 16) >> 4)); // DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index d1c1b98b17afd..bcae960515d3e 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -17,6 +17,8 @@ #include "PrecompiledHeader.h" #include "Common.h" #include "Hardware.h" +#include "Gif.h" +#include "Gif_Unit.h" #include "ps2/HwInternal.h" #include "ps2/eeHwTraceLog.inl" @@ -88,16 +90,17 @@ void __fastcall _hwWrite32( u32 mem, u32 value ) { icase(GIF_CTRL) { - psHu32(mem) = value & 0x8; - - if (value & 0x1) - gsGIFReset(); - - if (value & 8) - gifRegs.stat.PSE = true; - else - gifRegs.stat.PSE = false; - + // Not exactly sure what RST needs to do + gifRegs.ctrl.write(value & 9); + if (gifRegs.ctrl.RST) { +#if USE_OLD_GIF == 1 // d + gifUnit.ResetRegs(); // hmm? +#else + GUNIT_LOG("GIF CTRL - Reset"); + gifUnit.Reset(true); // hmm? +#endif + } + gifRegs.stat.PSE = gifRegs.ctrl.PSE; return; } @@ -110,7 +113,6 @@ void __fastcall _hwWrite32( u32 mem, u32 value ) const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT; psHu32(GIF_STAT) &= ~bitmask; psHu32(GIF_STAT) |= (u32)value & bitmask; - return; } } diff --git a/pcsx2/IPU/IPU_Fifo.cpp b/pcsx2/IPU/IPU_Fifo.cpp index cc35dc268cb25..25017c713fffa 100644 --- a/pcsx2/IPU/IPU_Fifo.cpp +++ b/pcsx2/IPU/IPU_Fifo.cpp @@ -106,7 +106,7 @@ int IPU_Fifo_Input::read(void *value) int IPU_Fifo_Output::write(const u32 *value, uint size) { - pxAssumeMsg(size>0, "Invalid size==0 when calling IPU_Fifo_Output::write"); + pxAssertMsg(size>0, "Invalid size==0 when calling IPU_Fifo_Output::write"); uint origsize = size; /*do {*/ @@ -131,7 +131,7 @@ int IPU_Fifo_Output::write(const u32 *value, uint size) void IPU_Fifo_Output::read(void *value, uint size) { - pxAssume(ipuRegs.ctrl.OFC >= size); + pxAssert(ipuRegs.ctrl.OFC >= size); ipuRegs.ctrl.OFC -= size; // Zeroing the read data is not needed, since the ringbuffer design will never read back diff --git a/pcsx2/IPU/IPUdma.cpp b/pcsx2/IPU/IPUdma.cpp index 9c1d0c2d777dc..a2da4faddfc24 100644 --- a/pcsx2/IPU/IPUdma.cpp +++ b/pcsx2/IPU/IPUdma.cpp @@ -73,31 +73,6 @@ static __fi void ipuDmacSrcChain() } } -static __fi bool WaitGSPaths() -{ - if(CHECK_IPUWAITHACK) - { - if(GSTransferStatus.PTH3 < STOPPED_MODE && GSTransferStatus.PTH3 != IDLE_MODE) - { - //GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc); - //DevCon.WriteLn("Waiting for GIF"); - return false; - } - - if(GSTransferStatus.PTH2 != STOPPED_MODE) - { - //DevCon.WriteLn("Waiting for VIF"); - return false; - } - if(GSTransferStatus.PTH1 != STOPPED_MODE) - { - //DevCon.WriteLn("Waiting for VU"); - return false; - } - } - return true; -} - static __fi int IPU1chain() { int totalqwc = 0; @@ -131,21 +106,6 @@ static __fi int IPU1chain() { return totalqwc; } -//static __fi bool WaitGSPaths() -//{ -// //Wait for all GS paths to be clear -// if (GSTransferStatus._u32 != 0x2a) -// { -// if(GSTransferStatus.PTH3 != STOPPED_MODE && vif1Regs.mskpath3) return true; -// IPU_LOG("Waiting for GS transfers to finish %x", GSTransferStatus._u32); -// IPU_INT_TO(4); -// return false; -// } -// return true; -//} - - - int IPU1dma() { int ipu1cycles = 0; diff --git a/pcsx2/IPU/mpeg2lib/Mpeg.cpp b/pcsx2/IPU/mpeg2lib/Mpeg.cpp index 72ba1af9b633e..1e6e3af025ed0 100644 --- a/pcsx2/IPU/mpeg2lib/Mpeg.cpp +++ b/pcsx2/IPU/mpeg2lib/Mpeg.cpp @@ -808,7 +808,7 @@ __fi bool mpeg2sliceIDEC() case 2: { - pxAssume(decoder.ipu0_data > 0); + pxAssert(decoder.ipu0_data > 0); uint read = ipu_fifo.out.write((u32*)decoder.GetIpuDataPtr(), decoder.ipu0_data); decoder.AdvanceIpuDataBy(read); @@ -1113,7 +1113,7 @@ __fi bool mpeg2_slice() case 3: { - pxAssume(decoder.ipu0_data > 0); + pxAssert(decoder.ipu0_data > 0); uint read = ipu_fifo.out.write((u32*)decoder.GetIpuDataPtr(), decoder.ipu0_data); decoder.AdvanceIpuDataBy(read); diff --git a/pcsx2/IPU/mpeg2lib/Mpeg.h b/pcsx2/IPU/mpeg2lib/Mpeg.h index 982007ed6cd02..a2eef26ba2102 100644 --- a/pcsx2/IPU/mpeg2lib/Mpeg.h +++ b/pcsx2/IPU/mpeg2lib/Mpeg.h @@ -174,8 +174,8 @@ struct decoder_t { void AdvanceIpuDataBy(uint amt) { - pxAssumeMsg(ipu0_data>=amt, "IPU FIFO Overflow on advance!" ); - ipu0_idx += amt; + pxAssertMsg(ipu0_data>=amt, "IPU FIFO Overflow on advance!" ); + ipu0_idx += amt; ipu0_data -= amt; } }; diff --git a/pcsx2/IopMem.cpp b/pcsx2/IopMem.cpp index e623b35c951de..4a711652e84c8 100644 --- a/pcsx2/IopMem.cpp +++ b/pcsx2/IopMem.cpp @@ -50,7 +50,7 @@ void iopMemoryReserve::Reset() { _parent::Reset(); - pxAssume( iopMem ); + pxAssert( iopMem ); if (!psxMemWLUT) { diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index a1faa20e87a07..c28eb0ee7853d 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -20,6 +20,7 @@ #include #include "GS.h" +#include "Gif_Unit.h" #include "Elfheader.h" #include "SamplProf.h" @@ -114,7 +115,12 @@ void SysMtgsThread::ResetGS() SendSimplePacket( GS_RINGTYPE_FRAMESKIP, 0, 0, 0 ); SetEvent(); +#if USE_OLD_GIF == 1 // d GIFPath_Reset(); +#else + //DevCon.WriteLn("ResetGS()"); + //gifUnit.Reset(); +#endif } struct RingCmdPacket_Vsync @@ -328,6 +334,7 @@ void SysMtgsThread::ExecuteTaskInThread() switch( tag.command ) { +#if USE_OLD_GIF == 1 || COPY_GS_PACKET_TO_MTGS == 1 // d case GS_RINGTYPE_P1: { uint datapos = (m_ReadPos+1) & RingBufferMask; @@ -402,6 +409,15 @@ void SysMtgsThread::ExecuteTaskInThread() ringposinc += qsize; } break; +#endif + case GS_RINGTYPE_GSPACKET: { + Gif_Path& path = gifUnit.gifPath[tag.data[2]]; + u32 offset = tag.data[0]; + u32 size = tag.data[1]; + if (offset != ~0u) GSgifTransfer((u32*)&path.buffer[offset], size/16); + AtomicExchangeSub(path.readAmount, size); + break; + } default: { @@ -590,7 +606,7 @@ void SysMtgsThread::WaitGS() // For use in loops that wait on the GS thread to do certain things. void SysMtgsThread::SetEvent() { - if( !m_RingBufferIsBusy ) + if(!m_RingBufferIsBusy) m_sem_event.Post(); m_CopyDataTally = 0; @@ -770,6 +786,18 @@ void SysMtgsThread::SendSimplePacket( MTGS_RingCommand type, int data0, int data _FinishSimplePacket(); } +void SysMtgsThread::SendSimpleGSPacket(MTGS_RingCommand type, u32 offset, u32 size, GIF_PATH path) +{ + SendSimplePacket(type, (int)offset, (int)size, (int)path); + + if(!EmuConfig.GS.SynchronousMTGS) { + if(!m_RingBufferIsBusy) { + m_CopyDataTally += size / 16; + if (m_CopyDataTally > 0x2000) SetEvent(); + } + } +} + void SysMtgsThread::SendPointerPacket( MTGS_RingCommand type, u32 data0, void* data1 ) { //ScopedLock locker( m_PacketLocker ); diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index beee3cdc40eed..5192d62fae6a1 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -837,7 +837,7 @@ static __aligned16 vtlb_PageProtectionInfo m_PageProtectInfo[Ps2MemSize::MainRam // int mmap_GetRamPageInfo( u32 paddr ) { - pxAssume( eeMem ); + pxAssert( eeMem ); paddr &= ~0xfff; @@ -854,7 +854,7 @@ int mmap_GetRamPageInfo( u32 paddr ) // paddr - physically mapped PS2 address void mmap_MarkCountedRamPage( u32 paddr ) { - pxAssume( eeMem ); + pxAssert( eeMem ); paddr &= ~0xfff; @@ -883,7 +883,7 @@ void mmap_MarkCountedRamPage( u32 paddr ) // from code residing in this page will use manual protection. static __fi void mmap_ClearCpuBlock( uint offset ) { - pxAssume( eeMem ); + pxAssert( eeMem ); int rampage = offset >> 12; @@ -899,7 +899,7 @@ static __fi void mmap_ClearCpuBlock( uint offset ) void mmap_PageFaultHandler::OnPageFaultEvent( const PageFaultInfo& info, bool& handled ) { - pxAssume( eeMem ); + pxAssert( eeMem ); // get bad virtual address uptr offset = info.addr - (uptr)eeMem->Main; diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 7441bdaf7eb04..92b91306b7c91 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -227,7 +227,7 @@ static void CALLBACK GS_gifTransferLegacy( const u32* src, u32 data ) if (src128 == RingBuffer.m_Ring) { - pxAssume( (data+path1size) <= 0x400 ); + pxAssert( (data+path1size) <= 0x400 ); memcpy_qwc( &path1queue[path1size], src128, data ); path1size += data; } @@ -951,7 +951,7 @@ SysCorePlugins::~SysCorePlugins() throw() void SysCorePlugins::Load( PluginsEnum_t pid, const wxString& srcfile ) { ScopedLock lock( m_mtx_PluginStatus ); - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); Console.Indent().WriteLn( L"Binding %s\t: %s ", tbl_PluginInfo[pid].GetShortname().c_str(), srcfile.c_str() ); m_info[pid] = new PluginStatus_t( pid, srcfile ); } @@ -1017,7 +1017,7 @@ void SysCorePlugins::Load( const wxString (&folders)[PluginId_Count] ) void SysCorePlugins::Unload(PluginsEnum_t pid) { ScopedLock lock( m_mtx_PluginStatus ); - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); m_info[pid].Delete(); } @@ -1119,7 +1119,7 @@ bool SysCorePlugins::OpenPlugin_Mcd() void SysCorePlugins::Open( PluginsEnum_t pid ) { - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); if( IsOpen(pid) ) return; Console.Indent().WriteLn( "Opening %s", tbl_PluginInfo[pid].shortname ); @@ -1240,7 +1240,7 @@ void SysCorePlugins::ClosePlugin_Mcd() void SysCorePlugins::Close( PluginsEnum_t pid ) { - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); if( !IsOpen(pid) ) return; @@ -1653,21 +1653,21 @@ bool SysCorePlugins::AreAnyInitialized() const bool SysCorePlugins::IsOpen( PluginsEnum_t pid ) const { - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); ScopedLock lock( m_mtx_PluginStatus ); return m_info[pid] && m_info[pid]->IsInitialized && m_info[pid]->IsOpened; } bool SysCorePlugins::IsInitialized( PluginsEnum_t pid ) const { - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); ScopedLock lock( m_mtx_PluginStatus ); return m_info[pid] && m_info[pid]->IsInitialized; } bool SysCorePlugins::IsLoaded( PluginsEnum_t pid ) const { - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); return !!m_info[pid]; } @@ -1732,13 +1732,13 @@ bool SysCorePlugins::NeedsClose() const const wxString SysCorePlugins::GetName( PluginsEnum_t pid ) const { ScopedLock lock( m_mtx_PluginStatus ); - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); return m_info[pid] ? m_info[pid]->Name : (wxString)_("Unloaded Plugin"); } const wxString SysCorePlugins::GetVersion( PluginsEnum_t pid ) const { ScopedLock lock( m_mtx_PluginStatus ); - pxAssume( (uint)pid < PluginId_Count ); + pxAssert( (uint)pid < PluginId_Count ); return m_info[pid] ? m_info[pid]->Version : L"0.0"; } diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index ba00a969542bf..f698f02784063 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -278,10 +278,13 @@ static __fi void _cpuTestInterrupts() that depends on the cycle timings */ TESTINT(DMAC_VIF1, vif1Interrupt); - TESTINT(DMAC_GIF, gsInterrupt); + TESTINT(DMAC_GIF, gifInterrupt); TESTINT(DMAC_SIF0, EEsif0Interrupt); TESTINT(DMAC_SIF1, EEsif1Interrupt); + //extern void Gif_Execute(); + //TESTINT(DMAC_GIF_UNIT, Gif_Execute); + // Profile-guided Optimization (sorta) // The following ints are rarely called. Encasing them in a conditional // as follows helps speed up most games. @@ -488,7 +491,7 @@ __fi void cpuTestHwInts() { __fi void CPU_INT( EE_EventType n, s32 ecycle) { - if( n != 2 && cpuRegs.interrupt & (1< Twice-thrown int on IRQ %d", n ); } diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 227bc9018f30e..b57952bd8e96c 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -404,7 +404,9 @@ enum EE_EventType // We're setting error conditions through hwDmacIrq, so these correspond to the conditions above. DMAC_STALL_SIS = 13, // SIS DMAC_MFIFO_EMPTY = 14, // MEIS - DMAC_BUS_ERROR = 15 // BEIS + DMAC_BUS_ERROR = 15, // BEIS + + DMAC_GIF_UNIT }; extern void CPU_INT( EE_EventType n, s32 ecycle ); diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index 75d45220f2dd0..49ddcca5d86f7 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -81,7 +81,7 @@ void SaveStateBase::Init( SafeArray* memblock ) void SaveStateBase::PrepBlock( int size ) { - pxAssumeDev( m_memory, "Savestate memory/buffer pointer is null!" ); + pxAssertDev( m_memory, "Savestate memory/buffer pointer is null!" ); const int end = m_idx+size; if( IsSaving() ) @@ -208,6 +208,7 @@ SaveStateBase& SaveStateBase::FreezeInternals() ipuFreeze(); ipuDmaFreeze(); gifFreeze(); + gifDmaFreeze(); sprFreeze(); // Fifth Block - iop-related systems @@ -283,7 +284,7 @@ void memSavingState::FreezeMem( void* data, int size ) void memSavingState::MakeRoomForData() { - pxAssumeDev( m_memory, "Savestate memory/buffer pointer is null!" ); + pxAssertDev( m_memory, "Savestate memory/buffer pointer is null!" ); m_memory->ChunkSize = ReallocThreshold; m_memory->MakeRoomFor( m_idx + MemoryBaseAllocSize ); diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index bf6373eaf28f9..6dd129442d57f 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -24,7 +24,7 @@ // the lower 16 bit value. IF the change is breaking of all compatibility with old // states, increment the upper 16 bit value, and clear the lower 16 bits to 0. -static const u32 g_SaveVersion = (0x9A01 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A02 << 16) | 0x0000; // this function is meant to be used in the place of GSfreeze, and provides a safe layer // between the GS saving function and the MTGS's needs. :) @@ -202,8 +202,12 @@ class SaveStateBase #endif void sifFreeze(); void ipuFreeze(); - void ipuDmaFreeze(); + void ipuDmaFreeze(); void gifFreeze(); + void gifDmaFreeze(); + void gifPathFreeze(u32 path); // called by gifFreeze() + void gifPathFreeze(); // called by gsFreeze() + void sprFreeze(); void sioFreeze(); @@ -212,8 +216,6 @@ class SaveStateBase void psxRcntFreeze(); void sio2Freeze(); - void gifPathFreeze(); // called by gsFreeze - void deci2Freeze(); }; diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index 054ffeecb57cf..6345a36903459 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -276,7 +276,7 @@ void SIO_CommandWrite(u8 value,int way) { info.McdSizeInSectors = cmd.mcdSizeInSectors; SysPlugins.McdGetSizeInfo( port, slot, info ); - pxAssumeDev( cmd.mcdSizeInSectors >= mc_sizeinfo_8mb.mcdSizeInSectors, + pxAssertDev( cmd.mcdSizeInSectors >= mc_sizeinfo_8mb.mcdSizeInSectors, "Mcd plugin returned an invalid memorycard size: Cards smaller than 8MB are not supported." ); cmd.sectorSize = info.SectorSize; diff --git a/pcsx2/System/SysThreadBase.cpp b/pcsx2/System/SysThreadBase.cpp index 55dc77f6ed202..20699630ce62f 100644 --- a/pcsx2/System/SysThreadBase.cpp +++ b/pcsx2/System/SysThreadBase.cpp @@ -111,7 +111,7 @@ void SysThreadBase::Suspend( bool isBlocking ) break; } - pxAssumeDev( m_ExecMode == ExecMode_Closing, "ExecMode should be nothing other than Closing..." ); + pxAssertDev( m_ExecMode == ExecMode_Closing, "ExecMode should be nothing other than Closing..." ); m_sem_event.Post(); } @@ -140,7 +140,7 @@ void SysThreadBase::Pause() if( m_ExecMode == ExecMode_Opened ) m_ExecMode = ExecMode_Pausing; - pxAssumeDev( m_ExecMode == ExecMode_Pausing, "ExecMode should be nothing other than Pausing..." ); + pxAssertDev( m_ExecMode == ExecMode_Pausing, "ExecMode should be nothing other than Pausing..." ); m_sem_event.Post(); } diff --git a/pcsx2/VUmicroMem.cpp b/pcsx2/VUmicroMem.cpp index 3547466bef70f..184cad74e6610 100644 --- a/pcsx2/VUmicroMem.cpp +++ b/pcsx2/VUmicroMem.cpp @@ -51,8 +51,8 @@ void vuMemoryReserve::Reset() { _parent::Reset(); - pxAssume( VU0.Mem ); - pxAssume( VU1.Mem ); + pxAssert( VU0.Mem ); + pxAssert( VU1.Mem ); memMapVUmicro(); diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index 00f22604b63b2..0fe2e5e587bd8 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -17,6 +17,7 @@ #include "Common.h" #include "VUops.h" #include "GS.h" +#include "Gif_Unit.h" #include @@ -2024,12 +2025,26 @@ static __ri void _vuXGKICK(VURegs * VU) { // flush all pipelines first (in the right order) _vuFlushAll(VU); - +#if USE_OLD_GIF == 1 // todo u8* data = ((u8*)VU->Mem + ((VU->VI[_Is_].US[0]*16) & 0x3fff)); u32 size; GetMTGS().PrepDataPacket( GIF_PATH_1, 0x400 ); size = GIFPath_CopyTag( GIF_PATH_1, (u128*)data, (0x400-(VU->VI[_Is_].US[0] & 0x3ff)) ); GetMTGS().SendDataPacket(); +#else + u32 addr = (VU->VI[_Is_].US[0] & 0x3ff) * 16; + u32 diff = 0x4000 - addr; + u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, VU->Mem, addr); + + if (size > diff) { + //DevCon.WriteLn(Color_Green, "VU1 Int: XGkick Wrap!"); + gifUnit.gifPath[GIF_PATH_1].CopyGSPacketData( &VU->Mem[addr], diff,true); + gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU->Mem[0],size-diff,true); + } + else { + gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU->Mem[addr], size, true); + } +#endif } static __ri void _vuXTOP(VURegs * VU) { diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index ad7c1770d5dde..55717af25bdf8 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -23,7 +23,9 @@ __aligned16 vifStruct vif0, vif1; +#if USE_OLD_GIF == 1 // d tGSTransferStatus GSTransferStatus((STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE); +#endif void vif0Reset() { @@ -172,17 +174,21 @@ __fi void vif1FBRST(u32 value) { vif1.done = true; vif1ch.chcr.STR = false; +#if USE_OLD_GIF == 1 // ... //DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs.mskpath3); - if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true) - { + if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true) { DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3); - gsInterrupt(); + gifInterrupt(); vif1Regs.mskpath3 = false; gifRegs.stat.M3P = 0; } - vif1Regs.mskpath3 = false; - gifRegs.stat.M3P = 0; + gifRegs.stat.M3P = 0; +#else + GUNIT_WARN(Color_Red, "VIF FBRST Reset MSK = %x", vif1Regs.mskpath3); + vif1Regs.mskpath3 = false; + gifRegs.stat.M3P = 0; +#endif vif1Regs.err.reset(); vif1.inprogress = 0; vif1.cmd = 0; diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index a35b42c9aa726..097b579bf62c7 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -227,4 +227,3 @@ extern void mfifoVIF1transfer(int qwc); extern bool VIF0transfer(u32 *data, int size, bool TTE=0); extern bool VIF1transfer(u32 *data, int size, bool TTE=0); extern void vifMFIFOInterrupt(); -extern bool CheckPath2GIF(EE_EventType channel); diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 7aa62fdaf8a0f..17ecfa90f4171 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -18,6 +18,7 @@ #include "Vif_Dma.h" #include "GS.h" #include "Gif.h" +#include "Gif_Unit.h" #include "VUmicro.h" #include "newVif.h" @@ -46,13 +47,15 @@ __fi void vif1FLUSH() //DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS); g_vifCycles += (VU1.cycle - _cycles) * BIAS; } - if(gifRegs.stat.P1Q && ((vif1.cmd & 0x7f) != 0x14) && ((vif1.cmd & 0x7f) != 0x17)) - { - vif1.vifstalled = true; +#if USE_OLD_GIF == 1 // d + if ((gifRegs.stat.P1Q == true) + && ((vif1.cmd & 0x7f) != 0x14) // cmd != MSCAL + && ((vif1.cmd & 0x7f) != 0x17)) { // cmd != MSCNT + vif1.vifstalled = true; vif1Regs.stat.VGW = true; vif1.GifWaitState = 2; } - +#endif } void vif1TransferToMemory() @@ -250,6 +253,7 @@ __fi void vif1SetupTransfer() } } +#if USE_OLD_GIF == 1 // d extern bool SIGNAL_IMR_Pending; bool CheckPath2GIF(EE_EventType channel) @@ -330,33 +334,32 @@ bool CheckPath2GIF(EE_EventType channel) return true; } +#endif + __fi void vif1Interrupt() { VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle); g_vifCycles = 0; - - if (schedulepath3msk & 0x10) - { +#if USE_OLD_GIF == 1 // d + if (schedulepath3msk & 0x10) { MSKPATH3_LOG("Scheduled Path3 Mask Firing"); Vif1MskPath3(); } - if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE) - { + if (GSTransferStatus.PTH2 == PENDINGSTOP_MODE) { GSTransferStatus.PTH2 = STOPPED_MODE; - if(gifRegs.stat.APATH == GIF_APATH2) - { - if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false; + if(gifRegs.stat.APATH == GIF_APATH2) { + if(gifRegs.stat.DIR == 0) gifRegs.stat.OPH = false; gifRegs.stat.APATH = GIF_APATH_IDLE; if(gifRegs.stat.P1Q) gsPath1Interrupt(); } } +#endif //Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here. - if (dmacRegs.ctrl.MFD == MFD_VIF1) - { + if (dmacRegs.ctrl.MFD == MFD_VIF1) { //Console.WriteLn("VIFMFIFO\n"); // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw. if (vif1ch.chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch.chcr._u32); @@ -365,11 +368,19 @@ __fi void vif1Interrupt() return; } - //We need to check the direction, if it is downloading from the GS, we handle that separately (KH2 for testing) - if (vif1ch.chcr.DIR) - { + // We need to check the direction, if it is downloading + // from the GS then we handle that separately (KH2 for testing) + if (vif1ch.chcr.DIR) { +#if USE_OLD_GIF == 1 // ... if (!CheckPath2GIF(DMAC_VIF1)) return; - +#else + if(gifUnit.gsSIGNAL.queued && (vif1.cmd & 0x7e) == 0x50) { // Direct/DirectHL + GUNIT_WARN("Path 2 Paused (vif1ch.chcr.DIR)"); + //CPU_INT(DMAC_VIF1, 128); + //return; + } +#endif + vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16); //Simulated GS transfer time done, clear the flags } diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 0b532abb8bb96..f6d5b108a70db 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -17,6 +17,7 @@ #include "Common.h" #include "Vif.h" #include "Gif.h" +#include "Gif_Unit.h" #include "Vif_Dma.h" u16 vifqwc = 0; @@ -261,47 +262,52 @@ void vifMFIFOInterrupt() return; } - if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE) - { +#if USE_OLD_GIF == 1 // d + if (GSTransferStatus.PTH2 == PENDINGSTOP_MODE) { GSTransferStatus.PTH2 = STOPPED_MODE; - if(gifRegs.stat.APATH == GIF_APATH2) - { + if(gifRegs.stat.APATH == GIF_APATH2) { if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false; gifRegs.stat.APATH = GIF_APATH_IDLE; if(gifRegs.stat.P1Q) gsPath1Interrupt(); } } - if (schedulepath3msk & 0x10) - { + if (schedulepath3msk & 0x10) { MSKPATH3_LOG("Scheduled Path3 Mask Firing on MFIFO VIF"); Vif1MskPath3(); } +#endif - if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) - { +#if USE_OLD_GIF == 1 // ... + if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) { SPR_LOG("Waiting for PATH to be ready"); return; } - //We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing) +#else + if(vif1ch.chcr.DIR && gifUnit.gsSIGNAL.queued && (vif1.cmd & 0x7e) == 0x50) { // Direct/DirectHL + GUNIT_WARN("Waiting for PATH to be ready (vif1ch.chcr.DIR)"); + //CPU_INT(DMAC_MFIFO_VIF, 128); + //return; + } +#endif + + // We need to check the direction, if it is downloading from the GS, + // we handle that separately (KH2 for testing) - //Simulated GS transfer time done, clear the flags + // Simulated GS transfer time done, clear the flags - if (vif1.irq && vif1.tag.size == 0) - { + if (vif1.irq && vif1.tag.size == 0) { SPR_LOG("VIF MFIFO Code Interrupt detected"); vif1Regs.stat.INT = true; hwIntcIrq(INTC_VIF1); --vif1.irq; - if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) - { + if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) { /*vif1Regs.stat.FQC = 0; // FQC=0 vif1ch.chcr.STR = false;*/ vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc); - if((vif1ch.qwc > 0 || !vif1.done) && !(vif1.inprogress & 0x10)) - { + if((vif1ch.qwc > 0 || !vif1.done) && !(vif1.inprogress & 0x10)) { VIF_LOG("VIF1 MFIFO Stalled"); return; } @@ -309,29 +315,22 @@ void vifMFIFOInterrupt() } //Mirroring change to VIF0 - if (vif1.cmd) - { - if(vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING; + if (vif1.cmd) { + if (vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING; } - else - { + else { vif1Regs.stat.VPS = VPS_IDLE; } - if(vif1.inprogress & 0x10) - { + if(vif1.inprogress & 0x10) { FireMFIFOEmpty(); if(!(vif1.done && vif1ch.qwc == 0))return; } - if (vif1.done == false || vif1ch.qwc) - { - - switch(vif1.inprogress & 1) - { + if (vif1.done == false || vif1ch.qwc) { + switch(vif1.inprogress & 1) { case 0: //Set up transfer - if (QWCinVIFMFIFO(vif1ch.tadr) == 0) - { + if (QWCinVIFMFIFO(vif1ch.tadr) == 0) { vif1.inprogress |= 0x10; CPU_INT(DMAC_MFIFO_VIF, 4 ); return; diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index c70bbc42d1402..eb69c92764eb0 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -17,14 +17,16 @@ #include "Common.h" #include "GS.h" #include "Gif.h" +#include "Gif_Unit.h" #include "Vif_Dma.h" #include "newVif.h" #include "VUmicro.h" #define vifOp(vifCodeName) _vifT int __fastcall vifCodeName(int pass, const u32 *data) -#define pass1 if (pass == 0) -#define pass2 if (pass == 1) -#define pass3 if (pass == 2) +#define pass1 if (pass == 0) +#define pass2 if (pass == 1) +#define pass3 if (pass == 2) +#define pass1or2 if (pass == 0 || pass == 1) #define vif1Only() { if (!idx) return vifCode_Null(pass, (u32*)data); } vifOp(vifCode_Null); @@ -80,34 +82,26 @@ static __fi void vuExecMicro(int idx, u32 addr) { GetVifX.vifstalled = true; } +#if USE_OLD_GIF == 1 // d u8 schedulepath3msk = 0; +#endif void Vif1MskPath3() { - +#if USE_OLD_GIF == 1 // d vif1Regs.mskpath3 = schedulepath3msk & 0x1; GIF_LOG("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs.mskpath3, gifch.chcr.STR, GSTransferStatus.PTH3); gifRegs.stat.M3P = vif1Regs.mskpath3; - if (!vif1Regs.mskpath3) - { + if(!vif1Regs.mskpath3) { MSKPATH3_LOG("Disabling Path3 Mask"); - //if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE; - //DevCon.Warning("Mask off"); - //if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE; - if(gifRegs.stat.P3Q) - { + if(gifRegs.stat.P3Q) { MSKPATH3_LOG("Path3 Waiting to Transfer, triggering"); - gsInterrupt(); + gifInterrupt(); } - } - else - { - MSKPATH3_LOG("Path3 Mask Enabled"); - } - // else if(!gif->chcr.STR && GSTransferStatus.PTH3 == IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE;//else DevCon.Warning("Mask on"); - + else { MSKPATH3_LOG("Path3 Mask Enabled"); } schedulepath3msk = 0; +#endif } //------------------------------------------------------------------ @@ -121,6 +115,7 @@ vifOp(vifCode_Base) { return 0; } +#if USE_OLD_GIF == 1 // d extern bool SIGNAL_IMR_Pending; static __aligned16 u32 partial_write[4]; static uint partial_count = 0; @@ -130,7 +125,7 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire vif1Only(); int vifImm = (u16)vif1Regs.code; vif1.tag.size = vifImm ? (vifImm*4) : (65536*4); - vif1.vifstalled = true; + vif1.vifstalled = true; gifRegs.stat.P2Q = true; if (gifRegs.stat.PSE) // temporarily stop { @@ -160,7 +155,7 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire //DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs.stat.APATH, gifRegs.stat.P1Q); vif1Regs.stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT) vif1.GifWaitState = 0; - vif1.vifstalled = true; + vif1.vifstalled = true; return 0; } } @@ -174,7 +169,7 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire { Console.WriteLn("Gif dma temp paused? VIF DIRECT"); vif1.GifWaitState = 3; - vif1.vifstalled = true; + vif1.vifstalled = true; vif1Regs.stat.VGW = true; return 0; } @@ -248,6 +243,39 @@ template __fi int _vifCode_Direct(int pass, const u8* data, bool isDire } return 0; } +#else +template __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) { + vif1Only(); + pass1 { + int vifImm = (u16)vif1Regs.code; + vif1.tag.size = vifImm ? (vifImm*4) : (65536*4); + return 0; + } + pass2 { + const char* name = isDirectHL ? "DirectHL" : "Direct"; + GIF_TRANSFER_TYPE tranType = isDirectHL ? GIF_TRANS_DIRECTHL : GIF_TRANS_DIRECT; + uint size = aMin(vif1.vifpacketsize, vif1.tag.size) * 4; // Get size in bytes + uint ret = gifUnit.TransferGSPacketData(tranType, (u8*)data, size); + + vif1.tag.size -= ret/4; // Convert to u32's + vif1Regs.stat.VGW = false; + + if (ret & 3) DevCon.Warning("Vif %s: Ret wasn't a multiple of 4!", name); // Shouldn't happen + if (size == 0) DevCon.Warning("Vif %s: No Data Transfer?", name); // Can this happen? + if (size != ret) { // Stall if gif didn't process all the data (path2 queued) + GUNIT_WARN("Vif %s: Stall! [size=%d][ret=%d]", name, size, ret); + //gifUnit.PrintInfo(); + vif1.vifstalled = true; + vif1Regs.stat.VGW = true; + } + if (vif1.tag.size == 0) { + vif1.cmd = 0; + } + return ret / 4; + } + return 0; +} +#endif vifOp(vifCode_Direct) { pass3 { VifCodeLog("Direct"); } @@ -263,7 +291,21 @@ vifOp(vifCode_DirectHL) { vifOp(vifCode_Flush) { vif1Only(); vifStruct& vifX = GetVifX; - pass1 { vifFlush(idx); vifX.cmd = 0; } +#if USE_OLD_GIF == 1 // d + pass1 { vifFlush(idx); vifX.cmd = 0; } +#else + pass1or2 { + vif1Regs.stat.VGW = false; + vifFlush(idx); + if (gifUnit.checkPaths(1,1,0)) { + GUNIT_WARN("Vif Flush: Stall!"); + //gifUnit.PrintInfo(); + vif1Regs.stat.VGW = true; + vifX.vifstalled = true; + } + else vifX.cmd = 0; + } +#endif pass3 { VifCodeLog("Flush"); } return 0; } @@ -272,21 +314,59 @@ vifOp(vifCode_Flush) { vifOp(vifCode_FlushA) { vif1Only(); vifStruct& vifX = GetVifX; +#if USE_OLD_GIF == 1 // d pass1 { vifFlush(idx); // Gif is already transferring so wait for it. if (gifRegs.stat.P1Q || GSTransferStatus.PTH3 < STOPPED_MODE) { //DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs.mskpath3); - // MSKPATH3_LOG("Waiting for Path3 to Flush"); //DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); vif1Regs.stat.VGW = true; - vifX.GifWaitState = 1; - vifX.vifstalled = true; - } // else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); - + vifX.GifWaitState = 1; + vifX.vifstalled = true; + } + //else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); vifX.cmd = 0; } +#else + pass1or2 { + Gif_Path& p3 = gifUnit.gifPath[GIF_PATH_3]; + u32 p1or2 = gifUnit.checkPaths(1,1,0); + bool doStall = false; + vif1Regs.stat.VGW = false; + vifFlush(idx); + if (p3.state != GIF_PATH_IDLE || p1or2) { + GUNIT_WARN("Vif FlushA: Stall!"); + //gifUnit.PrintInfo(); + if (p3.state != GIF_PATH_IDLE && !p1or2) { // Only path 3 left... + GUNIT_WARN("Vif FlushA - Getting path3 to finish!"); + if (gifUnit.lastTranType == GIF_TRANS_FIFO + && p3.state != GIF_PATH_IDLE && !p3.hasDataRemaining()) { + p3.state = GIF_PATH_IDLE; // Hack: Tekken 4 and Gitaroo Man need this to boot... + DevCon.Warning("Vif FlushA - path3 has no more data, but didn't EOP"); + } + else { // Path 3 hasn't finished its current gs packet + if (gifUnit.stat.APATH != 3 && gifUnit.Path3Masked()) { + gifUnit.stat.APATH = 3; // Hack: Force path 3 to finish (persona 3 needs this) + //DevCon.Warning("Vif FlushA - Forcing path3 to finish current packet"); + } + gifInterrupt(); // Feed path3 some gif dma data + gifUnit.Execute(); // Execute path3 in-case gifInterrupt() didn't... + } + if (p3.state != GIF_PATH_IDLE) { + doStall = true; // If path3 still isn't finished... + } + } + else doStall = true; + } + if (doStall) { + vif1Regs.stat.VGW = true; + vifX.vifstalled = true; + } + else vifX.cmd = 0; + } +#endif pass3 { VifCodeLog("FlushA"); } return 0; } @@ -310,7 +390,7 @@ vifOp(vifCode_Mark) { pass1 { vifXRegs.mark = (u16)vifXRegs.code; vifXRegs.stat.MRK = true; - vifX.cmd = 0; + vifX.cmd = 0; } pass3 { VifCodeLog("Mark"); } return 0; @@ -318,7 +398,7 @@ vifOp(vifCode_Mark) { static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) { VURegs& VUx = idx ? VU1 : VU0; - pxAssume(VUx.Micro > 0); + pxAssert(VUx.Micro > 0); if (memcmp_mmx(VUx.Micro + addr, data, size*4)) { // Clear VU memory before writing! @@ -372,7 +452,24 @@ vifOp(vifCode_MSCAL) { vifOp(vifCode_MSCALF) { vifStruct& vifX = GetVifX; + +#if USE_OLD_GIF == 1 // d pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs.code) << 3); vifX.cmd = 0; } +#else + pass1or2 { + vifXRegs.stat.VGW = false; + vifFlush(idx); + if (u32 a = gifUnit.checkPaths(1,1,0)) { + GUNIT_WARN("Vif MSCALF: Stall! [%d,%d]", !!(a&1), !!(a&2)); + vif1Regs.stat.VGW = true; + vifX.vifstalled = true; + } + else { + vuExecMicro(idx, (u16)(vifXRegs.code) << 3); + vifX.cmd = 0; + } + } +#endif pass3 { VifCodeLog("MSCALF"); } return 0; } @@ -388,15 +485,25 @@ vifOp(vifCode_MSCNT) { vifOp(vifCode_MskPath3) { vif1Only(); pass1 { +#if USE_OLD_GIF == 1 // d MSKPATH3_LOG("Direct MSKPATH3"); - schedulepath3msk = 0x10 | (vif1Regs.code >> 15) & 0x1; - - if(vif1ch.chcr.STR && vif1.lastcmd != 0x13)vif1.vifstalled = true; + if(vif1ch.chcr.STR && vif1.lastcmd != 0x13) vif1.vifstalled = true; else Vif1MskPath3(); - vif1.cmd = 0; +#else + vif1Regs.mskpath3 = (vif1Regs.code >> 15) & 0x1; + gifRegs.stat.M3P = (vif1Regs.code >> 15) & 0x1; + GUNIT_LOG("Vif1 - MskPath3 [p3 = %s]", vif1Regs.mskpath3 ? "disabled" : "enabled"); + if(!vif1Regs.mskpath3) { + //if(!gifUnit.gifPath[GIF_PATH_3].isDone() || gifRegs.stat.P3Q || gifRegs.stat.IP3) { + GUNIT_WARN("Path3 triggering!"); + gifInterrupt(); + //} + } + vif1.cmd = 0; +#endif } pass3 { VifCodeLog("MskPath3"); } return 0; @@ -446,15 +553,11 @@ template static __fi int _vifCode_STColRow(const u32* data, u32* pmem2) pxAssume(ret > 0); switch (ret) { - case 4: - pmem2[3] = data[3]; - case 3: - pmem2[2] = data[2]; - case 2: - pmem2[1] = data[1]; - case 1: - pmem2[0] = data[0]; - break; + case 4: pmem2[3] = data[3]; + case 3: pmem2[2] = data[2]; + case 2: pmem2[1] = data[1]; + case 1: pmem2[0] = data[0]; + break; jNO_DEFAULT } @@ -481,7 +584,6 @@ vifOp(vifCode_STCol) { vifOp(vifCode_STRow) { vifStruct& vifX = GetVifX; - pass1 { vifX.tag.addr = 0; vifX.tag.size = 4; diff --git a/pcsx2/Vif_Dma.h b/pcsx2/Vif_Dma.h index 4d9a301b790db..1f42b2164d72f 100644 --- a/pcsx2/Vif_Dma.h +++ b/pcsx2/Vif_Dma.h @@ -85,7 +85,6 @@ struct vifStruct { }; extern __aligned16 vifStruct vif0, vif1; -extern u8 schedulepath3msk; _vifT extern u32 vifRead32(u32 mem); _vifT extern bool vifWrite32(u32 mem, u32 value); diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index c11e1d86d3615..eee54b477a0c8 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -83,12 +83,11 @@ _vifT void vifTransferLoop(u32* &data) { if(!vifX.cmd) { // Get new VifCode vifXRegs.code = data[0]; - vifX.cmd = data[0] >> 24; - iBit = data[0] >> 31; + vifX.cmd = data[0] >> 24; + iBit = data[0] >> 31; //VIF_LOG("New VifCMD %x tagsize %x", vifX.cmd, vifX.tag.size); - if (IsDevBuild && SysTrace.EE.VIFcode.IsActive()) - { + if (IsDevBuild && SysTrace.EE.VIFcode.IsActive()) { // Pass 2 means "log it" vifCmdHandler[idx][vifX.cmd & 0x7f](2, data); } @@ -106,7 +105,7 @@ _vifT void vifTransferLoop(u32* &data) { if (analyzeIbit(data, iBit)) break; } - if (pSize) vifX.vifstalled = true; + if (pSize) vifX.vifstalled = true; } _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { @@ -122,51 +121,37 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) { g_packetsizeonvu = size; vifTransferLoop(data); + transferred += size - vifX.vifpacketsize; + g_vifCycles +=((transferred * BIAS) >> 2) ; /* guessing */ - transferred += size - vifX.vifpacketsize; - - g_vifCycles +=((transferred * BIAS) >> 2) ; /* guessing */ - - if(!idx && g_vu0Cycles > 0) - { - if(g_vifCycles < g_vu0Cycles) g_vu0Cycles -= g_vifCycles; - else if(g_vifCycles >= g_vu0Cycles)g_vu0Cycles = 0; + if(!idx && g_vu0Cycles > 0) { + if (g_vifCycles < g_vu0Cycles) g_vu0Cycles -= g_vifCycles; + elif(g_vifCycles >= g_vu0Cycles) g_vu0Cycles = 0; } - else if(idx && g_vu1Cycles > 0) - { - if(g_vifCycles < g_vu1Cycles) g_vu1Cycles -= g_vifCycles; - else if(g_vifCycles >= g_vu1Cycles)g_vu1Cycles = 0; + if (idx && g_vu1Cycles > 0) { + if (g_vifCycles < g_vu1Cycles) g_vu1Cycles -= g_vifCycles; + elif(g_vifCycles >= g_vu1Cycles) g_vu1Cycles = 0; } vifX.irqoffset = transferred % 4; // cannot lose the offset - if (!TTE) // *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4) - { - transferred = transferred >> 2; - + if (!TTE) {// *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4) + transferred = transferred >> 2; vifXch.madr +=(transferred << 4); vifXch.qwc -= transferred; - if(vifXch.chcr.STR)hwDmacSrcTadrInc(vifXch); - - if (!vifXch.qwc) - { + if (vifXch.chcr.STR) hwDmacSrcTadrInc(vifXch); + if(!vifXch.qwc) { vifX.inprogress &= ~0x1; vifX.vifstalled = false; } } - else - { - - if(!vifX.irqoffset) - { - vifX.vifstalled = false; - } + else { + if (!vifX.irqoffset) vifX.vifstalled = false; } if (vifX.irq && vifX.cmd == 0) { //DevCon.WriteLn("Vif IRQ!"); - if(((vifXRegs.code >> 24) & 0x7f) != 0x7) - { + if(((vifXRegs.code >> 24) & 0x7f) != 0x7) { vifXRegs.stat.VIS = true; // Note: commenting this out fixes WALL-E? vifX.vifstalled = true; } diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 3ac678bd7b1a3..218485240c515 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -537,7 +537,7 @@ void SysExecEvent_CoreThreadPause::InvokeEvent() if( CorePluginsAreOpen ) { CorePluginsAreOpen = GetCorePlugins().AreOpen(); - pxAssumeDev( CorePluginsAreOpen, "Invalid plugin close/shutdown detected during paused CoreThread; please Stop/Suspend the core instead." ); + pxAssertDev( CorePluginsAreOpen, "Invalid plugin close/shutdown detected during paused CoreThread; please Stop/Suspend the core instead." ); } paused_core.AllowResume(); diff --git a/pcsx2/gui/AppEventListeners.h b/pcsx2/gui/AppEventListeners.h index 4d492df907473..b825ca229a820 100644 --- a/pcsx2/gui/AppEventListeners.h +++ b/pcsx2/gui/AppEventListeners.h @@ -188,7 +188,7 @@ class EventListenerHelper_CoreThread : public EventListener_CoreThread EventListenerHelper_CoreThread( TypeToDispatchTo* dispatchTo ) : Owner( *dispatchTo ) { - pxAssume(dispatchTo != NULL); + pxAssert(dispatchTo != NULL); } virtual ~EventListenerHelper_CoreThread() throw() {} @@ -215,7 +215,7 @@ class EventListenerHelper_Plugins : public EventListener_Plugins EventListenerHelper_Plugins( TypeToDispatchTo* dispatchTo ) : Owner( *dispatchTo ) { - pxAssume(dispatchTo != NULL); + pxAssert(dispatchTo != NULL); } virtual ~EventListenerHelper_Plugins() throw() {} @@ -244,7 +244,7 @@ class EventListenerHelper_AppStatus : public EventListener_AppStatus EventListenerHelper_AppStatus( TypeToDispatchTo* dispatchTo ) : Owner( *dispatchTo ) { - pxAssume(dispatchTo != NULL); + pxAssert(dispatchTo != NULL); } virtual ~EventListenerHelper_AppStatus() throw() {} diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 7c99a904139ce..a6c6016593206 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -690,7 +690,7 @@ void Pcsx2App::ClearPendingSave() if( AppRpc_TryInvokeAsync(&Pcsx2App::ClearPendingSave) ) return; --m_PendingSaves; - pxAssumeDev( m_PendingSaves >= 0, "Pending saves count mismatch (pending count is less than 0)" ); + pxAssertDev( m_PendingSaves >= 0, "Pending saves count mismatch (pending count is less than 0)" ); if( (m_PendingSaves == 0) && m_ScheduledTermination ) { @@ -708,17 +708,16 @@ MainEmuFrame& Pcsx2App::GetMainFrame() const { MainEmuFrame* mainFrame = GetMainFramePtr(); - pxAssume( mainFrame != NULL ); - pxAssert( ((uptr)GetTopWindow()) == ((uptr)mainFrame) ); - return *mainFrame; + pxAssert(mainFrame != NULL); + pxAssert(((uptr)GetTopWindow()) == ((uptr)mainFrame)); + return *mainFrame; } GSFrame& Pcsx2App::GetGsFrame() const { - GSFrame* gsFrame = (GSFrame*)wxWindow::FindWindowById( m_id_GsFrame ); - - pxAssume( gsFrame != NULL ); - return *gsFrame; + GSFrame* gsFrame = (GSFrame*)wxWindow::FindWindowById( m_id_GsFrame ); + pxAssert(gsFrame != NULL); + return *gsFrame; } // NOTE: Plugins are *not* applied by this function. Changes to plugins need to handled diff --git a/pcsx2/gui/Panels/GameDatabasePanel.cpp b/pcsx2/gui/Panels/GameDatabasePanel.cpp index 7adc657120855..97871fcbc34fb 100644 --- a/pcsx2/gui/Panels/GameDatabasePanel.cpp +++ b/pcsx2/gui/Panels/GameDatabasePanel.cpp @@ -93,7 +93,7 @@ const ListViewColumnInfo& GameDatabaseListView::GetDefaultColumnInfo( uint idx ) { L"Patches", 48, wxLIST_FORMAT_CENTER }, }; - pxAssumeDev( idx < ArraySize(columns), "ListView column index is out of bounds." ); + pxAssertDev( idx < ArraySize(columns), "ListView column index is out of bounds." ); return columns[idx]; } diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index f57637ad2a713..918bedde5e441 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -244,7 +244,7 @@ class WXDLLEXPORT McdDataObject : public wxDataObjectSimple uint GetViewIndex() const { - pxAssumeDev( m_viewIndex >= 0, "memory card view-Index is uninitialized (invalid drag&drop object state)" ); + pxAssertDev( m_viewIndex >= 0, "memory card view-Index is uninitialized (invalid drag&drop object state)" ); return (uint)m_viewIndex; } diff --git a/pcsx2/gui/Panels/MemoryCardListView.cpp b/pcsx2/gui/Panels/MemoryCardListView.cpp index 9f08545bd1f95..0590ab616e5cc 100644 --- a/pcsx2/gui/Panels/MemoryCardListView.cpp +++ b/pcsx2/gui/Panels/MemoryCardListView.cpp @@ -36,7 +36,7 @@ void BaseMcdListView::SetMcdProvider( IMcdList* face ) IMcdList& BaseMcdListView::GetMcdProvider() { - pxAssume( m_CardProvider ); + pxAssert( m_CardProvider ); return *m_CardProvider; } @@ -111,7 +111,7 @@ const ListViewColumnInfo& MemoryCardListView_Simple::GetDefaultColumnInfo( uint { _("Created on") , 85 , wxLIST_FORMAT_LEFT }, }; - pxAssumeDev( idx < ArraySize(columns), "ListView column index is out of bounds." ); + pxAssertDev( idx < ArraySize(columns), "ListView column index is out of bounds." ); return columns[idx]; } diff --git a/pcsx2/gui/Panels/MemoryCardPanels.h b/pcsx2/gui/Panels/MemoryCardPanels.h index 61a7081a2a761..f462007286f9c 100644 --- a/pcsx2/gui/Panels/MemoryCardPanels.h +++ b/pcsx2/gui/Panels/MemoryCardPanels.h @@ -175,7 +175,7 @@ namespace Panels virtual wxDirName GetMcdPath() const { - pxAssume(m_FolderPicker); + pxAssert(m_FolderPicker); return m_FolderPicker->GetPath(); } diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp index f20426d8e2286..1b5500049c5c6 100644 --- a/pcsx2/ps2/GIFpath.cpp +++ b/pcsx2/ps2/GIFpath.cpp @@ -21,37 +21,11 @@ #include "Vif.h" #include +#if USE_OLD_GIF == 1 // d // -------------------------------------------------------------------------------------- // GIFpath -- the GIFtag Parser // -------------------------------------------------------------------------------------- -enum GIF_FLG -{ - GIF_FLG_PACKED = 0, - GIF_FLG_REGLIST = 1, - GIF_FLG_IMAGE = 2, - GIF_FLG_IMAGE2 = 3 -}; - -enum GIF_REG -{ - GIF_REG_PRIM = 0x00, - GIF_REG_RGBA = 0x01, - GIF_REG_STQ = 0x02, - GIF_REG_UV = 0x03, - GIF_REG_XYZF2 = 0x04, - GIF_REG_XYZ2 = 0x05, - GIF_REG_TEX0_1 = 0x06, - GIF_REG_TEX0_2 = 0x07, - GIF_REG_CLAMP_1 = 0x08, - GIF_REG_CLAMP_2 = 0x09, - GIF_REG_FOG = 0x0a, - GIF_REG_XYZF3 = 0x0c, - GIF_REG_XYZ3 = 0x0d, - GIF_REG_A_D = 0x0e, - GIF_REG_NOP = 0x0f, -}; - // GIFTAG // Members of this structure are in CAPS to help visually denote that they are representative // of actual hw register states of the GIF, unlike the internal tracking vars in GIFPath, which @@ -203,7 +177,7 @@ static void __fastcall RegHandlerSIGNAL(const u32* data) if (!SIGNAL_IMR_Pending) { //DevCon.WriteLn( Color_StrongOrange, "GS SIGNAL double throw encountered!" ); - SIGNAL_IMR_Pending = true; + SIGNAL_IMR_Pending = true; SIGNAL_Data_Pending[0] = data[0]; SIGNAL_Data_Pending[1] = data[1]; @@ -273,8 +247,8 @@ static void __fastcall RegHandlerUNMAPPED(const u32* data) // Using microVU avoids the GIFtag errors, so probably just one of sVU's hacks conflicting // with one of VIF's hacks, and causing corrupted packet data. - if( regidx != 0x7f && regidx != 0xee ) - DbgCon.Warning( "Ignoring Unmapped GIFtag Register, Index = %02x", regidx ); + if( regidx != 0x7f /*&& regidx != 0xee*/ ) + DevCon.Warning( "Ignoring Unmapped GIFtag Register, Index = %02x", regidx ); } #define INSERT_UNMAPPED_4 RegHandlerUNMAPPED, RegHandlerUNMAPPED, RegHandlerUNMAPPED, RegHandlerUNMAPPED, @@ -355,13 +329,6 @@ __fi bool GIFPath::IsActive() const return (nloop != 0) || !tag.EOP; } -void SaveStateBase::gifPathFreeze() -{ - FreezeTag( "GIFpath" ); - Freeze( s_gifPath.path ); -} - - static __fi void gsHandler(const u8* pMem) { const int reg = pMem[8]; @@ -579,42 +546,6 @@ __fi int GIFPath::ParseTagQuick(GIF_PATH pathidx, const u8* pMem, u32 size) return size; } -__ri void MemCopy_WrappedDest( const u128* src, u128* destBase, uint& destStart, uint destSize, uint len ) -{ - uint endpos = destStart + len; - if( endpos < destSize ) - { - memcpy_qwc(&destBase[destStart], src, len ); - destStart += len; - } - else - { - uint firstcopylen = destSize - destStart; - memcpy_qwc(&destBase[destStart], src, firstcopylen ); - - destStart = endpos % destSize; - memcpy_qwc(destBase, src+firstcopylen, destStart ); - } -} - -__ri void MemCopy_WrappedSrc( const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len ) -{ - uint endpos = srcStart + len; - if( endpos < srcSize ) - { - memcpy_qwc(dest, &srcBase[srcStart], len ); - srcStart += len; - } - else - { - uint firstcopylen = srcSize - srcStart; - memcpy_qwc(dest, &srcBase[srcStart], firstcopylen ); - - srcStart = endpos % srcSize; - memcpy_qwc(dest+firstcopylen, srcBase, srcStart ); - } -} - #define copyTag() do { \ _mm_store_ps( (float*)&RingBuffer.m_Ring[ringpos], Aligned ? _mm_load_ps((float*)pMem128) : _mm_loadu_ps((float*)pMem128)); \ ++pMem128; --size; \ @@ -991,7 +922,22 @@ __fi void GIFPath_Clear( GIF_PATH pathidx ) s_gifPath.path[pathidx].Reset(); GSTransferStatus._u32 &= ~(0xf << (pathidx * 4)); - GSTransferStatus._u32 |= (0x5 << (pathidx * 4)); + GSTransferStatus._u32 |= (0x5 << (pathidx * 4)); if( GSgifSoftReset == NULL ) return; GetMTGS().SendSimplePacket( GS_RINGTYPE_SOFTRESET, (1< + + + + + + - - diff --git a/pcsx2/windows/WinConsolePipe.cpp b/pcsx2/windows/WinConsolePipe.cpp index 8f96fe7b3dcee..2fb85611eb84f 100644 --- a/pcsx2/windows/WinConsolePipe.cpp +++ b/pcsx2/windows/WinConsolePipe.cpp @@ -158,7 +158,7 @@ WinPipeRedirection::WinPipeRedirection( FILE* stdstream ) m_crtFile = -1; m_fp = NULL; - pxAssume( (stdstream == stderr) || (stdstream == stdout) ); + pxAssert( (stdstream == stderr) || (stdstream == stdout) ); try { diff --git a/pcsx2/x86/BaseblockEx.h b/pcsx2/x86/BaseblockEx.h index 7541cb4749fa6..2fc4cd80c1aa5 100644 --- a/pcsx2/x86/BaseblockEx.h +++ b/pcsx2/x86/BaseblockEx.h @@ -259,7 +259,7 @@ static void recLUT_SetPage(uptr reclut[0x10000], uptr hwlut[0x10000], // this value is in 64k pages! uint page = pagebase + pageidx; - pxAssume( page < 0x10000 ); + pxAssert( page < 0x10000 ); reclut[page] = (uptr)&mapbase[(mappage - page) << 14]; if (hwlut) hwlut[page] = 0u - (pagebase << 16); diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index cc8e509c38c19..6089767b577e8 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -468,7 +468,7 @@ static DynGenFunc* _DynGen_DispatcherReg() static DynGenFunc* _DynGen_EnterRecompiledCode() { - pxAssumeDev( DispatcherReg != NULL, "Dynamically generated dispatchers are required prior to generating EnterRecompiledCode!" ); + pxAssertDev( DispatcherReg != NULL, "Dynamically generated dispatchers are required prior to generating EnterRecompiledCode!" ); u8* retval = xGetAlignedCallTarget(); @@ -1400,7 +1400,7 @@ static void __fastcall recRecompile( const u32 startpc ) if (dumplog & 4) iDumpRegisters(startpc, 0); #endif - pxAssume( startpc ); + pxAssert( startpc ); // if recPtr reached the mem limit reset whole mem if (recPtr >= (recMem->GetPtrEnd() - _64kb)) { @@ -1429,7 +1429,7 @@ static void __fastcall recRecompile( const u32 startpc ) s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr); - pxAssume(s_pCurBlockEx); + pxAssert(s_pCurBlockEx); if (g_SkipBiosHack && HWADDR(startpc) == EELOAD_START) { xCALL(eeloadReplaceOSDSYS); @@ -1448,7 +1448,7 @@ static void __fastcall recRecompile( const u32 startpc ) pc = startpc; x86FpuState = FPU_STATE; g_cpuHasConstReg = g_cpuFlushedConstReg = 1; - pxAssume( g_cpuConstRegs[0].UD[0] == 0 ); + pxAssert( g_cpuConstRegs[0].UD[0] == 0 ); _initX86regs(); _initXMMregs(); diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index fc33ab2a1a651..8ae475cd61f70 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -26,6 +26,7 @@ using namespace x86Emitter; #include "VU.h" #include "GS.h" #include "Gif.h" +#include "Gif_Unit.h" #include "iR5900.h" #include "R5900OpcodeTables.h" #include "System/RecTypes.h" diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index 201a519d4da86..7fea7e4eb62db 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -25,9 +25,9 @@ __fi static const x32& getFlagReg(uint fInst) { - static const x32* const gprF_crap[4] = { &gprF0, &gprF1, &gprF2, &gprF3 }; - pxAssume(fInst < 4); - return *gprF_crap[fInst]; + static const x32* const gprFlags[4] = { &gprF0, &gprF1, &gprF2, &gprF3 }; + pxAssert(fInst < 4); + return *gprFlags[fInst]; } __fi void setBitSFLAG(const x32& reg, const x32& regT, int bitTest, int bitSet) diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 974f929bd3f69..ba4ba6133c31d 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -508,8 +508,8 @@ __fi void* mVUentryGet(microVU& mVU, microBlockManager* block, u32 startPC, uptr // Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr) __fi void* mVUblockFetch(microVU& mVU, u32 startPC, uptr pState) { - pxAssumeDev((startPC & 7) == 0, pxsFmt("microVU%d: unaligned startPC=0x%04x", mVU.index, startPC) ); - pxAssumeDev( startPC <= mVU.microMemSize-8, pxsFmt("microVU%d: invalid startPC=0x%04x", mVU.index, startPC) ); + pxAssertDev((startPC & 7) == 0, pxsFmt("microVU%d: unaligned startPC=0x%04x", mVU.index, startPC) ); + pxAssertDev( startPC <= mVU.microMemSize-8, pxsFmt("microVU%d: invalid startPC=0x%04x", mVU.index, startPC) ); startPC &= mVU.microMemSize-8; blockCreate(startPC/8); diff --git a/pcsx2/x86/microVU_IR.h b/pcsx2/x86/microVU_IR.h index f2f902ac90042..ef7c24fef094f 100644 --- a/pcsx2/x86/microVU_IR.h +++ b/pcsx2/x86/microVU_IR.h @@ -230,7 +230,7 @@ class microRegAlloc { } } int x = findFreeRegRec(0); - pxAssumeDev( x >= 0, "microVU register allocation failure!" ); + pxAssertDev( x >= 0, "microVU register allocation failure!" ); return x; } diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 69227e28e8b84..438b15de7a9d8 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1119,64 +1119,50 @@ mVUop(mVU_XITOP) { // XGkick //------------------------------------------------------------------ -extern void gsPath1Interrupt(); -extern bool SIGNAL_IMR_Pending; - void __fastcall mVU_XGKICK_(u32 addr) { +#if USE_OLD_GIF == 1 // d + extern void gsPath1Interrupt(); + extern bool SIGNAL_IMR_Pending; + addr &= 0x3ff; u8* data = vuRegs[1].Mem + (addr*16); u32 diff = 0x400 - addr; u32 size; - /////////////////////////////////////////////// - ///////////////SIGNAL WARNING!!//////////////// - /////////////////////////////////////////////// - /* Due to the face SIGNAL can cause the loop - to leave early, we can end up missing data. - The only way we can avoid this is to queue - it :(, im relying on someone else to come - up with a better solution! */ - - /*if(gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.APATH == GIF_APATH3 && gifRegs.stat.IP3 == true) && SIGNAL_IMR_Pending == false) - { - if(Path1WritePos != 0) - { - //Flush any pending transfers so things dont go up in the wrong order - while(gifRegs.stat.P1Q == true) gsPath1Interrupt(); - } - GetMTGS().PrepDataPacket(GIF_PATH_1, 0x400); - size = GIFPath_CopyTag(GIF_PATH_1, (u128*)data, diff); - GetMTGS().SendDataPacket(); - - if(GSTransferStatus.PTH1 == STOPPED_MODE) - { - gifRegs.stat.OPH = false; - gifRegs.stat.APATH = GIF_APATH_IDLE; - } - } - else - {*/ - //DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs.stat.APATH, Path1WritePos, Path1ReadPos); - size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff); - u8* pDest = &Path1Buffer[Path1WritePos*16]; + size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff); + u8* pDest = &Path1Buffer[Path1WritePos*16]; - Path1WritePos += size; + Path1WritePos += size; - pxAssumeMsg((Path1WritePos < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!"); - //DevCon.Warning("Storing size %x PATH 1", size); + pxAssertMsg((Path1WritePos < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!"); + //DevCon.Warning("Storing size %x PATH 1", size); - if (size > diff) { - //DevCon.Status("XGkick Wrap!"); - memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), diff); - memcpy_qwc(pDest+(diff*16), vuRegs[1].Mem, size-diff); - } - else { - memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), size); - } - //if(!gifRegs.stat.P1Q) CPU_INT(28, 128); - gifRegs.stat.P1Q = true; - //} - gsPath1Interrupt(); + if (size > diff) { + //DevCon.Status("XGkick Wrap!"); + memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), diff); + memcpy_qwc(pDest+(diff*16), vuRegs[1].Mem, size-diff); + } + else { + memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), size); + } + //if(!gifRegs.stat.P1Q) CPU_INT(28, 128); + gifRegs.stat.P1Q = true; + + gsPath1Interrupt(); +#else + addr = (addr & 0x3ff) * 16; + u32 diff = 0x4000 - addr; + u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, vuRegs[1].Mem, addr); + + if (size > diff) { + //DevCon.WriteLn(Color_Green, "microVU1: XGkick Wrap!"); + gifUnit.gifPath[GIF_PATH_1].CopyGSPacketData( &vuRegs[1].Mem[addr], diff,true); + gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &vuRegs[1].Mem[0],size-diff,true); + } + else { + gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &vuRegs[1].Mem[addr], size, true); + } +#endif } static __fi void mVU_XGKICK_DELAY(mV, bool memVI) { diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index a20d35697b31c..f3f966e5f369c 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -241,11 +241,11 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); } #define branchAddr ( \ - pxAssumeDev((iPC & 1) == 0, "microVU: Expected Lower Op for valid branch addr."), \ + pxAssertDev((iPC & 1) == 0, "microVU: Expected Lower Op for valid branch addr."), \ ((((iPC + 2) + (_Imm11_ * 2)) & mVU.progMemMask) * 4) \ ) #define branchAddrN ( \ - pxAssumeDev((iPC & 1) == 0, "microVU: Expected Lower Op for valid branch addr."), \ + pxAssertDev((iPC & 1) == 0, "microVU: Expected Lower Op for valid branch addr."), \ ((((iPC + 4) + (_Imm11_ * 2)) & mVU.progMemMask) * 4) \ ) diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index c2a161a377514..db52bce079c4d 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -32,7 +32,7 @@ void dVifReserve(int idx) void dVifReset(int idx) { - pxAssumeDev(nVif[idx].recReserve, "Dynamic VIF recompiler reserve must be created prior to VIF use or reset!"); + pxAssertDev(nVif[idx].recReserve, "Dynamic VIF recompiler reserve must be created prior to VIF use or reset!"); if (!nVif[idx].vifBlocks) nVif[idx].vifBlocks = new HashBucket<_tParams>(); @@ -92,7 +92,7 @@ __fi void VifUnpackSSE_Dynarec::SetMasks(int cS) const { } void VifUnpackSSE_Dynarec::doMaskWrite(const xRegisterSSE& regX) const { - pxAssumeDev(regX.Id <= 1, "Reg Overflow! XMM2 thru XMM6 are reserved for masking."); + pxAssertDev(regX.Id <= 1, "Reg Overflow! XMM2 thru XMM6 are reserved for masking."); xRegisterSSE t = regX == xmm0 ? xmm1 : xmm0; // Get Temp Reg int cc = aMin(vCL, 3); u32 m0 = (vB.mask >> (cc * 8)) & 0xff; diff --git a/pcsx2/x86/newVif_UnpackSSE.cpp b/pcsx2/x86/newVif_UnpackSSE.cpp index 25a53d6a37dc5..d0806d42b2961 100644 --- a/pcsx2/x86/newVif_UnpackSSE.cpp +++ b/pcsx2/x86/newVif_UnpackSSE.cpp @@ -110,7 +110,7 @@ void VifUnpackSSE_Base::xUPK_S_8() const { void VifUnpackSSE_Base::xUPK_V2_32() const { xMOV64 (destReg, ptr32[srcIndirect]); - xMOVH.PS (destReg, ptr32[srcIndirect]); //v1v0v1v0 + xPSHUF.D (destReg, destReg, 0x44); //v1v0v1v0 } void VifUnpackSSE_Base::xUPK_V2_16() const { diff --git a/pcsx2/x86/sVU_Lower.cpp b/pcsx2/x86/sVU_Lower.cpp index 95096cd74eb0a..87bf4305922fa 100644 --- a/pcsx2/x86/sVU_Lower.cpp +++ b/pcsx2/x86/sVU_Lower.cpp @@ -27,6 +27,7 @@ #include "sVU_Debug.h" #include "sVU_zerorec.h" #include "Gif.h" +#include "Gif_Unit.h" using namespace x86Emitter; //------------------------------------------------------------------ @@ -1972,64 +1973,50 @@ void recVUMI_XTOP( VURegs *VU, int info ) //------------------------------------------------------------------ // VU1XGKICK_MTGSTransfer() - Called by ivuZerorec.cpp //------------------------------------------------------------------ -extern bool SIGNAL_IMR_Pending; -void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) +void __fastcall VU1XGKICK_MTGSTransfer(u32 addr) { +#if USE_OLD_GIF == 1 // todo + extern bool SIGNAL_IMR_Pending; addr &= 0x3fff; u8* data = VU1.Mem + (addr); u32 diff = 0x400 - (addr / 16); u32 size; u8* pDest; - /////////////////////////////////////////////// - ///////////////SIGNAL WARNING!!//////////////// - /////////////////////////////////////////////// - /* Due to the face SIGNAL can cause the loop - to leave early, we can end up missing data. - The only way we can avoid this is to queue - it :(, im relying on someone else to come - up with a better solution! */ + //DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs.stat.APATH, Path1WritePos, Path1ReadPos); + size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff); + pDest = &Path1Buffer[Path1WritePos*16]; + Path1WritePos += size; - /*if(gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.APATH == GIF_APATH3 && gifRegs.stat.IP3 == true) && SIGNAL_IMR_Pending == false) - { - if(Path1WritePos != 0) - { - //Flush any pending transfers so things dont go up in the wrong order - while(gifRegs.stat.P1Q == true) gsPath1Interrupt(); - } - GetMTGS().PrepDataPacket(GIF_PATH_1, 0x400); - size = GIFPath_CopyTag(GIF_PATH_1, (u128*)data, diff); - GetMTGS().SendDataPacket(); - - if(GSTransferStatus.PTH1 == STOPPED_MODE ) - { - gifRegs.stat.OPH = false; - gifRegs.stat.APATH = GIF_APATH_IDLE; - } - } - else - {*/ - //DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs.stat.APATH, Path1WritePos, Path1ReadPos); - size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff); - pDest = &Path1Buffer[Path1WritePos*16]; + pxAssertMsg((Path1WritePos+size < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!"); - Path1WritePos += size; - - pxAssumeMsg((Path1WritePos+size < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!"); + if (size > diff) { + //DevCon.Status("XGkick Wrap!"); + memcpy_qwc(pDest, VU1.Mem + addr, diff); + memcpy_qwc(pDest+(diff*16), VU1.Mem, size-diff); + } + else { + memcpy_qwc(pDest, VU1.Mem + addr, size); + } + //if(!gifRegs.stat.P1Q) CPU_INT(28, 128); + gifRegs.stat.P1Q = true; +//} + gsPath1Interrupt(); +#else + addr &= 0x3fff; + u32 diff = 0x4000 - addr; + u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, vuRegs[1].Mem, addr); - if (size > diff) { - //DevCon.Status("XGkick Wrap!"); - memcpy_qwc(pDest, VU1.Mem + addr, diff); - memcpy_qwc(pDest+(diff*16), VU1.Mem, size-diff); - } - else { - memcpy_qwc(pDest, VU1.Mem + addr, size); - } - //if(!gifRegs.stat.P1Q) CPU_INT(28, 128); - gifRegs.stat.P1Q = true; - //} - gsPath1Interrupt(); + if (size > diff) { + //DevCon.WriteLn(Color_Green, "superVU1: XGkick Wrap!"); + gifUnit.gifPath[0].CopyGSPacketData(&vuRegs[1].Mem[addr], diff, true); + gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &vuRegs[1].Mem[0],size-diff,true); + } + else { + gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &vuRegs[1].Mem[addr], size, true); + } +#endif } //------------------------------------------------------------------ diff --git a/pcsx2/x86/sVU_Micro.h b/pcsx2/x86/sVU_Micro.h index 0b78827d98fbb..587f50ecb5016 100644 --- a/pcsx2/x86/sVU_Micro.h +++ b/pcsx2/x86/sVU_Micro.h @@ -47,7 +47,7 @@ struct _vuopinfo { void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs); int eeVURecompileCode(VURegs *VU, _VURegsNum* regs); // allocates all the necessary regs and returns the indices -void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr); // used for MTGS in XGKICK +void __fastcall VU1XGKICK_MTGSTransfer(u32 addr); // used for MTGS in XGKICK extern int vucycle; typedef void (*vFloat)(int regd, int regTemp); diff --git a/pcsx2/x86/sVU_zerorec.cpp b/pcsx2/x86/sVU_zerorec.cpp index 576f6890f4e85..6a1f93bfb9fa4 100644 --- a/pcsx2/x86/sVU_zerorec.cpp +++ b/pcsx2/x86/sVU_zerorec.cpp @@ -396,7 +396,7 @@ void DestroyVUHeaders(int vuindex) // destroy VU resources void SuperVUDestroy(int vuindex) { - pxAssumeDev(vuindex >= 0 && vuindex <= 2, "Invalid VU index parameter!"); + pxAssertDev(vuindex >= 0 && vuindex <= 2, "Invalid VU index parameter!"); safe_delete_array(recVUHeaders[vuindex]); safe_delete_array(recVUBlocks[vuindex]); @@ -418,7 +418,7 @@ void SuperVUDestroy(int vuindex) // reset VU void SuperVUReset(int vuindex) { - pxAssumeDev(vuindex >= 0 && vuindex <= 2, "Invalid VU index parameter!"); + pxAssertDev(vuindex >= 0 && vuindex <= 2, "Invalid VU index parameter!"); #ifdef PCSX2_DEBUG s_vucount = 0; @@ -4314,8 +4314,7 @@ void recVUMI_XGKICK_(VURegs *VU) _freeX86regs(); _freeXMMregs(); - xMOV(edx, xRegister32(s_XGKICKReg)); - xMOV(ecx, (uptr)VU->Mem); + xMOV(ecx, xRegister32(s_XGKICKReg)); xCALL(VU1XGKICK_MTGSTransfer); s_ScheduleXGKICK = 0; diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index dd13de895c758..d7ed0f406dfd1 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -535,7 +535,7 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx ) // If this assertion fails, it mans SCurrent is being corrupted somewhere, or is not initialized // properly. Invalid values in SCurrent will cause errant IRQs and corrupted audio. - pxAssumeMsg( (vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28" ); + pxAssertMsg( (vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28" ); // Most games don't use much volume slide effects. So only call the UpdateVolume // methods when needed by checking the flag outside the method here... diff --git a/plugins/spu2-x/src/spu2freeze.cpp b/plugins/spu2-x/src/spu2freeze.cpp index c4229d1e16feb..63ae69ac58dae 100644 --- a/plugins/spu2-x/src/spu2freeze.cpp +++ b/plugins/spu2-x/src/spu2freeze.cpp @@ -54,7 +54,7 @@ s32 __fastcall Savestate::FreezeIt( DataBlock& spud ) spud.spu2id = SAVE_ID; spud.version = SAVE_VERSION; - pxAssumeMsg( spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted." ); + pxAssertMsg( spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted." ); if( spu2regs != NULL ) memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs)); if( _spu2mem != NULL ) memcpy(spud.mem, _spu2mem, sizeof(spud.mem)); @@ -104,7 +104,7 @@ s32 __fastcall Savestate::ThawIt( DataBlock& spud ) { SndBuffer::ClearContents(); - pxAssumeMsg( spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted." ); + pxAssertMsg( spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted." ); // base stuff if( spu2regs ) memcpy(spu2regs, spud.unkregs, sizeof(spud.unkregs)); diff --git a/plugins/zzogl-pg/opengl/HostMemory.cpp b/plugins/zzogl-pg/opengl/HostMemory.cpp index a85161245104c..e6bc5820ea792 100644 --- a/plugins/zzogl-pg/opengl/HostMemory.cpp +++ b/plugins/zzogl-pg/opengl/HostMemory.cpp @@ -452,9 +452,9 @@ __forceinline void _TransferLocalLocal_4() assert((gs.imageWnew % 8) == 0); - for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; ++i, ++i2) + for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; ++i, ++i2) { - for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < maxX; j += 8, j2 += 8) + for(u32 j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < maxX; j += 8, j2 += 8) { /* NOTE: the 2 conseq 4bit values are in NOT in the same byte */ u32 read = gsp(j%2048, i%2048, gs.srcbuf.bw);