SPU2: redesign save states into a working state, config saves now works

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2020-09-25 14:14:02 +02:00 committed by refractionpcsx2
parent e8c50aaadf
commit c5b5a3039a
8 changed files with 77 additions and 36 deletions

View File

@ -19,7 +19,7 @@
#include <wx/fileconf.h> #include <wx/fileconf.h>
wxFileConfig *spuConfig = nullptr; wxFileConfig *spuConfig = nullptr;
wxString path(L"~/.pcsx2/inis/spu2-x.ini"); wxString path(L"~/.config/PCSX2/inis/SPU2.ini");
bool pathSet = false; bool pathSet = false;
void initIni() void initIni()
@ -37,7 +37,7 @@ void setIni(const wchar_t *Section)
void CfgSetSettingsDir(const char *dir) void CfgSetSettingsDir(const char *dir)
{ {
FileLog("CfgSetSettingsDir(%s)\n", dir); FileLog("CfgSetSettingsDir(%s)\n", dir);
path = wxString::FromUTF8(dir) + L"/spu2-x.ini"; path = wxString::FromUTF8(dir) + L"/SPU2.ini";
pathSet = true; pathSet = true;
} }

View File

@ -51,11 +51,11 @@ void SysMessage(const wchar_t *fmt, ...)
#include "Utilities/Path.h" #include "Utilities/Path.h"
static wxString CfgFile(L"inis/SPU2-X.ini"); static wxString CfgFile(L"inis/SPU2.ini");
void CfgSetSettingsDir(const char *dir) 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");
} }

View File

@ -23,6 +23,8 @@
#elif defined(_WIN32) #elif defined(_WIN32)
#include "Windows/Dialogs.h" #include "Windows/Dialogs.h"
#endif #endif
#include "R3000A.h"
#include "Utilities/pxStreams.h"
using namespace Threading; using namespace Threading;
@ -377,6 +379,8 @@ s32 SPU2open(void *pDsp)
SPU2close(); SPU2close();
return -1; return -1;
} }
SPU2setDMABaseAddr((uptr)iopMem->Main);
SPU2setClockPtr(&psxRegs.cycle);
return 0; return 0;
} }
@ -611,35 +615,50 @@ s32 SPU2freeze(int mode, freezeData *data)
return 0; 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 ); ScopedLock lock( mtx_SPU2Status );
freezeData fP = { 0, NULL }; freezeData fP = { 0, NULL };
if( !SPU2freeze( FREEZE_SIZE, &fP ) ) if (SPU2freeze( FREEZE_SIZE, &fP )!=0)
fP.size = 0; fP.size = 0;
int fsize = fP.size; Console.Indent().WriteLn( "Loading SPU-2");
state.Freeze( fsize );
Console.Indent().WriteLn( "%s SPU-2", state.IsSaving() ? "Saving" : "Loading"); if (!infp.IsOk() || !infp.Length())
fP.size = fsize;
if( fP.size == 0 ) return;
state.PrepBlock( fP.size );
fP.data = (s8*)state.GetBlockPtr();
if( state.IsSaving() )
{ {
if( !SPU2freeze(FREEZE_SAVE, &fP) ) // no state data to read, but SPU-2 expects some state data?
throw std::runtime_error(" * SPU-2: Error saving state!\n"); // Issue a warning to console...
} if( fP.size != 0 )
else Console.Indent().Warning( "Warning: No data for SPU-2 found. Status may be unpredictable." );
{
if( !SPU2freeze(FREEZE_LOAD, &fP) ) return;
throw std::runtime_error(" * SPU-2: Error loading state!\n");
// 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<s8> 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");
} }

View File

@ -44,7 +44,8 @@ void SPU2setClockPtr(u32 *ptr);
void SPU2async(u32 cycles); void SPU2async(u32 cycles);
s32 SPU2freeze(int mode, freezeData *data); s32 SPU2freeze(int mode, freezeData *data);
void SPU2DoFreeze( SaveStateBase& state ); void SPU2DoFreezeIn( pxInputStream& infp );
void SPU2DoFreezeOut( void* dest );
void SPU2configure(); void SPU2configure();
void SPU2about(); void SPU2about();
s32 SPU2test(); s32 SPU2test();

View File

@ -54,7 +54,7 @@ s32 __fastcall SPU2Savestate::FreezeIt(DataBlock &spud)
spud.spu2id = SAVE_ID; spud.spu2id = SAVE_ID;
spud.version = SAVE_VERSION; 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) if (spu2regs != NULL)
memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs)); 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) { if (spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION) {
fprintf(stderr, "\n*** SPU2-X Warning:\n"); fprintf(stderr, "\n*** SPU2-X Warning:\n");
if (spud.spu2id == SAVE_ID) 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 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, fprintf(stderr,
"\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n" "\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n"
@ -102,7 +102,7 @@ s32 __fastcall SPU2Savestate::ThawIt(DataBlock &spud)
} else { } else {
SndBuffer::ClearContents(); 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 // base stuff
if (spu2regs) if (spu2regs)

View File

@ -225,6 +225,7 @@ SaveStateBase& SaveStateBase::FreezeInternals()
sio2Freeze(); sio2Freeze();
cdrFreeze(); cdrFreeze();
cdvdFreeze(); cdvdFreeze();
// technically this is HLE BIOS territory, but we don't have enough such stuff // technically this is HLE BIOS territory, but we don't have enough such stuff
// to merit an HLE Bios sub-section... yet. // to merit an HLE Bios sub-section... yet.
@ -245,9 +246,6 @@ SaveStateBase& SaveStateBase::FreezePlugins()
FreezeTag( FastFormatAscii().Write("Plugin:%s", tbl_PluginInfo[i].shortname) ); FreezeTag( FastFormatAscii().Write("Plugin:%s", tbl_PluginInfo[i].shortname) );
GetCorePlugins().Freeze( (PluginsEnum_t)i, *this ); GetCorePlugins().Freeze( (PluginsEnum_t)i, *this );
} }
// now with more core!
SPU2DoFreeze(*this);
return *this; return *this;
} }
@ -257,6 +255,7 @@ SaveStateBase& SaveStateBase::FreezeAll()
FreezeBios(); FreezeBios();
FreezeInternals(); FreezeInternals();
FreezePlugins(); FreezePlugins();
return *this; return *this;
} }

View File

@ -28,7 +28,6 @@
#include "IPC.h" #include "IPC.h"
#include "FW.h" #include "FW.h"
#include "SPU2/spu2.h" #include "SPU2/spu2.h"
#include "R3000A.h"
#include "../DebugTools/MIPSAnalyst.h" #include "../DebugTools/MIPSAnalyst.h"
#include "../DebugTools/SymbolMap.h" #include "../DebugTools/SymbolMap.h"
@ -304,8 +303,6 @@ void SysCoreThread::OnResumeInThread( bool isSuspended )
DoCDVDopen(); DoCDVDopen();
FWopen(); FWopen();
SPU2open((void*)pDsp); SPU2open((void*)pDsp);
SPU2setDMABaseAddr((uptr)iopMem->Main);
SPU2setClockPtr(&psxRegs.cycle);
} }

View File

@ -23,6 +23,7 @@
#include "ZipTools/ThreadedZipTools.h" #include "ZipTools/ThreadedZipTools.h"
#include "Utilities/pxStreams.h" #include "Utilities/pxStreams.h"
#include "SPU2/spu2.h"
#include "ConsoleLogger.h" #include "ConsoleLogger.h"
@ -240,6 +241,29 @@ public:
uint GetDataSize() const { return VU1_PROGSIZE; } 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? // [TODO] : Add other components as files to the savestate gzip?
// * VU0/VU1 memory banks? VU0prog, VU1prog, VU0data, VU1data. // * VU0/VU1 memory banks? VU0prog, VU1prog, VU0data, VU1data.
@ -260,6 +284,7 @@ static const std::unique_ptr<BaseSavestateEntry> SavestateEntries[] = {
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1mem), std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1mem),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU0prog), std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU0prog),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1prog), std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1prog),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_SPU2),
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_GS )), std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_GS )),
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_PAD )), std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_PAD )),