mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-08 04:25:37 +00:00
System: Add taints to save states
This informs the user they are loading a save state that at some point had potentially-game-breaking options enabled, and a reset is necessary to clear them.
This commit is contained in:
parent
2aea06526c
commit
baa9065d2e
@ -237,6 +237,8 @@ static EnableCodeList s_enabled_patches;
|
|||||||
|
|
||||||
static ActiveCodeList s_frame_end_codes;
|
static ActiveCodeList s_frame_end_codes;
|
||||||
|
|
||||||
|
static u32 s_active_patch_count = 0;
|
||||||
|
static u32 s_active_cheat_count = 0;
|
||||||
static bool s_patches_enabled = false;
|
static bool s_patches_enabled = false;
|
||||||
static bool s_cheats_enabled = false;
|
static bool s_cheats_enabled = false;
|
||||||
static bool s_database_cheat_codes_enabled = false;
|
static bool s_database_cheat_codes_enabled = false;
|
||||||
@ -828,6 +830,8 @@ void Cheats::ReloadCheats(bool reload_files, bool reload_enabled_list, bool verb
|
|||||||
|
|
||||||
void Cheats::UnloadAll()
|
void Cheats::UnloadAll()
|
||||||
{
|
{
|
||||||
|
s_active_cheat_count = 0;
|
||||||
|
s_active_patch_count = 0;
|
||||||
s_frame_end_codes = ActiveCodeList();
|
s_frame_end_codes = ActiveCodeList();
|
||||||
s_enabled_patches = EnableCodeList();
|
s_enabled_patches = EnableCodeList();
|
||||||
s_enabled_cheats = EnableCodeList();
|
s_enabled_cheats = EnableCodeList();
|
||||||
@ -862,14 +866,15 @@ void Cheats::UpdateActiveCodes(bool reload_enabled_list, bool verbose, bool verb
|
|||||||
const size_t prev_count = s_frame_end_codes.size();
|
const size_t prev_count = s_frame_end_codes.size();
|
||||||
s_frame_end_codes.clear();
|
s_frame_end_codes.clear();
|
||||||
|
|
||||||
u32 patch_count = 0;
|
s_active_patch_count = 0;
|
||||||
u32 cheat_count = 0;
|
s_active_cheat_count = 0;
|
||||||
|
|
||||||
if (!g_settings.disable_all_enhancements)
|
if (!g_settings.disable_all_enhancements)
|
||||||
{
|
{
|
||||||
const bool hc_mode_active = Achievements::IsHardcoreModeActive();
|
const bool hc_mode_active = Achievements::IsHardcoreModeActive();
|
||||||
patch_count = EnableCheats(s_patch_codes, s_enabled_patches, "Patches", hc_mode_active);
|
s_active_patch_count = EnableCheats(s_patch_codes, s_enabled_patches, "Patches", hc_mode_active);
|
||||||
cheat_count = AreCheatsEnabled() ? EnableCheats(s_cheat_codes, s_enabled_cheats, "Cheats", hc_mode_active) : 0;
|
s_active_cheat_count =
|
||||||
|
AreCheatsEnabled() ? EnableCheats(s_cheat_codes, s_enabled_cheats, "Cheats", hc_mode_active) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display message on first boot when we load patches.
|
// Display message on first boot when we load patches.
|
||||||
@ -877,20 +882,23 @@ void Cheats::UpdateActiveCodes(bool reload_enabled_list, bool verbose, bool verb
|
|||||||
const size_t new_count = s_frame_end_codes.size();
|
const size_t new_count = s_frame_end_codes.size();
|
||||||
if (verbose || (verbose_if_changed && prev_count != new_count))
|
if (verbose || (verbose_if_changed && prev_count != new_count))
|
||||||
{
|
{
|
||||||
if (patch_count > 0)
|
if (s_active_patch_count > 0)
|
||||||
{
|
{
|
||||||
Host::AddIconOSDMessage("LoadPatches", ICON_FA_BAND_AID,
|
System::SetTaint(System::Taint::Patches);
|
||||||
TRANSLATE_PLURAL_STR("Cheats", "%n game patches are active.", "OSD Message", patch_count),
|
Host::AddIconOSDMessage(
|
||||||
|
"LoadPatches", ICON_FA_BAND_AID,
|
||||||
|
TRANSLATE_PLURAL_STR("Cheats", "%n game patches are active.", "OSD Message", s_active_patch_count),
|
||||||
Host::OSD_INFO_DURATION);
|
Host::OSD_INFO_DURATION);
|
||||||
}
|
}
|
||||||
if (cheat_count > 0)
|
if (s_active_cheat_count > 0)
|
||||||
{
|
{
|
||||||
Host::AddIconOSDMessage(
|
System::SetTaint(System::Taint::Cheats);
|
||||||
"LoadCheats", ICON_EMOJI_WARNING,
|
Host::AddIconOSDMessage("LoadCheats", ICON_EMOJI_WARNING,
|
||||||
TRANSLATE_PLURAL_STR("Cheats", "%n cheats are enabled. This may crash games.", "OSD Message", cheat_count),
|
TRANSLATE_PLURAL_STR("Cheats", "%n cheats are enabled. This may crash games.",
|
||||||
|
"OSD Message", s_active_cheat_count),
|
||||||
Host::OSD_WARNING_DURATION);
|
Host::OSD_WARNING_DURATION);
|
||||||
}
|
}
|
||||||
else if (patch_count == 0)
|
else if (s_active_patch_count == 0)
|
||||||
{
|
{
|
||||||
Host::RemoveKeyedOSDMessage("LoadPatches");
|
Host::RemoveKeyedOSDMessage("LoadPatches");
|
||||||
Host::AddIconOSDMessage("LoadCheats", ICON_FA_BAND_AID,
|
Host::AddIconOSDMessage("LoadCheats", ICON_FA_BAND_AID,
|
||||||
@ -936,6 +944,16 @@ bool Cheats::ApplyManualCode(const std::string_view name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Cheats::GetActivePatchCount()
|
||||||
|
{
|
||||||
|
return s_active_patch_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Cheats::GetActiveCheatCount()
|
||||||
|
{
|
||||||
|
return s_active_cheat_count;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// File Parsing
|
// File Parsing
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -143,6 +143,12 @@ extern bool EnumerateManualCodes(std::function<bool(const std::string& name)> ca
|
|||||||
/// Invokes/applies the specified manually-activated code.
|
/// Invokes/applies the specified manually-activated code.
|
||||||
extern bool ApplyManualCode(const std::string_view name);
|
extern bool ApplyManualCode(const std::string_view name);
|
||||||
|
|
||||||
|
/// Returns the number of active patches.
|
||||||
|
extern u32 GetActivePatchCount();
|
||||||
|
|
||||||
|
/// Returns the number of active cheats.
|
||||||
|
extern u32 GetActiveCheatCount();
|
||||||
|
|
||||||
// Config sections/keys to use to enable patches.
|
// Config sections/keys to use to enable patches.
|
||||||
extern const char* PATCHES_CONFIG_SECTION;
|
extern const char* PATCHES_CONFIG_SECTION;
|
||||||
extern const char* CHEATS_CONFIG_SECTION;
|
extern const char* CHEATS_CONFIG_SECTION;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||||
static constexpr u32 SAVE_STATE_VERSION = 74;
|
static constexpr u32 SAVE_STATE_VERSION = 75;
|
||||||
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
|
||||||
|
|
||||||
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);
|
||||||
|
@ -151,6 +151,8 @@ static bool ShouldStartPaused();
|
|||||||
|
|
||||||
/// Checks for settings changes, std::move() the old settings away for comparing beforehand.
|
/// Checks for settings changes, std::move() the old settings away for comparing beforehand.
|
||||||
static void CheckForSettingsChanges(const Settings& old_settings);
|
static void CheckForSettingsChanges(const Settings& old_settings);
|
||||||
|
static void SetTaintsFromSettings();
|
||||||
|
static void WarnAboutStateTaints(u32 state_taints);
|
||||||
static void WarnAboutUnsafeSettings();
|
static void WarnAboutUnsafeSettings();
|
||||||
static void LogUnsafeSettingsToConsole(const SmallStringBase& messages);
|
static void LogUnsafeSettingsToConsole(const SmallStringBase& messages);
|
||||||
|
|
||||||
@ -251,6 +253,7 @@ static u32 s_frame_number = 1;
|
|||||||
static u32 s_internal_frame_number = 1;
|
static u32 s_internal_frame_number = 1;
|
||||||
static const BIOS::ImageInfo* s_bios_image_info = nullptr;
|
static const BIOS::ImageInfo* s_bios_image_info = nullptr;
|
||||||
static BIOS::ImageInfo::Hash s_bios_hash = {};
|
static BIOS::ImageInfo::Hash s_bios_hash = {};
|
||||||
|
static u32 s_taints = 0;
|
||||||
|
|
||||||
static std::string s_running_game_path;
|
static std::string s_running_game_path;
|
||||||
static std::string s_running_game_serial;
|
static std::string s_running_game_serial;
|
||||||
@ -660,6 +663,49 @@ bool System::IsPALRegion()
|
|||||||
return s_region == ConsoleRegion::PAL;
|
return s_region == ConsoleRegion::PAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* System::GetTaintDisplayName(Taint taint)
|
||||||
|
{
|
||||||
|
static constexpr const std::array<const char*, static_cast<size_t>(Taint::MaxCount)> names = {{
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "CPU Overclock", "Taint"),
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "CD-ROM Read Speedup", "Taint"),
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "CD-ROM Seek Speedup", "Taint"),
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "Force Frame Timings", "Taint"),
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "8MB RAM", "Taint"),
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "Cheats", "Taint"),
|
||||||
|
TRANSLATE_DISAMBIG_NOOP("System", "Game Patches", "Taint"),
|
||||||
|
}};
|
||||||
|
|
||||||
|
return names[static_cast<size_t>(taint)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* System::GetTaintName(Taint taint)
|
||||||
|
{
|
||||||
|
static constexpr const std::array<const char*, static_cast<size_t>(Taint::MaxCount)> names = {{
|
||||||
|
"CPUOverclock",
|
||||||
|
"CDROMReadSpeedup",
|
||||||
|
"CDROMSeekSpeedup",
|
||||||
|
"ForceFrameTimings",
|
||||||
|
"RAM8MB",
|
||||||
|
"Cheats",
|
||||||
|
"Patches",
|
||||||
|
}};
|
||||||
|
|
||||||
|
return names[static_cast<size_t>(taint)];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool System::HasTaint(Taint taint)
|
||||||
|
{
|
||||||
|
return (s_taints & (1u << static_cast<u8>(taint))) != 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::SetTaint(Taint taint)
|
||||||
|
{
|
||||||
|
if (!HasTaint(taint))
|
||||||
|
WARNING_LOG("Setting system taint: {}", GetTaintName(taint));
|
||||||
|
|
||||||
|
s_taints |= (1u << static_cast<u8>(taint));
|
||||||
|
}
|
||||||
|
|
||||||
TickCount System::GetMaxSliceTicks()
|
TickCount System::GetMaxSliceTicks()
|
||||||
{
|
{
|
||||||
return s_max_slice_ticks;
|
return s_max_slice_ticks;
|
||||||
@ -2039,6 +2085,7 @@ void System::DestroySystem()
|
|||||||
Host::ReleaseGPUDevice();
|
Host::ReleaseGPUDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_taints = 0;
|
||||||
s_bios_hash = {};
|
s_bios_hash = {};
|
||||||
s_bios_image_info = nullptr;
|
s_bios_image_info = nullptr;
|
||||||
s_exe_override = {};
|
s_exe_override = {};
|
||||||
@ -2464,6 +2511,11 @@ bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
|
|||||||
sw.Do(&s_region);
|
sw.Do(&s_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 state_taints = s_taints;
|
||||||
|
sw.DoEx(&state_taints, 75, static_cast<u32>(0));
|
||||||
|
if (state_taints != s_taints) [[unlikely]]
|
||||||
|
WarnAboutStateTaints(state_taints);
|
||||||
|
|
||||||
sw.Do(&s_frame_number);
|
sw.Do(&s_frame_number);
|
||||||
sw.Do(&s_internal_frame_number);
|
sw.Do(&s_internal_frame_number);
|
||||||
|
|
||||||
@ -2600,6 +2652,9 @@ void System::InternalReset()
|
|||||||
if (IsShutdown())
|
if (IsShutdown())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// reset and clear taints
|
||||||
|
SetTaintsFromSettings();
|
||||||
|
|
||||||
TimingEvents::Reset();
|
TimingEvents::Reset();
|
||||||
CPU::Reset();
|
CPU::Reset();
|
||||||
CPU::CodeCache::Reset();
|
CPU::CodeCache::Reset();
|
||||||
@ -4580,6 +4635,54 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void System::SetTaintsFromSettings()
|
||||||
|
{
|
||||||
|
s_taints = 0;
|
||||||
|
|
||||||
|
if (g_settings.cdrom_read_speedup > 1)
|
||||||
|
SetTaint(Taint::CDROMReadSpeedup);
|
||||||
|
if (g_settings.cdrom_seek_speedup > 1)
|
||||||
|
SetTaint(Taint::CDROMSeekSpeedup);
|
||||||
|
if (g_settings.cpu_overclock_active)
|
||||||
|
SetTaint(Taint::CPUOverclock);
|
||||||
|
if (g_settings.gpu_force_video_timing != ForceVideoTimingMode::Disabled)
|
||||||
|
SetTaint(Taint::ForceFrameTimings);
|
||||||
|
if (g_settings.enable_8mb_ram)
|
||||||
|
SetTaint(Taint::RAM8MB);
|
||||||
|
if (Cheats::GetActivePatchCount() > 0)
|
||||||
|
SetTaint(Taint::Patches);
|
||||||
|
if (Cheats::GetActiveCheatCount() > 0)
|
||||||
|
SetTaint(Taint::Cheats);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::WarnAboutStateTaints(u32 state_taints)
|
||||||
|
{
|
||||||
|
const u32 taints_active_in_file = state_taints & ~s_taints;
|
||||||
|
if (taints_active_in_file == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LargeString messages;
|
||||||
|
for (u32 i = 0; i < static_cast<u32>(Taint::MaxCount); i++)
|
||||||
|
{
|
||||||
|
if (!(taints_active_in_file & (1u << i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (messages.empty())
|
||||||
|
{
|
||||||
|
messages.append_format(
|
||||||
|
"{} {}\n", ICON_EMOJI_WARNING,
|
||||||
|
TRANSLATE_SV("System", "This save state was created with the following tainted options, and may\n"
|
||||||
|
" be unstable. You will need to reset the system to clear any effects."));
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.append(" \u2022 ");
|
||||||
|
messages.append(GetTaintDisplayName(static_cast<Taint>(i)));
|
||||||
|
messages.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
Host::AddKeyedOSDWarning("SystemTaintsFromState", std::string(messages.view()), Host::OSD_WARNING_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
void System::WarnAboutUnsafeSettings()
|
void System::WarnAboutUnsafeSettings()
|
||||||
{
|
{
|
||||||
LargeString messages;
|
LargeString messages;
|
||||||
|
@ -104,6 +104,18 @@ enum class BootMode
|
|||||||
BootPSF,
|
BootPSF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Taint : u8
|
||||||
|
{
|
||||||
|
CPUOverclock,
|
||||||
|
CDROMReadSpeedup,
|
||||||
|
CDROMSeekSpeedup,
|
||||||
|
ForceFrameTimings,
|
||||||
|
RAM8MB,
|
||||||
|
Cheats,
|
||||||
|
Patches,
|
||||||
|
MaxCount,
|
||||||
|
};
|
||||||
|
|
||||||
extern TickCount g_ticks_per_second;
|
extern TickCount g_ticks_per_second;
|
||||||
|
|
||||||
/// Returns true if the filename is a PlayStation executable we can inject.
|
/// Returns true if the filename is a PlayStation executable we can inject.
|
||||||
@ -156,6 +168,12 @@ ConsoleRegion GetRegion();
|
|||||||
DiscRegion GetDiscRegion();
|
DiscRegion GetDiscRegion();
|
||||||
bool IsPALRegion();
|
bool IsPALRegion();
|
||||||
|
|
||||||
|
/// Taints - flags that are set on the system and only cleared on reset.
|
||||||
|
const char* GetTaintDisplayName(Taint taint);
|
||||||
|
const char* GetTaintName(Taint taint);
|
||||||
|
bool HasTaint(Taint taint);
|
||||||
|
void SetTaint(Taint taint);
|
||||||
|
|
||||||
ALWAYS_INLINE TickCount GetTicksPerSecond()
|
ALWAYS_INLINE TickCount GetTicksPerSecond()
|
||||||
{
|
{
|
||||||
return g_ticks_per_second;
|
return g_ticks_per_second;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user