mirror of https://github.com/PCSX2/pcsx2.git
pcsx2: improve the GS read fifo API
1/ initReadFifo will be first called on the GS thread (openGL can only be done on the GS thread) 2/ readFifo will be called on the EE thread. It is not safe too access eeMem from GS because of memory is virtual Fix "recent" regression (crash) on Kingdom heart and others game too. v2: add a len check on GSState::InitReadFIFO
This commit is contained in:
parent
3a46634f4a
commit
0bf7a35a53
|
@ -255,7 +255,9 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size);
|
|||
void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits)
|
||||
void CALLBACK GSgifSoftReset(u32 mask);
|
||||
void CALLBACK GSreadFIFO(u64 *mem);
|
||||
void CALLBACK GSinitReadFIFO(u64 *mem);
|
||||
void CALLBACK GSreadFIFO2(u64 *mem, int qwc);
|
||||
void CALLBACK GSinitReadFIFO2(u64 *mem, int qwc);
|
||||
|
||||
// extended funcs
|
||||
|
||||
|
@ -580,6 +582,8 @@ typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size);
|
|||
typedef void (CALLBACK* _GSgifSoftReset)(u32 mask);
|
||||
typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem);
|
||||
typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc);
|
||||
typedef void (CALLBACK* _GSinitReadFIFO)(u64 *pMem);
|
||||
typedef void (CALLBACK* _GSinitReadFIFO2)(u64 *pMem, int qwc);
|
||||
|
||||
typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename);
|
||||
typedef void (CALLBACK* _GSgetTitleInfo2)(char* dest, size_t length);
|
||||
|
@ -734,7 +738,9 @@ extern _GSgifTransfer2 GSgifTransfer2;
|
|||
extern _GSgifTransfer3 GSgifTransfer3;
|
||||
extern _GSgifSoftReset GSgifSoftReset;
|
||||
extern _GSreadFIFO GSreadFIFO;
|
||||
extern _GSinitReadFIFO GSinitReadFIFO;
|
||||
extern _GSreadFIFO2 GSreadFIFO2;
|
||||
extern _GSinitReadFIFO2 GSinitReadFIFO2;
|
||||
|
||||
extern _GSchangeSaveState GSchangeSaveState;
|
||||
extern _GSgetTitleInfo2 GSgetTitleInfo2;
|
||||
|
|
|
@ -51,8 +51,11 @@ void __fastcall ReadFIFO_VIF1(mem128_t* out)
|
|||
}
|
||||
if (vif1Regs.stat.FQC > 0) {
|
||||
GetMTGS().WaitGS();
|
||||
GetMTGS().SendPointerPacket(GS_RINGTYPE_READ_FIFO1, 0, out);
|
||||
GetMTGS().WaitGS(false); // wait without reg sync
|
||||
if (GSinitReadFIFO) {
|
||||
GetMTGS().SendPointerPacket(GS_RINGTYPE_INIT_READ_FIFO1, 0, out);
|
||||
GetMTGS().WaitGS(false); // wait without reg sync
|
||||
}
|
||||
GSreadFIFO((u64*)out);
|
||||
vif1.GSLastDownloadSize--;
|
||||
GUNIT_LOG("ReadFIFO_VIF1");
|
||||
if (vif1.GSLastDownloadSize <= 16)
|
||||
|
|
|
@ -247,8 +247,8 @@ enum MTGS_RingCommand
|
|||
, GS_RINGTYPE_CRC
|
||||
, GS_RINGTYPE_GSPACKET
|
||||
, GS_RINGTYPE_MTVU_GSPACKET
|
||||
, GS_RINGTYPE_READ_FIFO1
|
||||
, GS_RINGTYPE_READ_FIFO2
|
||||
, GS_RINGTYPE_INIT_READ_FIFO1
|
||||
, GS_RINGTYPE_INIT_READ_FIFO2
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -495,14 +495,16 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
GSsetGameCRC( tag.data[0], 0 );
|
||||
break;
|
||||
|
||||
case GS_RINGTYPE_READ_FIFO1:
|
||||
case GS_RINGTYPE_INIT_READ_FIFO1:
|
||||
MTGS_LOG( "(MTGS Packet Read) ringtype=Fifo1" );
|
||||
GSreadFIFO( (u64*)tag.data[1]);
|
||||
if (GSinitReadFIFO)
|
||||
GSinitReadFIFO( (u64*)tag.data[1]);
|
||||
break;
|
||||
|
||||
case GS_RINGTYPE_READ_FIFO2:
|
||||
case GS_RINGTYPE_INIT_READ_FIFO2:
|
||||
MTGS_LOG( "(MTGS Packet Read) ringtype=Fifo2, size=%d", tag.data[0] );
|
||||
GSreadFIFO2( (u64*)tag.data[1], tag.data[0]);
|
||||
if (GSinitReadFIFO2)
|
||||
GSinitReadFIFO2( (u64*)tag.data[1], tag.data[0]);
|
||||
break;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
|
|
@ -156,6 +156,8 @@ _GSgifTransfer3 GSgifTransfer3;
|
|||
_GSgifSoftReset GSgifSoftReset;
|
||||
_GSreadFIFO GSreadFIFO;
|
||||
_GSreadFIFO2 GSreadFIFO2;
|
||||
_GSinitReadFIFO GSinitReadFIFO;
|
||||
_GSinitReadFIFO2 GSinitReadFIFO2;
|
||||
_GSchangeSaveState GSchangeSaveState;
|
||||
_GSgetTitleInfo2 GSgetTitleInfo2;
|
||||
_GSmakeSnapshot GSmakeSnapshot;
|
||||
|
@ -406,6 +408,8 @@ static const LegacyApi_OptMethod s_MethMessOpt_GS[] =
|
|||
{ "GSmakeSnapshot2", (vMeth**)&GSmakeSnapshot2 },
|
||||
{ "GSgifSoftReset", (vMeth**)&GSgifSoftReset },
|
||||
{ "GSreadFIFO", (vMeth**)&GSreadFIFO },
|
||||
{ "GSinitReadFIFO", (vMeth**)&GSinitReadFIFO },
|
||||
{ "GSinitReadFIFO2", (vMeth**)&GSinitReadFIFO2 },
|
||||
{ "GSgifTransfer1", (vMeth**)&GSgifTransfer1 },
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
@ -68,8 +68,11 @@ void vif1TransferToMemory()
|
|||
}
|
||||
|
||||
GetMTGS().WaitGS();
|
||||
GetMTGS().SendPointerPacket(GS_RINGTYPE_READ_FIFO2, size, pMem);
|
||||
GetMTGS().WaitGS(false); // wait without reg sync
|
||||
if (GSinitReadFIFO2) {
|
||||
GetMTGS().SendPointerPacket(GS_RINGTYPE_INIT_READ_FIFO2, size, pMem);
|
||||
GetMTGS().WaitGS(false); // wait without reg sync
|
||||
}
|
||||
GSreadFIFO2((u64*)pMem, size);
|
||||
pMem += size;
|
||||
|
||||
if(pMem < pMemEnd) {
|
||||
|
|
|
@ -542,6 +542,17 @@ EXPORT_C GSwriteCSR(uint32 csr)
|
|||
}
|
||||
}
|
||||
|
||||
EXPORT_C GSinitReadFIFO(uint8* mem)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_gs->InitReadFIFO(mem, 1);
|
||||
}
|
||||
catch (GSDXRecoverableError)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO(uint8* mem)
|
||||
{
|
||||
try
|
||||
|
@ -553,6 +564,17 @@ EXPORT_C GSreadFIFO(uint8* mem)
|
|||
}
|
||||
}
|
||||
|
||||
EXPORT_C GSinitReadFIFO2(uint8* mem, uint32 size)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_gs->InitReadFIFO(mem, size);
|
||||
}
|
||||
catch (GSDXRecoverableError)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO2(uint8* mem, uint32 size)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -30,6 +30,7 @@ GSState::GSState()
|
|||
, m_mt(false)
|
||||
, m_irq(NULL)
|
||||
, m_path3hack(0)
|
||||
, m_init_read_fifo_supported(false)
|
||||
, m_q(1.0f)
|
||||
, m_texflush(true)
|
||||
, m_vt(this)
|
||||
|
@ -1509,10 +1510,13 @@ void GSState::Write(const uint8* mem, int len)
|
|||
m_mem.m_clut.Invalidate();
|
||||
}
|
||||
|
||||
void GSState::Read(uint8* mem, int len)
|
||||
void GSState::InitReadFIFO(uint8* mem, int len)
|
||||
{
|
||||
if(len <= 0) return;
|
||||
|
||||
// Allow to keep compatibility with older PCSX2
|
||||
m_init_read_fifo_supported = true;
|
||||
|
||||
int sx = m_env.TRXPOS.SSAX;
|
||||
int sy = m_env.TRXPOS.SSAY;
|
||||
int w = m_env.TRXREG.RRW;
|
||||
|
@ -1529,6 +1533,30 @@ void GSState::Read(uint8* mem, int len)
|
|||
{
|
||||
InvalidateLocalMem(m_env.BITBLTBUF, GSVector4i(sx, sy, sx + w, sy + h));
|
||||
}
|
||||
}
|
||||
|
||||
void GSState::Read(uint8* mem, int len)
|
||||
{
|
||||
if(len <= 0) return;
|
||||
|
||||
int sx = m_env.TRXPOS.SSAX;
|
||||
int sy = m_env.TRXPOS.SSAY;
|
||||
int w = m_env.TRXREG.RRW;
|
||||
int h = m_env.TRXREG.RRH;
|
||||
|
||||
// printf("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n", len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h);
|
||||
|
||||
if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].trbpp, len))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_init_read_fifo_supported) {
|
||||
if(m_tr.x == sx && m_tr.y == sy)
|
||||
{
|
||||
InvalidateLocalMem(m_env.BITBLTBUF, GSVector4i(sx, sy, sx + w, sy + h));
|
||||
}
|
||||
}
|
||||
|
||||
m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ class GSState : public GSAlignedClass<32>
|
|||
bool m_mt;
|
||||
void (*m_irq)();
|
||||
bool m_path3hack;
|
||||
bool m_init_read_fifo_supported;
|
||||
|
||||
struct GSTransferBuffer
|
||||
{
|
||||
|
@ -232,6 +233,7 @@ public:
|
|||
void Move();
|
||||
void Write(const uint8* mem, int len);
|
||||
void Read(uint8* mem, int len);
|
||||
void InitReadFIFO(uint8* mem, int len);
|
||||
|
||||
void SoftReset(uint32 mask);
|
||||
void WriteCSR(uint32 csr) {m_regs->CSR.u32[1] = csr;}
|
||||
|
|
|
@ -27,7 +27,9 @@ EXPORTS
|
|||
GSconfigure
|
||||
GStest
|
||||
GSabout
|
||||
GSinitReadFIFO
|
||||
GSreadFIFO
|
||||
GSinitReadFIFO2
|
||||
GSreadFIFO2
|
||||
GSirqCallback
|
||||
GSsetupRecording
|
||||
|
|
Loading…
Reference in New Issue