SPU2: Delay DMA Reads to prevent overrun

Savestate bump
This commit is contained in:
refractionpcsx2 2020-11-29 19:23:27 +00:00
parent 7f9f7d49c6
commit f929d79473
4 changed files with 24 additions and 8 deletions

View File

@ -334,11 +334,9 @@ void V_Core::PlainDMAWrite(u16* pMem, u32 size)
TADR = MADR + (size << 1);
}
void V_Core::DoDMAread(u16* pMem, u32 size)
void V_Core::FinishDMAread()
{
TSA &= 0xfffff;
u32 buff1end = TSA + size;
u32 buff1end = TSA + ReadSize;
u32 buff2end = 0;
if (buff1end > 0x100000)
{
@ -347,8 +345,7 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
}
const u32 buff1size = (buff1end - TSA);
memcpy(pMem, GetMemPtr(TSA), buff1size * 2);
memcpy(DMARPtr, GetMemPtr(TSA), buff1size * 2);
// Note on TSA's position after our copy finishes:
// IRQA should be measured by the end of the writepos+0x20. But the TDA
// should be written back at the precise endpoint of the xfer.
@ -360,7 +357,7 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
// second branch needs cleared:
// It starts at the beginning of memory and moves forward to buff2end
memcpy(&pMem[buff1size], GetMemPtr(0), buff2end * 2);
memcpy(&DMARPtr[buff1size], GetMemPtr(0), buff2end * 2);
TDA = (buff2end + 0x20) & 0xfffff;
@ -396,6 +393,15 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
}
TSA = TDA;
IsDMARead = false;
}
void V_Core::DoDMAread(u16* pMem, u32 size)
{
TSA &= 0xfffff;
DMARPtr = pMem;
ReadSize = size;
IsDMARead = true;
DMAICounter = size;
Regs.STATX &= ~0x80;

View File

@ -437,6 +437,9 @@ struct V_Core
// old dma only
u16* DMAPtr;
u16* DMARPtr; // Mem pointer for DMA Reads
u32 ReadSize;
bool IsDMARead;
u32 MADR;
u32 TADR;
@ -525,6 +528,7 @@ struct V_Core
// old dma only
void DoDMAwrite(u16* pMem, u32 size);
void DoDMAread(u16* pMem, u32 size);
void FinishDMAread();
void AutoDMAReadBuffer(int mode);
void StartADMAWrite(u16* pMem, u32 sz);

View File

@ -427,6 +427,9 @@ __forceinline void TimeUpdate(u32 cClocks)
Cores[0].DMAICounter -= TickInterval;
if (Cores[0].DMAICounter <= 0)
{
if (Cores[0].IsDMARead)
Cores[0].FinishDMAread();
//ConLog("counter set and callback!\n");
Cores[0].MADR = Cores[0].TADR;
Cores[0].DMAICounter = 0;
@ -447,6 +450,9 @@ __forceinline void TimeUpdate(u32 cClocks)
Cores[1].DMAICounter -= TickInterval;
if (Cores[1].DMAICounter <= 0)
{
if (Cores[1].IsDMARead)
Cores[1].FinishDMAread();
Cores[1].MADR = Cores[1].TADR;
Cores[1].DMAICounter = 0;
//ConLog( "* SPU2 > DMA 7 Callback! %d\n", Cycles );

View File

@ -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 = (0x9A10 << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A11 << 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. :)