StateWrapper: Track save state version

This commit is contained in:
Connor McLaughlin 2020-10-12 20:46:59 +10:00
parent 893268bba5
commit 69b2c3fc2d
4 changed files with 26 additions and 8 deletions

View file

@ -5,7 +5,10 @@
#include <cstring>
Log_SetChannel(StateWrapper);
StateWrapper::StateWrapper(ByteStream* stream, Mode mode) : m_stream(stream), m_mode(mode) {}
StateWrapper::StateWrapper(ByteStream* stream, Mode mode, u32 version)
: m_stream(stream), m_mode(mode), m_version(version)
{
}
StateWrapper::~StateWrapper() = default;

View file

@ -20,7 +20,7 @@ public:
Write
};
StateWrapper(ByteStream* stream, Mode mode);
StateWrapper(ByteStream* stream, Mode mode, u32 version);
StateWrapper(const StateWrapper&) = delete;
~StateWrapper();
@ -30,6 +30,7 @@ public:
bool IsWriting() const { return (m_mode == Mode::Write); }
Mode GetMode() const { return m_mode; }
void SetMode(Mode mode) { m_mode = mode; }
u32 GetVersion() const { return m_version; }
/// Overload for integral or floating-point types. Writes bytes as-is.
template<typename T, std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, int> = 0>
@ -175,8 +176,21 @@ public:
bool DoMarker(const char* marker);
template<typename T>
void DoEx(T* data, u32 version_introduced, T default_value)
{
if (m_version < version_introduced)
{
*data = std::move(default_value);
return;
}
Do(data);
}
private:
ByteStream* m_stream;
Mode m_mode;
u32 m_version;
bool m_error = false;
};

View file

@ -3,6 +3,7 @@
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
static constexpr u32 SAVE_STATE_VERSION = 42;
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
#pragma pack(push, 4)
struct SAVE_STATE_HEADER

View file

@ -491,7 +491,7 @@ bool RecreateGPU(GPURenderer renderer)
// save current state
std::unique_ptr<ByteStream> state_stream = ByteStream_CreateGrowableMemoryStream();
StateWrapper sw(state_stream.get(), StateWrapper::Mode::Write);
StateWrapper sw(state_stream.get(), StateWrapper::Mode::Write, SAVE_STATE_VERSION);
const bool state_valid = g_gpu->DoState(sw) && TimingEvents::DoState(sw);
if (!state_valid)
Log_ErrorPrintf("Failed to save old GPU state when switching renderers");
@ -946,12 +946,12 @@ bool DoLoadState(ByteStream* state, bool force_software_renderer)
if (header.magic != SAVE_STATE_MAGIC)
return false;
if (header.version != SAVE_STATE_VERSION)
if (header.version < SAVE_STATE_MINIMUM_VERSION)
{
g_host_interface->ReportFormattedError(
g_host_interface->TranslateString("System",
"Save state is incompatible: expecting version %u but state is version %u."),
SAVE_STATE_VERSION, header.version);
"Save state is incompatible: minimum version is %u but state is version %u."),
SAVE_STATE_MINIMUM_VERSION, header.version);
return false;
}
@ -1041,7 +1041,7 @@ bool DoLoadState(ByteStream* state, bool force_software_renderer)
if (!state->SeekAbsolute(header.offset_to_data))
return false;
StateWrapper sw(state, StateWrapper::Mode::Read);
StateWrapper sw(state, StateWrapper::Mode::Read, header.version);
if (!DoState(sw))
return false;
@ -1108,7 +1108,7 @@ bool SaveState(ByteStream* state, u32 screenshot_size /* = 128 */)
g_gpu->RestoreGraphicsAPIState();
StateWrapper sw(state, StateWrapper::Mode::Write);
StateWrapper sw(state, StateWrapper::Mode::Write, SAVE_STATE_VERSION);
const bool result = DoState(sw);
g_gpu->ResetGraphicsAPIState();