Patch: Re-run PPT_ONCE_ON_LOAD patches when enabling them as the game is running

This commit is contained in:
Silent 2025-01-06 14:56:09 +01:00 committed by Ty
parent 7ebcca36d2
commit 3b5b3ffa91
3 changed files with 46 additions and 12 deletions

View File

@ -156,7 +156,7 @@ namespace Patch
static bool PatchStringHasUnlabelledPatch(const std::string& pnach_data); static bool PatchStringHasUnlabelledPatch(const std::string& pnach_data);
static void ExtractPatchInfo(PatchInfoList* dst, const std::string& pnach_data, u32* num_unlabelled_patches); static void ExtractPatchInfo(PatchInfoList* dst, const std::string& pnach_data, u32* num_unlabelled_patches);
static void ReloadEnabledLists(); static void ReloadEnabledLists();
static u32 EnablePatches(const PatchList& patches, const EnablePatchList& enable_list); static u32 EnablePatches(const PatchList& patches, const EnablePatchList& enable_list, const EnablePatchList& enable_immediately_list);
static void ApplyPatch(const PatchCommand* p); static void ApplyPatch(const PatchCommand* p);
static void ApplyDynaPatch(const DynamicPatch& patch, u32 address); static void ApplyDynaPatch(const DynamicPatch& patch, u32 address);
@ -183,6 +183,8 @@ namespace Patch
static std::vector<DynamicPatch> s_active_pnach_dynamic_patches; static std::vector<DynamicPatch> s_active_pnach_dynamic_patches;
static EnablePatchList s_enabled_cheats; static EnablePatchList s_enabled_cheats;
static EnablePatchList s_enabled_patches; static EnablePatchList s_enabled_patches;
static EnablePatchList s_just_enabled_cheats;
static EnablePatchList s_just_enabled_patches;
static u32 s_patches_crc; static u32 s_patches_crc;
static std::optional<AspectRatioType> s_override_aspect_ratio; static std::optional<AspectRatioType> s_override_aspect_ratio;
static std::optional<GSInterlaceMode> s_override_interlace_mode; static std::optional<GSInterlaceMode> s_override_interlace_mode;
@ -583,13 +585,13 @@ std::string Patch::GetPnachFilename(const std::string_view serial, u32 crc, bool
void Patch::ReloadEnabledLists() void Patch::ReloadEnabledLists()
{ {
const EnablePatchList prev_enabled_cheats = std::move(s_enabled_cheats);
if (EmuConfig.EnableCheats && !Achievements::IsHardcoreModeActive()) if (EmuConfig.EnableCheats && !Achievements::IsHardcoreModeActive())
s_enabled_cheats = Host::GetStringListSetting(CHEATS_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY); s_enabled_cheats = Host::GetStringListSetting(CHEATS_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY);
else else
s_enabled_cheats = {}; s_enabled_cheats = {};
s_enabled_patches = Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY); const EnablePatchList prev_enabled_patches = std::exchange(s_enabled_patches, Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY));
const EnablePatchList disabled_patches = Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_DISABLE_CONFIG_KEY); const EnablePatchList disabled_patches = Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_DISABLE_CONFIG_KEY);
// Name based matching for widescreen/NI settings. // Name based matching for widescreen/NI settings.
@ -621,10 +623,29 @@ void Patch::ReloadEnabledLists()
++it; ++it;
} }
} }
s_just_enabled_cheats.clear();
s_just_enabled_patches.clear();
for (const auto& p : s_enabled_cheats)
{
if (std::find(prev_enabled_cheats.begin(), prev_enabled_cheats.end(), p) == prev_enabled_cheats.end())
{
s_just_enabled_cheats.emplace_back(p);
}
}
for (const auto& p : s_enabled_patches)
{
if (std::find(prev_enabled_patches.begin(), prev_enabled_patches.end(), p) == prev_enabled_patches.end())
{
s_just_enabled_patches.emplace_back(p);
}
}
} }
u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable_list) u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable_list, const EnablePatchList& enable_immediately_list)
{ {
ActivePatchList patches_to_apply_immediately;
u32 count = 0; u32 count = 0;
for (const PatchGroup& p : patches) for (const PatchGroup& p : patches)
{ {
@ -636,6 +657,7 @@ u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable
Console.WriteLn(Color_Green, fmt::format("Enabled patch: {}", Console.WriteLn(Color_Green, fmt::format("Enabled patch: {}",
p.name.empty() ? std::string_view("<unknown>") : std::string_view(p.name))); p.name.empty() ? std::string_view("<unknown>") : std::string_view(p.name)));
const bool apply_immediately = std::find(enable_immediately_list.begin(), enable_immediately_list.end(), p.name) != enable_immediately_list.end();
for (const PatchCommand& ip : p.patches) for (const PatchCommand& ip : p.patches)
{ {
// print the actual patch lines only in verbose mode (even in devel) // print the actual patch lines only in verbose mode (even in devel)
@ -643,6 +665,8 @@ u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable
DevCon.WriteLnFmt(" {}", ip.ToString()); DevCon.WriteLnFmt(" {}", ip.ToString());
s_active_patches.push_back(&ip); s_active_patches.push_back(&ip);
if (apply_immediately && ip.placetopatch == PPT_ONCE_ON_LOAD)
patches_to_apply_immediately.push_back(&ip);
} }
for (const DynamicPatch& dp : p.dpatches) for (const DynamicPatch& dp : p.dpatches)
@ -659,6 +683,16 @@ u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable
count += p.name.empty() ? (static_cast<u32>(p.patches.size()) + static_cast<u32>(p.dpatches.size())) : 1; count += p.name.empty() ? (static_cast<u32>(p.patches.size()) + static_cast<u32>(p.dpatches.size())) : 1;
} }
if (!patches_to_apply_immediately.empty())
{
Host::RunOnCPUThread([patches = std::move(patches_to_apply_immediately)]() {
for (const PatchCommand* i : patches)
{
ApplyPatch(i);
}
});
}
return count; return count;
} }
@ -703,10 +737,10 @@ void Patch::ReloadPatches(const std::string& serial, u32 crc, bool reload_files,
}); });
} }
UpdateActivePatches(reload_enabled_list, verbose, verbose_if_changed); UpdateActivePatches(reload_enabled_list, verbose, verbose_if_changed, false);
} }
void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed) void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed, bool apply_new_patches)
{ {
if (reload_enabled_list) if (reload_enabled_list)
ReloadEnabledLists(); ReloadEnabledLists();
@ -721,19 +755,19 @@ void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool ver
u32 gp_count = 0; u32 gp_count = 0;
if (EmuConfig.EnablePatches) if (EmuConfig.EnablePatches)
{ {
gp_count = EnablePatches(s_gamedb_patches, EnablePatchList()); gp_count = EnablePatches(s_gamedb_patches, EnablePatchList(), EnablePatchList());
if (gp_count > 0) if (gp_count > 0)
message.append(TRANSLATE_PLURAL_STR("Patch", "%n GameDB patches are active.", "OSD Message", gp_count)); message.append(TRANSLATE_PLURAL_STR("Patch", "%n GameDB patches are active.", "OSD Message", gp_count));
} }
const u32 p_count = EnablePatches(s_game_patches, s_enabled_patches); const u32 p_count = EnablePatches(s_game_patches, s_enabled_patches, apply_new_patches ? s_just_enabled_patches : EnablePatchList());
if (p_count > 0) if (p_count > 0)
{ {
message.append_format("{}{}", message.empty() ? "" : "\n", message.append_format("{}{}", message.empty() ? "" : "\n",
TRANSLATE_PLURAL_STR("Patch", "%n game patches are active.", "OSD Message", p_count)); TRANSLATE_PLURAL_STR("Patch", "%n game patches are active.", "OSD Message", p_count));
} }
const u32 c_count = EmuConfig.EnableCheats ? EnablePatches(s_cheat_patches, s_enabled_cheats) : 0; const u32 c_count = EmuConfig.EnableCheats ? EnablePatches(s_cheat_patches, s_enabled_cheats, apply_new_patches ? s_just_enabled_cheats : EnablePatchList()) : 0;
if (c_count > 0) if (c_count > 0)
{ {
message.append_format("{}{}", message.empty() ? "" : "\n", message.append_format("{}{}", message.empty() ? "" : "\n",

View File

@ -88,7 +88,7 @@ namespace Patch
/// Reloads cheats/patches. If verbose is set, the number of patches loaded will be shown in the OSD. /// Reloads cheats/patches. If verbose is set, the number of patches loaded will be shown in the OSD.
extern void ReloadPatches(const std::string& serial, u32 crc, bool reload_files, bool reload_enabled_list, bool verbose, bool verbose_if_changed); extern void ReloadPatches(const std::string& serial, u32 crc, bool reload_files, bool reload_enabled_list, bool verbose, bool verbose_if_changed);
extern void UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed); extern void UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed, bool apply_new_patches);
extern void ApplyPatchSettingOverrides(); extern void ApplyPatchSettingOverrides();
extern bool ReloadPatchAffectingOptions(); extern bool ReloadPatchAffectingOptions();
extern void UnloadPatches(); extern void UnloadPatches();

View File

@ -760,7 +760,7 @@ bool VMManager::ReloadGameSettings()
return false; return false;
// Patches must come first, because they can affect aspect ratio/interlacing. // Patches must come first, because they can affect aspect ratio/interlacing.
Patch::UpdateActivePatches(true, false, true); Patch::UpdateActivePatches(true, false, true, HasValidVM());
ApplySettings(); ApplySettings();
return true; return true;
} }
@ -2899,7 +2899,7 @@ void VMManager::CheckForPatchConfigChanges(const Pcsx2Config& old_config)
return; return;
} }
Patch::UpdateActivePatches(true, false, true); Patch::UpdateActivePatches(true, false, true, HasValidVM());
// This is a bit messy, because the patch config update happens after the settings are loaded, // This is a bit messy, because the patch config update happens after the settings are loaded,
// if we disable widescreen patches, we have to reload the original settings again. // if we disable widescreen patches, we have to reload the original settings again.