From 4497532edb6e738b2324972bc924db65c81f6c37 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sat, 23 Jan 2021 06:20:14 +0000 Subject: [PATCH] SPU2: Improve ADMA behaviour/timing --- pcsx2/SPU2/Dma.cpp | 23 +++++++++++++++-------- pcsx2/SPU2/ReadInput.cpp | 38 +++++++++++--------------------------- pcsx2/SPU2/spu2sys.cpp | 6 +++--- 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/pcsx2/SPU2/Dma.cpp b/pcsx2/SPU2/Dma.cpp index 99e7aecbd9..39b7967a78 100644 --- a/pcsx2/SPU2/Dma.cpp +++ b/pcsx2/SPU2/Dma.cpp @@ -97,8 +97,10 @@ void V_Core::LogAutoDMA(FILE* fp) void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo { - int spos = ((InputPosRead + 0xff) & 0x100); //starting position of the free buffer + int spos = ActiveTSA & 0x100;// ((InputPosRead + 0xff) & 0x100); //starting position of the free buffer + if (spos == (OutPos & 0x100)) + return; LogAutoDMA(Index ? ADMA7LogFile : ADMA4LogFile); // HACKFIX!! DMAPtr can be invalid after a savestate load, so the savestate just forces it @@ -129,6 +131,9 @@ void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not spl MADR += 0x200; InputDataLeft -= 0x100; InputDataProgress += 0x100; + ActiveTSA += 0x100; + ActiveTSA &= ~0x200; + TSA = ActiveTSA; } // See ReadInput at mixer.cpp for explanation on the commented out lines // @@ -155,6 +160,7 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz) else if (size >= 512) { InputDataLeft = size; + AutoDMACtrl &= 3; if (AdmaInProgress == 0) { #ifdef PCM24_S1_INTERLEAVE @@ -172,15 +178,18 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz) AutoDMAReadBuffer(0); #endif + + AdmaInProgress = 1; + // Klonoa 2 - if (size == 512) + if (!InputDataLeft) { DMAICounter = size * 4; LastClock = *cyclePtr; + AdmaInProgress = 0; + AutoDMACtrl |= ~3; } } - - AdmaInProgress = 1; } else { @@ -357,8 +366,6 @@ void V_Core::FinishDMAwrite() void V_Core::FinishDMAread() { - if (ActiveTSA != TSA) - ConLog("Read WTF TSA %x Active %x\n", TSA, ActiveTSA); u32 buff1end = ActiveTSA + std::min(ReadSize, (u32)0x100 + std::abs(DMAICounter / 4)); u32 start = ActiveTSA; u32 buff2end = 0; @@ -520,7 +527,7 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size) else { PlainDMAWrite(pMem, size); + Regs.STATX &= ~0x80; + Regs.STATX |= 0x400; } - Regs.STATX &= ~0x80; - Regs.STATX |= 0x400; } diff --git a/pcsx2/SPU2/ReadInput.cpp b/pcsx2/SPU2/ReadInput.cpp index 3fb6dee0bb..bdb5b2fe62 100644 --- a/pcsx2/SPU2/ReadInput.cpp +++ b/pcsx2/SPU2/ReadInput.cpp @@ -123,7 +123,7 @@ StereoOut32 V_Core::ReadInput() if ((Index != 1) || ((PlayMode & 2) == 0)) { for (int i = 0; i < 2; i++) - if (Cores[i].IRQEnable && 0x2000 + (Index << 10) + InputPosRead == (Cores[i].IRQA & 0xfffffdff)) + if (Cores[i].IRQEnable && 0x2000 + (Index << 10) + OutPos == (Cores[i].IRQA & 0xfffffdff)) SetIrqCall(i); //retval = StereoOut32( @@ -131,8 +131,8 @@ StereoOut32 V_Core::ReadInput() // (s32)ADMATempBuffer[InputPosRead+0x200] //); retval = StereoOut32( - (s32)(*GetMemPtr(0x2000 + (Index << 10) + InputPosRead)), - (s32)(*GetMemPtr(0x2200 + (Index << 10) + InputPosRead))); + (s32)(*GetMemPtr(0x2000 + (Index << 10) + OutPos)), + (s32)(*GetMemPtr(0x2200 + (Index << 10) + OutPos))); } #ifdef PCSX2_DEVBUILD @@ -142,21 +142,19 @@ StereoOut32 V_Core::ReadInput() InputPosRead++; - if ((AutoDMACtrl & (Index + 1)) && (InputPosRead == 0x100 || InputPosRead == 0x200)) + if ((OutPos == 0xFF || OutPos == 0x1FF)) { - AdmaInProgress = 0; if (InputDataLeft >= 0x200) { //u8 k=InputDataLeft>=InputDataProgress; - + int oldOutPos = OutPos; + OutPos = (OutPos + 1) & 0x1FF; AutoDMAReadBuffer(0); - + OutPos = oldOutPos; AdmaInProgress = 1; - ActiveTSA = (Index << 10) + InputPosRead; - TSA = ActiveTSA; if (InputDataLeft < 0x200) { - if((AutoDMACtrl & (Index + 1))) + if ((AutoDMACtrl & (Index + 1))) AutoDMACtrl |= ~3; if (IsDevBuild) @@ -168,24 +166,10 @@ StereoOut32 V_Core::ReadInput() ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); } } - + AdmaInProgress = 0; InputDataLeft = 0; - // Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed. - //DMAICounter = 1; - if (Index == 0) - { - if (!SPU2_dummy_callback) - spu2DMA4Irq(); - else - SPU2interruptDMA4(); - } - else - { - if (!SPU2_dummy_callback) - spu2DMA7Irq(); - else - SPU2interruptDMA7(); - } + DMAICounter = 0x200 * 4; + LastClock = *cyclePtr; } } } diff --git a/pcsx2/SPU2/spu2sys.cpp b/pcsx2/SPU2/spu2sys.cpp index 4d81b1d12d..095d7fc995 100644 --- a/pcsx2/SPU2/spu2sys.cpp +++ b/pcsx2/SPU2/spu2sys.cpp @@ -1522,11 +1522,11 @@ static void __fastcall RegWrite_Core(u16 value) return; } thiscore.AutoDMACtrl = value; - if (value == 0 && thiscore.AdmaInProgress && (thiscore.Regs.STATX & 0x400)) + if (value == 0 && thiscore.AdmaInProgress) { + // Kill the current transfer so it doesn't continue thiscore.AdmaInProgress = 0; - thiscore.Regs.STATX &= ~0x400; // Set DMA as not busy transferring - // No need to end the DMA here, the IOP seems to handle that + thiscore.InputDataLeft = 0; } break;