diff --git a/pcsx2/SPU2/spu2freeze.cpp b/pcsx2/SPU2/spu2freeze.cpp index 8e11e5dc62..1f66a42aea 100644 --- a/pcsx2/SPU2/spu2freeze.cpp +++ b/pcsx2/SPU2/spu2freeze.cpp @@ -14,8 +14,9 @@ */ #include "PrecompiledHeader.h" -#include "Global.h" -#include "spu2.h" // hopefully temporary, until I resolve lClocks depdendency +#include "SPU2/Global.h" +#include "SPU2/spu2.h" // hopefully temporary, until I resolve lClocks depdendency +#include "IopMem.h" namespace SPU2Savestate { @@ -63,6 +64,28 @@ s32 SPU2Savestate::FreezeIt(DataBlock& spud) memcpy(spud.Cores, Cores, sizeof(Cores)); memcpy(&spud.Spdif, &Spdif, sizeof(Spdif)); + // Convert pointers to offsets so we can safely restore them when loading. + // We use -1 for null, and anything else as an offset from iop memory. +#define FIX_POINTER(x) \ + if (!(x)) \ + { \ + x = reinterpret_cast(-1); \ + } \ + else \ + { \ + pxAssert(reinterpret_cast((x)) >= iopPhysMem(0) && reinterpret_cast((x)) < iopPhysMem(0x1fffff)); \ + x = reinterpret_cast(reinterpret_cast((x)) - iopPhysMem(0)); \ + } + + for (u32 i = 0; i < 2; i++) + { + V_Core& core = spud.Cores[i]; + FIX_POINTER(core.DMAPtr); + FIX_POINTER(core.DMARPtr); + } + +#undef FIX_POINTER + spud.OutPos = OutPos; spud.InputPos = InputPos; spud.Cycles = Cycles; @@ -115,6 +138,27 @@ s32 SPU2Savestate::ThawIt(DataBlock& spud) memcpy(Cores, spud.Cores, sizeof(Cores)); memcpy(&Spdif, &spud.Spdif, sizeof(Spdif)); + // Reverse the pointer offset from above. +#define FIX_POINTER(x) \ + if ((x) == reinterpret_cast(-1)) \ + { \ + x = nullptr; \ + } \ + else \ + { \ + pxAssert(reinterpret_cast((x)) <= 0x1fffff); \ + x = reinterpret_cast(iopPhysMem(0) + reinterpret_cast((x))); \ + } + + for (u32 i = 0; i < 2; i++) + { + V_Core& core = spud.Cores[i]; + FIX_POINTER(core.DMAPtr); + FIX_POINTER(core.DMARPtr); + } + +#undef FIX_POINTER + OutPos = spud.OutPos; InputPos = spud.InputPos; Cycles = spud.Cycles; @@ -134,13 +178,6 @@ s32 SPU2Savestate::ThawIt(DataBlock& spud) Cores[c].Voices[v].SBuffer = pcm_cache_data[cacheIdx].Sampledata; } } - - // HACKFIX!! DMAPtr can be invalid after a savestate load, so force it to nullptr and - // ignore it on any pending ADMA writes. (the DMAPtr concept used to work in old VM - // editions of PCSX2 with fixed addressing, but new PCSX2s have dynamic memory - // addressing). - - Cores[0].DMAPtr = Cores[1].DMAPtr = nullptr; } return 0; } diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index a7f0d92219..d53a05f84a 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -36,7 +36,7 @@ enum class FreezeAction // [SAVEVERSION+] // This informs the auto updater that the users savestates will be invalidated. -static const u32 g_SaveVersion = (0x9A34 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A35 << 16) | 0x0000; // the freezing data between submodules and core