From c06bee609363f5e9145ef065a4dfe25bb2152bee Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Tue, 17 Dec 2024 14:39:50 -0500 Subject: [PATCH] Savestates: Warn on savestate load and saves without mcd activity [SAVEVERSION+] --- pcsx2/SIO/Sio.cpp | 15 +++++++++++++++ pcsx2/SIO/Sio.h | 9 +++++++++ pcsx2/SIO/Sio2.cpp | 1 + pcsx2/SaveState.cpp | 5 +++-- pcsx2/SaveState.h | 2 +- pcsx2/VMManager.cpp | 2 ++ 6 files changed, 31 insertions(+), 3 deletions(-) diff --git a/pcsx2/SIO/Sio.cpp b/pcsx2/SIO/Sio.cpp index 7741ed14f09a6..9dd22932f8320 100644 --- a/pcsx2/SIO/Sio.cpp +++ b/pcsx2/SIO/Sio.cpp @@ -5,6 +5,7 @@ #include "SIO/SioTypes.h" #include "SIO/Memcard/MemoryCardProtocol.h" +#include "Counters.h" #include "Host.h" #include "IconsPromptFont.h" @@ -128,6 +129,8 @@ void AutoEject::ClearAll() // unsafe to shutdown the VM due to memcard access. static std::atomic_uint32_t currentBusyTicks = 0; +uint32_t sioLastFrameMcdBusy = 0; + void MemcardBusy::Decrement() { if (currentBusyTicks.load(std::memory_order_relaxed) == 0) @@ -139,6 +142,7 @@ void MemcardBusy::Decrement() void MemcardBusy::SetBusy() { currentBusyTicks.store(300, std::memory_order_release); + sioLastFrameMcdBusy = g_FrameCount; } bool MemcardBusy::IsBusy() @@ -149,4 +153,15 @@ bool MemcardBusy::IsBusy() void MemcardBusy::ClearBusy() { currentBusyTicks.store(0, std::memory_order_release); + sioLastFrameMcdBusy = 0; +} + +#include "common/Console.h" +void MemcardBusy::CheckSaveStateDependency() +{ + if (g_FrameCount - sioLastFrameMcdBusy > NUM_FRAMES_BEFORE_SAVESTATE_DEPENDENCY_WARNING) + { + Host::AddIconOSDMessage("MemcardBusy", ICON_PF_MEMORY_CARD, + TRANSLATE_SV("MemoryCard", "The virtual console hasn't saved to your memory card for quite some time. Savestates should not be used in place of in-game saves."), Host::OSD_INFO_DURATION); + } } diff --git a/pcsx2/SIO/Sio.h b/pcsx2/SIO/Sio.h index c0f3f4ad1ccfb..565761dda91fc 100644 --- a/pcsx2/SIO/Sio.h +++ b/pcsx2/SIO/Sio.h @@ -118,10 +118,19 @@ namespace AutoEject extern void ClearAll(); } // namespace AutoEject +// ~1 hour of memory card inactivity. +constexpr u32 NUM_FRAMES_BEFORE_SAVESTATE_DEPENDENCY_WARNING = 60 * 60 * 60; + +// Set to the current frame count when there is memory card activity. +// Used to detect the last frame when memory card activity was detected, +// and if it exceeds a certain threshold, warns on savestate save/load. +extern uint32_t sioLastFrameMcdBusy; + namespace MemcardBusy { extern void Decrement(); extern void SetBusy(); extern bool IsBusy(); extern void ClearBusy(); + extern void CheckSaveStateDependency(); } diff --git a/pcsx2/SIO/Sio2.cpp b/pcsx2/SIO/Sio2.cpp index d9d7543599601..3f6ad6aec93a9 100644 --- a/pcsx2/SIO/Sio2.cpp +++ b/pcsx2/SIO/Sio2.cpp @@ -541,5 +541,6 @@ bool Sio2::DoState(StateWrapper& sw) } } + sw.Do(&sioLastFrameMcdBusy); return sw.IsGood(); } diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index d5ff69ccf3fd7..1dcae02518a0b 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -15,12 +15,13 @@ #include "Host.h" #include "MTGS.h" #include "MTVU.h" -#include "SIO/Pad/Pad.h" #include "Patch.h" #include "R3000A.h" +#include "SIO/Multitap/MultitapProtocol.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Sio.h" #include "SIO/Sio0.h" #include "SIO/Sio2.h" -#include "SIO/Multitap/MultitapProtocol.h" #include "SPU2/spu2.h" #include "SaveState.h" #include "StateWrapper.h" diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 81c31fa35da8d..709468b709930 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -25,7 +25,7 @@ enum class FreezeAction // [SAVEVERSION+] // This informs the auto updater that the users savestates will be invalidated. -static const u32 g_SaveVersion = (0x9A51 << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A52 << 16) | 0x0000; // the freezing data between submodules and core diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 340bde8e42475..cb0321c50baad 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -1818,6 +1818,7 @@ bool VMManager::DoLoadState(const char* filename) MTGS::PresentCurrentFrame(); } + MemcardBusy::CheckSaveStateDependency(); return true; } @@ -1866,6 +1867,7 @@ bool VMManager::DoSaveState(const char* filename, s32 slot_for_message, bool zip } Host::OnSaveStateSaved(filename); + MemcardBusy::CheckSaveStateDependency(); return true; }