From c5b5a3039a2dd17acefd23cb9971d7f6e43392dc Mon Sep 17 00:00:00 2001 From: Gauvain 'GovanifY' Roussel-Tarbouriech Date: Fri, 25 Sep 2020 14:14:02 +0200 Subject: [PATCH] SPU2: redesign save states into a working state, config saves now works --- pcsx2/SPU2/Linux/CfgHelpers.cpp | 4 +- pcsx2/SPU2/Windows/CfgHelpers.cpp | 4 +- pcsx2/SPU2/spu2.cpp | 61 ++++++++++++++++++++----------- pcsx2/SPU2/spu2.h | 3 +- pcsx2/SPU2/spu2freeze.cpp | 8 ++-- pcsx2/SaveState.cpp | 5 +-- pcsx2/System/SysCoreThread.cpp | 3 -- pcsx2/gui/SysState.cpp | 25 +++++++++++++ 8 files changed, 77 insertions(+), 36 deletions(-) diff --git a/pcsx2/SPU2/Linux/CfgHelpers.cpp b/pcsx2/SPU2/Linux/CfgHelpers.cpp index 7c0d3f9eaa..d6a9d38130 100644 --- a/pcsx2/SPU2/Linux/CfgHelpers.cpp +++ b/pcsx2/SPU2/Linux/CfgHelpers.cpp @@ -19,7 +19,7 @@ #include wxFileConfig *spuConfig = nullptr; -wxString path(L"~/.pcsx2/inis/spu2-x.ini"); +wxString path(L"~/.config/PCSX2/inis/SPU2.ini"); bool pathSet = false; void initIni() @@ -37,7 +37,7 @@ void setIni(const wchar_t *Section) void CfgSetSettingsDir(const char *dir) { FileLog("CfgSetSettingsDir(%s)\n", dir); - path = wxString::FromUTF8(dir) + L"/spu2-x.ini"; + path = wxString::FromUTF8(dir) + L"/SPU2.ini"; pathSet = true; } diff --git a/pcsx2/SPU2/Windows/CfgHelpers.cpp b/pcsx2/SPU2/Windows/CfgHelpers.cpp index 020ef232b2..24960d7045 100644 --- a/pcsx2/SPU2/Windows/CfgHelpers.cpp +++ b/pcsx2/SPU2/Windows/CfgHelpers.cpp @@ -51,11 +51,11 @@ void SysMessage(const wchar_t *fmt, ...) #include "Utilities/Path.h" -static wxString CfgFile(L"inis/SPU2-X.ini"); +static wxString CfgFile(L"inis/SPU2.ini"); void CfgSetSettingsDir(const char *dir) { - CfgFile = Path::Combine((dir == NULL) ? wxString(L"inis") : wxString::FromUTF8(dir), L"SPU2-X.ini"); + CfgFile = Path::Combine((dir == NULL) ? wxString(L"inis") : wxString::FromUTF8(dir), L"SPU2.ini"); } diff --git a/pcsx2/SPU2/spu2.cpp b/pcsx2/SPU2/spu2.cpp index a192a7b07a..5591e1aa05 100644 --- a/pcsx2/SPU2/spu2.cpp +++ b/pcsx2/SPU2/spu2.cpp @@ -23,6 +23,8 @@ #elif defined(_WIN32) #include "Windows/Dialogs.h" #endif +#include "R3000A.h" +#include "Utilities/pxStreams.h" using namespace Threading; @@ -377,6 +379,8 @@ s32 SPU2open(void *pDsp) SPU2close(); return -1; } + SPU2setDMABaseAddr((uptr)iopMem->Main); + SPU2setClockPtr(&psxRegs.cycle); return 0; } @@ -611,35 +615,50 @@ s32 SPU2freeze(int mode, freezeData *data) return 0; } -void SPU2DoFreeze( SaveStateBase& state ) +void SPU2DoFreezeOut( void* dest ) +{ + ScopedLock lock( mtx_SPU2Status ); + + freezeData fP = { 0, (s8*)dest }; + if (SPU2freeze( FREEZE_SIZE, &fP)!=0) return; + if (!fP.size) return; + + Console.Indent().WriteLn( "Saving SPU-2"); + + if (SPU2freeze(FREEZE_SAVE, &fP)!=0) + throw std::runtime_error(" * SPU-2: Error saving state!\n"); +} + + +void SPU2DoFreezeIn( pxInputStream& infp ) { ScopedLock lock( mtx_SPU2Status ); freezeData fP = { 0, NULL }; - if( !SPU2freeze( FREEZE_SIZE, &fP ) ) + if (SPU2freeze( FREEZE_SIZE, &fP )!=0) fP.size = 0; - int fsize = fP.size; - state.Freeze( fsize ); + Console.Indent().WriteLn( "Loading SPU-2"); - Console.Indent().WriteLn( "%s SPU-2", state.IsSaving() ? "Saving" : "Loading"); - - fP.size = fsize; - if( fP.size == 0 ) return; - - state.PrepBlock( fP.size ); - fP.data = (s8*)state.GetBlockPtr(); - - if( state.IsSaving() ) + if (!infp.IsOk() || !infp.Length()) { - if( !SPU2freeze(FREEZE_SAVE, &fP) ) - throw std::runtime_error(" * SPU-2: Error saving state!\n"); - } - else - { - if( !SPU2freeze(FREEZE_LOAD, &fP) ) - throw std::runtime_error(" * SPU-2: Error loading state!\n"); + // no state data to read, but SPU-2 expects some state data? + // Issue a warning to console... + if( fP.size != 0 ) + Console.Indent().Warning( "Warning: No data for SPU-2 found. Status may be unpredictable." ); + + return; + + // Note: Size mismatch check could also be done here on loading, but + // some plugins may have built-in version support for non-native formats or + // older versions of a different size... or could give different sizes depending + // on the status of the plugin when loading, so let's ignore it. } - state.CommitBlock( fP.size ); + ScopedAlloc data( fP.size ); + fP.data = data.GetPtr(); + + infp.Read( fP.data, fP.size ); + if (SPU2freeze(FREEZE_LOAD, &fP)!=0) + throw std::runtime_error(" * SPU-2: Error loading state!\n"); } diff --git a/pcsx2/SPU2/spu2.h b/pcsx2/SPU2/spu2.h index 37c193cfc4..60c7f86b64 100644 --- a/pcsx2/SPU2/spu2.h +++ b/pcsx2/SPU2/spu2.h @@ -44,7 +44,8 @@ void SPU2setClockPtr(u32 *ptr); void SPU2async(u32 cycles); s32 SPU2freeze(int mode, freezeData *data); -void SPU2DoFreeze( SaveStateBase& state ); +void SPU2DoFreezeIn( pxInputStream& infp ); +void SPU2DoFreezeOut( void* dest ); void SPU2configure(); void SPU2about(); s32 SPU2test(); diff --git a/pcsx2/SPU2/spu2freeze.cpp b/pcsx2/SPU2/spu2freeze.cpp index 92fd7abf71..0f234672cd 100644 --- a/pcsx2/SPU2/spu2freeze.cpp +++ b/pcsx2/SPU2/spu2freeze.cpp @@ -54,7 +54,7 @@ s32 __fastcall SPU2Savestate::FreezeIt(DataBlock &spud) spud.spu2id = SAVE_ID; spud.version = SAVE_VERSION; - pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted."); + pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while components are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted."); if (spu2regs != NULL) memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs)); @@ -83,9 +83,9 @@ s32 __fastcall SPU2Savestate::ThawIt(DataBlock &spud) if (spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION) { fprintf(stderr, "\n*** SPU2-X Warning:\n"); if (spud.spu2id == SAVE_ID) - fprintf(stderr, "\tSavestate version is from an older version of this plugin.\n"); + fprintf(stderr, "\tSavestate version is from an older version of PCSX2.\n"); else - fprintf(stderr, "\tThe savestate you are trying to load was not made with this plugin.\n"); + fprintf(stderr, "\tThe savestate you are trying to load is incorrect or corrupted.\n"); fprintf(stderr, "\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n" @@ -102,7 +102,7 @@ s32 __fastcall SPU2Savestate::ThawIt(DataBlock &spud) } else { SndBuffer::ClearContents(); - pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted."); + pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while components are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted."); // base stuff if (spu2regs) diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index ef5815cce0..6076b80702 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -225,6 +225,7 @@ SaveStateBase& SaveStateBase::FreezeInternals() sio2Freeze(); cdrFreeze(); cdvdFreeze(); + // technically this is HLE BIOS territory, but we don't have enough such stuff // to merit an HLE Bios sub-section... yet. @@ -245,9 +246,6 @@ SaveStateBase& SaveStateBase::FreezePlugins() FreezeTag( FastFormatAscii().Write("Plugin:%s", tbl_PluginInfo[i].shortname) ); GetCorePlugins().Freeze( (PluginsEnum_t)i, *this ); } - // now with more core! - SPU2DoFreeze(*this); - return *this; } @@ -257,6 +255,7 @@ SaveStateBase& SaveStateBase::FreezeAll() FreezeBios(); FreezeInternals(); FreezePlugins(); + return *this; } diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 75e6e61e05..e420227d70 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -28,7 +28,6 @@ #include "IPC.h" #include "FW.h" #include "SPU2/spu2.h" -#include "R3000A.h" #include "../DebugTools/MIPSAnalyst.h" #include "../DebugTools/SymbolMap.h" @@ -304,8 +303,6 @@ void SysCoreThread::OnResumeInThread( bool isSuspended ) DoCDVDopen(); FWopen(); SPU2open((void*)pDsp); - SPU2setDMABaseAddr((uptr)iopMem->Main); - SPU2setClockPtr(&psxRegs.cycle); } diff --git a/pcsx2/gui/SysState.cpp b/pcsx2/gui/SysState.cpp index 663bd94693..8d95cf0451 100644 --- a/pcsx2/gui/SysState.cpp +++ b/pcsx2/gui/SysState.cpp @@ -23,6 +23,7 @@ #include "ZipTools/ThreadedZipTools.h" #include "Utilities/pxStreams.h" +#include "SPU2/spu2.h" #include "ConsoleLogger.h" @@ -240,6 +241,29 @@ public: uint GetDataSize() const { return VU1_PROGSIZE; } }; +class SavestateEntry_SPU2 : public BaseSavestateEntry +{ +public: + virtual ~SavestateEntry_SPU2() = default; + + wxString GetFilename() const { return L"SPU2.bin"; } + void FreezeIn( pxInputStream& reader ) const { return SPU2DoFreezeIn(reader); } + void FreezeOut( SaveStateBase& writer ) const + { + int size = 0; + freezeData fP = { 0, NULL }; + if(SPU2freeze( FREEZE_SIZE, &fP)==0) { + size = fP.size; + writer.PrepBlock( size ); + SPU2DoFreezeOut(writer.GetBlockPtr()); + writer.CommitBlock( size ); + } + return; + } + bool IsRequired() const { return true; } +}; + + // [TODO] : Add other components as files to the savestate gzip? // * VU0/VU1 memory banks? VU0prog, VU1prog, VU0data, VU1data. @@ -260,6 +284,7 @@ static const std::unique_ptr SavestateEntries[] = { std::unique_ptr(new SavestateEntry_VU1mem), std::unique_ptr(new SavestateEntry_VU0prog), std::unique_ptr(new SavestateEntry_VU1prog), + std::unique_ptr(new SavestateEntry_SPU2), std::unique_ptr(new PluginSavestateEntry( PluginId_GS )), std::unique_ptr(new PluginSavestateEntry( PluginId_PAD )),