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:
Gregory Hainaut 2014-05-02 23:03:02 +02:00
parent 3a46634f4a
commit 0bf7a35a53
10 changed files with 85 additions and 13 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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
};

View File

@ -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

View File

@ -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 }
};

View File

@ -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) {

View File

@ -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

View File

@ -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);
}

View File

@ -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;}

View File

@ -27,8 +27,10 @@ EXPORTS
GSconfigure
GStest
GSabout
GSreadFIFO
GSreadFIFO2
GSinitReadFIFO
GSreadFIFO
GSinitReadFIFO2
GSreadFIFO2
GSirqCallback
GSsetupRecording
GSsetGameCRC