Achievements: Ensure loading old states behave the same as new

This commit is contained in:
Stenzek 2025-01-13 13:13:14 +10:00
parent 8f39dbb464
commit 3621705933
No known key found for this signature in database
5 changed files with 21 additions and 18 deletions

View File

@ -1642,7 +1642,7 @@ void Achievements::HandleServerReconnectedEvent(const rc_client_event_t* event)
}); });
} }
void Achievements::ResetClient() void Achievements::Reset()
{ {
#ifdef ENABLE_RAINTEGRATION #ifdef ENABLE_RAINTEGRATION
if (IsUsingRAIntegration()) if (IsUsingRAIntegration())
@ -1750,11 +1750,13 @@ void Achievements::SetHardcoreMode(bool enabled, bool force_display_message)
bool Achievements::DoState(StateWrapper& sw) bool Achievements::DoState(StateWrapper& sw)
{ {
static constexpr u32 REQUIRED_VERSION = 56;
// if we're inactive, we still need to skip the data (if any) // if we're inactive, we still need to skip the data (if any)
if (!IsActive()) if (!IsActive())
{ {
u32 data_size = 0; u32 data_size = 0;
sw.Do(&data_size); sw.DoEx(&data_size, REQUIRED_VERSION, 0u);
if (data_size > 0) if (data_size > 0)
sw.SkipBytes(data_size); sw.SkipBytes(data_size);
@ -1780,8 +1782,11 @@ bool Achievements::DoState(StateWrapper& sw)
GPUThread::RunOnThread([]() { FullscreenUI::CloseLoadingScreen(); }); GPUThread::RunOnThread([]() { FullscreenUI::CloseLoadingScreen(); });
} }
// loading an old state without cheevos, so reset the runtime
Achievements::Reset();
u32 data_size = 0; u32 data_size = 0;
sw.Do(&data_size); sw.DoEx(&data_size, REQUIRED_VERSION, 0u);
if (data_size == 0) if (data_size == 0)
{ {
// reset runtime, no data (state might've been created without cheevos) // reset runtime, no data (state might've been created without cheevos)

View File

@ -41,7 +41,7 @@ bool Initialize();
void UpdateSettings(const Settings& old_config); void UpdateSettings(const Settings& old_config);
/// Resets the internal state of all achievement tracking. Call on system reset. /// Resets the internal state of all achievement tracking. Call on system reset.
void ResetClient(); void Reset();
/// Called when the system is being reset. If it returns false, the reset should be aborted. /// Called when the system is being reset. If it returns false, the reset should be aborted.
bool ConfirmSystemReset(); bool ConfirmSystemReset();

View File

@ -2457,19 +2457,8 @@ bool System::DoState(StateWrapper& sw, bool update_display)
UpdateOverclock(); UpdateOverclock();
} }
if (sw.GetVersion() >= 56) [[unlikely]] if (!sw.DoMarkerEx("Cheevos", 56) || !Achievements::DoState(sw))
{ return false;
if (!sw.DoMarker("Cheevos"))
return false;
if (!Achievements::DoState(sw))
return false;
}
else
{
// loading an old state without cheevos, so reset the runtime
Achievements::ResetClient();
}
if (sw.HasError()) if (sw.HasError())
return false; return false;
@ -2750,7 +2739,7 @@ void System::InternalReset()
MDEC::Reset(); MDEC::Reset();
SIO::Reset(); SIO::Reset();
PCDrv::Reset(); PCDrv::Reset();
Achievements::ResetClient(); Achievements::Reset();
s_state.frame_number = 1; s_state.frame_number = 1;
s_state.internal_frame_number = 0; s_state.internal_frame_number = 0;
} }

View File

@ -111,6 +111,14 @@ bool StateWrapper::DoMarker(const char* marker)
return false; return false;
} }
bool StateWrapper::DoMarkerEx(const char* marker, u32 version_introduced)
{
if (m_version < version_introduced)
return !HasError();
return DoMarker(marker);
}
std::span<u8> StateWrapper::GetDeferredBytes(size_t size) std::span<u8> StateWrapper::GetDeferredBytes(size_t size)
{ {
if ((m_error = (m_error || (m_pos + size) > m_size))) [[unlikely]] if ((m_error = (m_error || (m_pos + size) > m_size))) [[unlikely]]

View File

@ -180,6 +180,7 @@ public:
} }
bool DoMarker(const char* marker); bool DoMarker(const char* marker);
bool DoMarkerEx(const char* marker, u32 version_introduced);
template<typename T> template<typename T>
void DoEx(T* data, u32 version_introduced, T default_value) void DoEx(T* data, u32 version_introduced, T default_value)