2009-09-08 12:08:10 +00:00
|
|
|
/* PCSX2 - PS2 Emulator for PCs
|
2021-07-23 12:23:23 +00:00
|
|
|
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
2010-04-25 00:31:27 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
2009-02-09 21:15:56 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
2009-02-09 21:15:56 +00:00
|
|
|
*/
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
#pragma once
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-03-13 04:49:23 +00:00
|
|
|
#include "System.h"
|
2021-09-01 20:31:46 +00:00
|
|
|
#include "common/Exceptions.h"
|
2009-03-19 04:16:24 +00:00
|
|
|
|
2021-07-06 06:08:18 +00:00
|
|
|
enum class FreezeAction
|
|
|
|
{
|
|
|
|
Load,
|
|
|
|
Save,
|
|
|
|
Size,
|
|
|
|
};
|
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
// Savestate Versioning!
|
|
|
|
// If you make changes to the savestate version, please increment the value below.
|
2009-03-19 04:16:24 +00:00
|
|
|
// If the change is minor and compatibility with old states is retained, increment
|
|
|
|
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
|
|
|
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2021-09-10 21:03:20 +00:00
|
|
|
static const u32 g_SaveVersion = (0x9A24 << 16) | 0x0000;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2021-05-11 08:58:44 +00:00
|
|
|
// the freezing data between submodules and core
|
|
|
|
// an interesting thing to note is that this dates back from before plugin
|
|
|
|
// merges and was used to pass data between plugins and cores, although the
|
|
|
|
// struct was system dependant as the size of int differs between systems, thus
|
|
|
|
// subsystems making use of freezeData, like GSDump and save states aren't
|
|
|
|
// necessarily portable; we might want to investigate this in the future -- govanify
|
2021-09-07 09:46:33 +00:00
|
|
|
struct freezeData
|
2021-05-11 08:58:44 +00:00
|
|
|
{
|
|
|
|
int size;
|
2021-09-07 09:42:47 +00:00
|
|
|
u8 *data;
|
2021-09-07 09:46:33 +00:00
|
|
|
};
|
2021-05-11 08:58:44 +00:00
|
|
|
|
2009-03-06 19:01:30 +00:00
|
|
|
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
2009-02-09 21:15:56 +00:00
|
|
|
// between the GS saving function and the MTGS's needs. :)
|
|
|
|
extern s32 CALLBACK gsSafeFreeze( int mode, freezeData *data );
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// SaveStateBase class
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// Provides the base API for both loading and saving savestates. Normally you'll want to
|
|
|
|
// use one of the four "functional" derived classes rather than this class directly: gzLoadingState, gzSavingState (gzipped disk-saved
|
2009-02-09 21:15:56 +00:00
|
|
|
// states), and memLoadingState, memSavingState (uncompressed memory states).
|
2009-09-16 17:23:02 +00:00
|
|
|
class SaveStateBase
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
protected:
|
2010-04-28 16:25:04 +00:00
|
|
|
VmStateBuffer* m_memory;
|
2009-09-16 17:23:02 +00:00
|
|
|
char m_tagspace[32];
|
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
u32 m_version; // version of the savestate being loaded.
|
2009-09-16 17:23:02 +00:00
|
|
|
|
2010-11-22 16:24:54 +00:00
|
|
|
int m_idx; // current read/write index of the allocation
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
public:
|
2010-04-28 16:25:04 +00:00
|
|
|
SaveStateBase( VmStateBuffer& memblock );
|
|
|
|
SaveStateBase( VmStateBuffer* memblock );
|
2009-09-16 17:23:02 +00:00
|
|
|
virtual ~SaveStateBase() { }
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-04-02 11:30:23 +00:00
|
|
|
static wxString GetFilename( int slot );
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
// Gets the version of savestate that this object is acting on.
|
|
|
|
// The version refers to the low 16 bits only (high 16 bits classifies Pcsx2 build types)
|
|
|
|
u32 GetVersion() const
|
|
|
|
{
|
2009-03-04 13:00:32 +00:00
|
|
|
return (m_version & 0xffff);
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
|
2010-12-14 07:28:05 +00:00
|
|
|
virtual SaveStateBase& FreezeMainMemory();
|
|
|
|
virtual SaveStateBase& FreezeBios();
|
|
|
|
virtual SaveStateBase& FreezeInternals();
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2010-04-25 00:31:27 +00:00
|
|
|
// Loads or saves an arbitrary data type. Usable on atomic types, structs, and arrays.
|
2009-02-09 21:15:56 +00:00
|
|
|
// For dynamically allocated pointers use FreezeMem instead.
|
|
|
|
template<typename T>
|
|
|
|
void Freeze( T& data )
|
|
|
|
{
|
2009-09-19 09:45:26 +00:00
|
|
|
FreezeMem( const_cast<void*>((void*)&data), sizeof( T ) );
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FreezeLegacy can be used to load structures short of their full size, which is
|
|
|
|
// useful for loading structures that have had new stuff added since a previous version.
|
|
|
|
template<typename T>
|
|
|
|
void FreezeLegacy( T& data, int sizeOfNewStuff )
|
|
|
|
{
|
|
|
|
FreezeMem( &data, sizeof( T ) - sizeOfNewStuff );
|
|
|
|
}
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
void PrepBlock( int size );
|
|
|
|
|
2010-11-22 16:24:54 +00:00
|
|
|
uint GetCurrentPos() const
|
|
|
|
{
|
|
|
|
return m_idx;
|
|
|
|
}
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
u8* GetBlockPtr()
|
|
|
|
{
|
2010-04-27 13:12:03 +00:00
|
|
|
return m_memory->GetPtr(m_idx);
|
2009-09-16 17:23:02 +00:00
|
|
|
}
|
2010-11-22 16:24:54 +00:00
|
|
|
|
|
|
|
u8* GetPtrEnd() const
|
|
|
|
{
|
|
|
|
return m_memory->GetPtrEnd();
|
|
|
|
}
|
2009-09-16 17:23:02 +00:00
|
|
|
|
|
|
|
void CommitBlock( int size )
|
|
|
|
{
|
|
|
|
m_idx += size;
|
|
|
|
}
|
|
|
|
|
2009-03-19 04:16:24 +00:00
|
|
|
// Freezes an identifier value into the savestate for troubleshooting purposes.
|
|
|
|
// Identifiers can be used to determine where in a savestate that data has become
|
|
|
|
// skewed (if the value does not match then the error occurs somewhere prior to that
|
|
|
|
// position).
|
|
|
|
void FreezeTag( const char* src );
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
// Returns true if this object is a StateLoading type object.
|
|
|
|
bool IsLoading() const { return !IsSaving(); }
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
// Loads or saves a memory block.
|
|
|
|
virtual void FreezeMem( void* data, int size )=0;
|
|
|
|
|
|
|
|
// Returns true if this object is a StateSaving type object.
|
|
|
|
virtual bool IsSaving() const=0;
|
|
|
|
|
|
|
|
public:
|
2009-09-16 17:23:02 +00:00
|
|
|
// note: gsFreeze() needs to be public because of the GSState recorder.
|
|
|
|
void gsFreeze();
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
protected:
|
2010-04-28 16:25:04 +00:00
|
|
|
void Init( VmStateBuffer* memblock );
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
// Load/Save functions for the various components of our glorious emulator!
|
|
|
|
|
2011-08-12 02:31:49 +00:00
|
|
|
void mtvuFreeze();
|
2009-02-09 21:15:56 +00:00
|
|
|
void rcntFreeze();
|
|
|
|
void vuMicroFreeze();
|
|
|
|
void vif0Freeze();
|
|
|
|
void vif1Freeze();
|
|
|
|
void sifFreeze();
|
|
|
|
void ipuFreeze();
|
2011-07-24 13:02:50 +00:00
|
|
|
void ipuDmaFreeze();
|
2009-02-20 00:39:58 +00:00
|
|
|
void gifFreeze();
|
2011-07-24 13:02:50 +00:00
|
|
|
void gifDmaFreeze();
|
|
|
|
void gifPathFreeze(u32 path); // called by gifFreeze()
|
|
|
|
|
2009-03-04 13:00:32 +00:00
|
|
|
void sprFreeze();
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
void sioFreeze();
|
|
|
|
void cdrFreeze();
|
|
|
|
void cdvdFreeze();
|
|
|
|
void psxRcntFreeze();
|
|
|
|
void sio2Freeze();
|
|
|
|
|
2010-04-27 16:23:08 +00:00
|
|
|
void deci2Freeze();
|
2018-07-03 00:40:44 +00:00
|
|
|
|
2020-09-16 03:00:48 +00:00
|
|
|
// Save or load PCSX2's global frame counter (g_FrameCount) along with each savestate
|
|
|
|
//
|
|
|
|
// This is to prevent any inaccuracy issues caused by having a different
|
|
|
|
// internal emulation frame count than what it was at the beginning of the
|
|
|
|
// original recording
|
2018-07-03 00:40:44 +00:00
|
|
|
void InputRecordingFreeze();
|
2009-02-09 21:15:56 +00:00
|
|
|
};
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// Saving and Loading Specialized Implementations...
|
|
|
|
// --------------------------------------------------------------------------------------
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
class memSavingState : public SaveStateBase
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2009-10-09 17:28:17 +00:00
|
|
|
typedef SaveStateBase _parent;
|
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
protected:
|
2010-11-17 14:06:51 +00:00
|
|
|
static const int ReallocThreshold = _1mb / 4; // 256k reallocation block size.
|
|
|
|
static const int MemoryBaseAllocSize = _8mb; // 8 meg base alloc when PS2 main memory is excluded
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
public:
|
2017-05-06 13:28:33 +00:00
|
|
|
virtual ~memSavingState() = default;
|
2010-04-28 16:25:04 +00:00
|
|
|
memSavingState( VmStateBuffer& save_to );
|
|
|
|
memSavingState( VmStateBuffer* save_to );
|
2010-03-05 14:24:44 +00:00
|
|
|
|
2010-11-22 16:24:54 +00:00
|
|
|
void MakeRoomForData();
|
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
void FreezeMem( void* data, int size );
|
2009-10-09 17:28:17 +00:00
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
bool IsSaving() const { return true; }
|
|
|
|
};
|
|
|
|
|
2009-09-16 17:23:02 +00:00
|
|
|
class memLoadingState : public SaveStateBase
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
public:
|
2017-05-06 11:02:02 +00:00
|
|
|
virtual ~memLoadingState() = default;
|
2010-04-27 13:12:03 +00:00
|
|
|
|
2010-04-28 16:25:04 +00:00
|
|
|
memLoadingState( const VmStateBuffer& load_from );
|
|
|
|
memLoadingState( const VmStateBuffer* load_from );
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
void FreezeMem( void* data, int size );
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
bool IsSaving() const { return false; }
|
2010-04-27 13:12:03 +00:00
|
|
|
bool IsFinished() const { return m_idx >= m_memory->GetSizeInBytes(); }
|
2009-02-09 21:15:56 +00:00
|
|
|
};
|
|
|
|
|
2021-05-11 16:29:01 +00:00
|
|
|
|
|
|
|
namespace Exception
|
|
|
|
{
|
|
|
|
// Exception thrown when a corrupted or truncated savestate is encountered.
|
|
|
|
class SaveStateLoadError : public BadStream
|
|
|
|
{
|
|
|
|
DEFINE_STREAM_EXCEPTION(SaveStateLoadError, BadStream)
|
|
|
|
|
|
|
|
virtual wxString FormatDiagnosticMessage() const;
|
|
|
|
virtual wxString FormatDisplayMessage() const;
|
|
|
|
};
|
|
|
|
}; // namespace Exception
|
|
|
|
|