mirror of https://github.com/PCSX2/pcsx2.git
SPU2: Handle partial ADMA Transfers
This commit is contained in:
parent
7c37e86283
commit
c7267d3665
|
@ -98,11 +98,18 @@ void V_Core::LogAutoDMA(FILE* fp)
|
||||||
void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo
|
void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo
|
||||||
{
|
{
|
||||||
int spos = ActiveTSA & 0x100; // Starting position passed by TSA
|
int spos = ActiveTSA & 0x100; // Starting position passed by TSA
|
||||||
|
bool leftbuffer = !(ActiveTSA & 0x80);
|
||||||
if (spos == (OutPos & 0x100))
|
if (spos == (OutPos & 0x100))
|
||||||
|
{
|
||||||
|
//ConLog("Ignoring buffer update Pos %x OutPos %x\n", spos, OutPos);
|
||||||
return;
|
return;
|
||||||
LogAutoDMA(Index ? ADMA7LogFile : ADMA4LogFile);
|
}
|
||||||
|
|
||||||
|
int size = std::min(InputDataLeft, (u32)0x200);
|
||||||
|
if (!leftbuffer)
|
||||||
|
size = 0x100;
|
||||||
|
LogAutoDMA(Index ? ADMA7LogFile : ADMA4LogFile);
|
||||||
|
//ConLog("Refilling ADMA buffer at %x OutPos %x with %x\n", spos, OutPos, size);
|
||||||
// HACKFIX!! DMAPtr can be invalid after a savestate load, so the savestate just forces it
|
// HACKFIX!! DMAPtr can be invalid after a savestate load, so the savestate just forces it
|
||||||
// to nullptr and we ignore it here. (used to work in old VM editions of PCSX2 with fixed
|
// to nullptr and we ignore it here. (used to work in old VM editions of PCSX2 with fixed
|
||||||
// addressing, but new PCSX2s have dynamic memory addressing).
|
// addressing, but new PCSX2s have dynamic memory addressing).
|
||||||
|
@ -111,44 +118,45 @@ void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not spl
|
||||||
{
|
{
|
||||||
if (DMAPtr != nullptr)
|
if (DMAPtr != nullptr)
|
||||||
//memcpy((ADMATempBuffer+(spos<<1)),DMAPtr+InputDataProgress,0x400);
|
//memcpy((ADMATempBuffer+(spos<<1)),DMAPtr+InputDataProgress,0x400);
|
||||||
memcpy(GetMemPtr(0x2000 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x400);
|
memcpy(GetMemPtr(0x2000 + (Index << 10) + spos), DMAPtr + InputDataProgress, size);
|
||||||
MADR += 0x400;
|
MADR += size;
|
||||||
InputDataLeft -= 0x200;
|
InputDataLeft -= 0x200;
|
||||||
InputDataProgress += 0x200;
|
InputDataProgress += 0x200;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
if (!leftbuffer)
|
||||||
|
spos |= 0x200;
|
||||||
|
else
|
||||||
|
spos &= ~0x200;
|
||||||
|
//ConLog("Filling %s buffer\n", leftbuffer ? "Left" : "Right");
|
||||||
if (DMAPtr != nullptr)
|
if (DMAPtr != nullptr)
|
||||||
//memcpy((ADMATempBuffer+spos),DMAPtr+InputDataProgress,0x200);
|
//memcpy((ADMATempBuffer+spos),DMAPtr+InputDataProgress,0x200);
|
||||||
memcpy(GetMemPtr(0x2000 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x200);
|
memcpy(GetMemPtr(0x2000 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x200);
|
||||||
MADR += 0x200;
|
MADR += 0x200;
|
||||||
InputDataLeft -= 0x100;
|
InputDataLeft -= 0x100;
|
||||||
InputDataProgress += 0x100;
|
InputDataProgress += 0x100;
|
||||||
|
leftbuffer = !leftbuffer;
|
||||||
if (DMAPtr != nullptr)
|
size -= 0x100;
|
||||||
//memcpy((ADMATempBuffer+spos+0x200),DMAPtr+InputDataProgress,0x200);
|
ActiveTSA += 0x80;
|
||||||
memcpy(GetMemPtr(0x2200 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x200);
|
|
||||||
MADR += 0x200;
|
|
||||||
InputDataLeft -= 0x100;
|
|
||||||
InputDataProgress += 0x100;
|
|
||||||
ActiveTSA += 0x100;
|
|
||||||
ActiveTSA &= ~0x200;
|
ActiveTSA &= ~0x200;
|
||||||
TSA = ActiveTSA;
|
TSA = ActiveTSA;
|
||||||
}
|
}
|
||||||
// See ReadInput at mixer.cpp for explanation on the commented out lines
|
}
|
||||||
//
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
||||||
{
|
{
|
||||||
int size = (sz) & (~511);
|
int size = sz;
|
||||||
|
|
||||||
if (cyclePtr != nullptr)
|
if (cyclePtr != nullptr)
|
||||||
TimeUpdate(*cyclePtr);
|
TimeUpdate(*cyclePtr);
|
||||||
|
|
||||||
if (MsgAutoDMA())
|
if (MsgAutoDMA())
|
||||||
ConLog("* SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
|
ConLog("* SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).OutPos %x\n",
|
||||||
GetDmaIndexChar(), size << 1, ActiveTSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0xffff);
|
GetDmaIndexChar(), size << 1, ActiveTSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0xffff, OutPos);
|
||||||
|
|
||||||
InputDataProgress = 0;
|
InputDataProgress = 0;
|
||||||
if ((AutoDMACtrl & (Index + 1)) == 0)
|
if ((AutoDMACtrl & (Index + 1)) == 0)
|
||||||
|
@ -157,7 +165,7 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
||||||
DMAICounter = size * 4;
|
DMAICounter = size * 4;
|
||||||
LastClock = *cyclePtr;
|
LastClock = *cyclePtr;
|
||||||
}
|
}
|
||||||
else if (size >= 512)
|
else if (size >= 256)
|
||||||
{
|
{
|
||||||
InputDataLeft = size;
|
InputDataLeft = size;
|
||||||
AutoDMACtrl &= 3;
|
AutoDMACtrl &= 3;
|
||||||
|
@ -178,7 +186,6 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
||||||
|
|
||||||
AdmaInProgress = 1;
|
AdmaInProgress = 1;
|
||||||
|
|
||||||
// Klonoa 2
|
|
||||||
if (!InputDataLeft)
|
if (!InputDataLeft)
|
||||||
{
|
{
|
||||||
DMAICounter = size * 4;
|
DMAICounter = size * 4;
|
||||||
|
@ -190,7 +197,7 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size = sz;
|
ConLog("ADMA%c Error Size of %x too small\n", GetDmaIndexChar(), size);
|
||||||
InputDataLeft = 0;
|
InputDataLeft = 0;
|
||||||
DMAICounter = size * 4;
|
DMAICounter = size * 4;
|
||||||
LastClock = *cyclePtr;
|
LastClock = *cyclePtr;
|
||||||
|
|
|
@ -48,9 +48,6 @@ StereoOut32 V_Core::ReadInput_HiFi()
|
||||||
retval.Right >>= 4;
|
retval.Right >>= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Why does CDDA mode check for InputPos == 0x100? In the old code, SPDIF mode did not but CDDA did.
|
|
||||||
// One of these seems wrong, they should be the same. Since standard ADMA checks too I'm assuming that as default. -- air
|
|
||||||
|
|
||||||
if ((OutPos == 0xFF || OutPos == 0x1FF))
|
if ((OutPos == 0xFF || OutPos == 0x1FF))
|
||||||
{
|
{
|
||||||
if (InputDataLeft >= 0x200)
|
if (InputDataLeft >= 0x200)
|
||||||
|
@ -103,9 +100,9 @@ StereoOut32 V_Core::ReadInput()
|
||||||
DebugCores[Index].admaWaveformR[OutPos % 0x100] = retval.Right;
|
DebugCores[Index].admaWaveformR[OutPos % 0x100] = retval.Right;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((OutPos == 0xFF || OutPos == 0x1FF))
|
if (OutPos == 0xFF || OutPos == 0x1FF || OutPos == 0x7F || OutPos == 0x17F)
|
||||||
{
|
{
|
||||||
if (InputDataLeft >= 0x200)
|
if (InputDataLeft >= 0x100)
|
||||||
{
|
{
|
||||||
//u8 k=InputDataLeft>=InputDataProgress;
|
//u8 k=InputDataLeft>=InputDataProgress;
|
||||||
int oldOutPos = OutPos;
|
int oldOutPos = OutPos;
|
||||||
|
@ -113,7 +110,7 @@ StereoOut32 V_Core::ReadInput()
|
||||||
AutoDMAReadBuffer(0);
|
AutoDMAReadBuffer(0);
|
||||||
OutPos = oldOutPos;
|
OutPos = oldOutPos;
|
||||||
AdmaInProgress = 1;
|
AdmaInProgress = 1;
|
||||||
if (InputDataLeft < 0x200)
|
if (InputDataLeft < 0x100)
|
||||||
{
|
{
|
||||||
if ((AutoDMACtrl & (Index + 1)))
|
if ((AutoDMACtrl & (Index + 1)))
|
||||||
AutoDMACtrl |= ~3;
|
AutoDMACtrl |= ~3;
|
||||||
|
|
Loading…
Reference in New Issue