mirror of https://github.com/PCSX2/pcsx2.git
Big gif transfer code rewrite!
Pcsx2 now has a gifUnit class which acts like the ps2's gif and executes a single gif transfer at a time (and performs path arbitration according to priority and path3 slicing). This new code is generally a speedup for most games. Particularly VU heavy games like GoW. This revision breaks old saved state compatibility so don't update if you wish to keep playing with your old saved states. Leave comments if this revision fixes or breaks anything... Message to GS Plugin authors: This new code now uses only 1 gif callback to transfer data to the gs plugin (GSgifTransfer). pcsx2 also is garaunteed to send full GS primitives to the plugin. So you don't have to account for partial-transfers anymore. Thanks goes out to shadowlady who tested around 500 games for me :D Note 1: The old gif code is still in this revision, and can be enabled by the USE_OLD_GIF macro. The old code will be deleted soon. Note 2: This revision also enables assertion dialogs in devel builds, and changed a lot of assume cases into assertions. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4821 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
7cb4dbb8d9
commit
c05dc759e3
|
@ -309,6 +309,7 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
|||
#define __ri __releaseinline
|
||||
#define __fi __forceinline
|
||||
#define __fc __fastcall
|
||||
#define elif else if
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -195,18 +195,19 @@ public:
|
|||
// --------------------------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
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;
|
||||
|
|
|
@ -199,13 +199,13 @@ public:
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
|
||||
virtual ~BaseScopedAlloc() throw()
|
||||
{
|
||||
//pxAssume(m_buffer==NULL);
|
||||
//pxAssert(m_buffer==NULL);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -50,12 +50,12 @@ public:
|
|||
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; }
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -92,14 +92,14 @@ public:
|
|||
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)
|
||||
|
|
|
@ -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<Mutex*>(locker);
|
||||
if( !m_lock ) return;
|
||||
|
|
|
@ -44,7 +44,7 @@ void pxInstallSignalHandler()
|
|||
// --------------------------------------------------------------------------------------
|
||||
EventListener_PageFault::EventListener_PageFault()
|
||||
{
|
||||
pxAssume(Source_PageFault);
|
||||
pxAssert(Source_PageFault);
|
||||
Source_PageFault->Add( *this );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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' );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -616,6 +616,6 @@ wxFont pxGetFixedFont( int ptsize, int weight )
|
|||
|
||||
wxString pxGetAppName()
|
||||
{
|
||||
pxAssume( wxTheApp );
|
||||
pxAssert( wxTheApp );
|
||||
return wxTheApp->GetAppName();
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
77
pcsx2/GS.cpp
77
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();
|
||||
|
|
49
pcsx2/GS.h
49
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 @@ public:
|
|||
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 );
|
||||
}
|
||||
}
|
||||
|
|
358
pcsx2/Gif.cpp
358
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;
|
||||
}
|
||||
|
||||
__fi void gsInterrupt()
|
||||
void incGifChAddr(u32 qwc) {
|
||||
if (gifch.chcr.STR) {
|
||||
gifch.madr += qwc * 16;
|
||||
gifch.qwc -= qwc;
|
||||
hwDmacSrcTadrInc(gifch);
|
||||
}
|
||||
else DevCon.Error("incGifAddr() Error!");
|
||||
}
|
||||
|
||||
__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);
|
||||
if (mfifoqwc == 0) return true; //Lets skip all this, we don't have the data
|
||||
|
||||
#if USE_OLD_GIF == 1 // d
|
||||
u32 *src;
|
||||
|
||||
if(mfifoqwc == 0) return true; //Lets skip all this, we don't have the data
|
||||
|
||||
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<<DMAC_MFIFO_GIF)))
|
||||
CPU_INT(DMAC_MFIFO_GIF, 4);
|
||||
|
||||
gifstate &= ~GIF_STATE_EMPTY;
|
||||
}
|
||||
|
||||
gifRegs.stat.FQC = 16;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gifRegs.ctrl.PSE) // temporarily stop
|
||||
{
|
||||
if (gifRegs.ctrl.PSE) { // temporarily stop
|
||||
Console.WriteLn("Gif dma temp paused?");
|
||||
CPU_INT(DMAC_MFIFO_GIF, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gifch.qwc == 0)
|
||||
{
|
||||
if (gifch.qwc == 0) {
|
||||
gifch.tadr = qwctag(gifch.tadr);
|
||||
|
||||
ptag = dmaGetAddr(gifch.tadr, false);
|
||||
|
@ -572,8 +562,7 @@ void mfifoGIFtransfer(int qwc)
|
|||
if(gspath3done == true) gifstate = GIF_STATE_DONE;
|
||||
else gifstate = GIF_STATE_READY;
|
||||
|
||||
if ((gifch.chcr.TIE) && (ptag->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
|
||||
}
|
||||
|
|
162
pcsx2/Gif.h
162
pcsx2/Gif.h
|
@ -13,19 +13,57 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ void iopMemoryReserve::Reset()
|
|||
{
|
||||
_parent::Reset();
|
||||
|
||||
pxAssume( iopMem );
|
||||
pxAssert( iopMem );
|
||||
|
||||
if (!psxMemWLUT)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <wx/datetime.h>
|
||||
|
||||
#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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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<<n) ){ //2 is Gif, and every path 3 masking game triggers this :/
|
||||
if( n != 2 && cpuRegs.interrupt & (1<<n) ){ // 2 is Gif, and every path 3 masking game triggers this :/
|
||||
DevCon.Warning( "***** EE > Twice-thrown int on IRQ %d", n );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -81,7 +81,7 @@ void SaveStateBase::Init( SafeArray<u8>* 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 );
|
||||
|
|
|
@ -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 @@ protected:
|
|||
#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 @@ protected:
|
|||
void psxRcntFreeze();
|
||||
void sio2Freeze();
|
||||
|
||||
void gifPathFreeze(); // called by gsFreeze
|
||||
|
||||
void deci2Freeze();
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -51,8 +51,8 @@ void vuMemoryReserve::Reset()
|
|||
{
|
||||
_parent::Reset();
|
||||
|
||||
pxAssume( VU0.Mem );
|
||||
pxAssume( VU1.Mem );
|
||||
pxAssert( VU0.Mem );
|
||||
pxAssert( VU1.Mem );
|
||||
|
||||
memMapVUmicro();
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Common.h"
|
||||
#include "VUops.h"
|
||||
#include "GS.h"
|
||||
#include "Gif_Unit.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
//Simulated GS transfer time done, clear the flags
|
||||
// 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
|
||||
|
||||
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;
|
||||
|
|
|
@ -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<idx>(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<int idx> __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<int idx> __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<int idx> __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<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
template<int idx> __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<int idx> 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<idx>(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<idx>(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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ public:
|
|||
EventListenerHelper_CoreThread( TypeToDispatchTo* dispatchTo )
|
||||
: Owner( *dispatchTo )
|
||||
{
|
||||
pxAssume(dispatchTo != NULL);
|
||||
pxAssert(dispatchTo != NULL);
|
||||
}
|
||||
|
||||
virtual ~EventListenerHelper_CoreThread() throw() {}
|
||||
|
@ -215,7 +215,7 @@ public:
|
|||
EventListenerHelper_Plugins( TypeToDispatchTo* dispatchTo )
|
||||
: Owner( *dispatchTo )
|
||||
{
|
||||
pxAssume(dispatchTo != NULL);
|
||||
pxAssert(dispatchTo != NULL);
|
||||
}
|
||||
|
||||
virtual ~EventListenerHelper_Plugins() throw() {}
|
||||
|
@ -244,7 +244,7 @@ public:
|
|||
EventListenerHelper_AppStatus( TypeToDispatchTo* dispatchTo )
|
||||
: Owner( *dispatchTo )
|
||||
{
|
||||
pxAssume(dispatchTo != NULL);
|
||||
pxAssert(dispatchTo != NULL);
|
||||
}
|
||||
|
||||
virtual ~EventListenerHelper_AppStatus() throw() {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ public:
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ namespace Panels
|
|||
|
||||
virtual wxDirName GetMcdPath() const
|
||||
{
|
||||
pxAssume(m_FolderPicker);
|
||||
pxAssert(m_FolderPicker);
|
||||
return m_FolderPicker->GetPath();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,37 +21,11 @@
|
|||
#include "Vif.h"
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#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<<pathidx), 0, 0 );
|
||||
}
|
||||
|
||||
void SaveStateBase::gifPathFreeze()
|
||||
{
|
||||
FreezeTag( "GIFpath" );
|
||||
Freeze( s_gifPath.path );
|
||||
}
|
||||
#else
|
||||
void SaveStateBase::gifPathFreeze()
|
||||
{
|
||||
//FreezeTag( "GIFpath" );
|
||||
//Freeze( s_gifPath.path );
|
||||
}
|
||||
#endif // USE_OLD_GIF == 1
|
||||
|
||||
|
||||
|
|
|
@ -889,6 +889,18 @@
|
|||
RelativePath="..\..\Gif.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Gif_Unit.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Gif_Unit.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\ps2\GIFpath.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -1355,10 +1367,6 @@
|
|||
<Filter
|
||||
Name="GS"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\ps2\GIFpath.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\GS.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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -230,7 +230,7 @@ protected:
|
|||
}
|
||||
}
|
||||
int x = findFreeRegRec(0);
|
||||
pxAssumeDev( x >= 0, "microVU register allocation failure!" );
|
||||
pxAssertDev( x >= 0, "microVU register allocation failure!" );
|
||||
return x;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff);
|
||||
u8* pDest = &Path1Buffer[Path1WritePos*16];
|
||||
|
||||
if(GSTransferStatus.PTH1 == STOPPED_MODE)
|
||||
{
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
Path1WritePos += 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
|
||||
{*/
|
||||
//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];
|
||||
else {
|
||||
memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), size);
|
||||
}
|
||||
//if(!gifRegs.stat.P1Q) CPU_INT(28, 128);
|
||||
gifRegs.stat.P1Q = true;
|
||||
|
||||
Path1WritePos += size;
|
||||
gsPath1Interrupt();
|
||||
#else
|
||||
addr = (addr & 0x3ff) * 16;
|
||||
u32 diff = 0x4000 - addr;
|
||||
u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, vuRegs[1].Mem, addr);
|
||||
|
||||
pxAssumeMsg((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.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) {
|
||||
|
|
|
@ -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) \
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
pxAssertMsg((Path1WritePos+size < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!");
|
||||
|
||||
if(GSTransferStatus.PTH1 == STOPPED_MODE )
|
||||
{
|
||||
gifRegs.stat.OPH = false;
|
||||
gifRegs.stat.APATH = GIF_APATH_IDLE;
|
||||
}
|
||||
if (size > diff) {
|
||||
//DevCon.Status("XGkick Wrap!");
|
||||
memcpy_qwc(pDest, VU1.Mem + addr, diff);
|
||||
memcpy_qwc(pDest+(diff*16), VU1.Mem, size-diff);
|
||||
}
|
||||
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];
|
||||
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);
|
||||
|
||||
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();
|
||||
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
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue