From 9e376f373e06e6a69b7675bb94e12f5a739db961 Mon Sep 17 00:00:00 2001 From: bicarus <202771338+bicarus-dev@users.noreply.github.com> Date: Tue, 20 Jan 2026 04:00:15 -0800 Subject: [PATCH] patcher: load auto-enable settings even if dest/spec/rev don't match (#527) ## Link to GitHub Issue, if one exists n/a ## Description of change Before this change, if user changes `dest`/`spec`/`rev`, then the "auto enable patches" settings doesn't get loaded. This is because the patch manager config file relies on having an exact match of `model+dest+spec+rev+ext`. This causes a lot of confusion for: * people who edit prop files - e.g., to switch between sdvx nemsys/valk cab modes - and forget to re-enable patches * people who use batch scripts to change xml files on launch - e.g., for gitadora, omnimix, etc - even if they checked auto-apply in spicecfg, when they use the batch script to launch the game, the setting won't be loaded This PR solves this by just ignoring the `dest`/`spec`/`rev` fields when checking if patches should be auto applied on launch. Yes, this may cause false positive cases, but probably very unlikely, and it's pretty harmless anyway. For future consideration: should we fix up gitadora XG disparity (K32 vs K33 etc)? ## Testing Manually validated --- src/spice2x/overlay/windows/patch_manager.cpp | 39 ++++++++++++++++--- src/spice2x/overlay/windows/patch_manager.h | 2 + 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/spice2x/overlay/windows/patch_manager.cpp b/src/spice2x/overlay/windows/patch_manager.cpp index 017d24b..e22247f 100644 --- a/src/spice2x/overlay/windows/patch_manager.cpp +++ b/src/spice2x/overlay/windows/patch_manager.cpp @@ -930,6 +930,13 @@ namespace overlay::windows { } } + // match on model and ext, ignoring dest/spec/rev + // sample: LDJ:J:E:A:2025011400 + bool PatchManager::is_game_id_wildcard_matched(const std::string& id_from_config) { + return ((id_from_config.compare(0, 3, avs::game::MODEL) == 0) && + (id_from_config.compare(10, 10, avs::game::EXT) == 0)); + } + void PatchManager::config_load() { log_info("patchmanager", "loading config"); @@ -955,7 +962,7 @@ namespace overlay::windows { if (auto_apply != doc.MemberEnd() && auto_apply->value.IsArray()) { // get game id - auto game_id = avs::game::get_identifier(); + const auto game_id = avs::game::get_identifier(); // iterate entries setting_auto_apply = false; @@ -964,15 +971,37 @@ namespace overlay::windows { if (entry.IsString()) { // check if this is our game identifier - std::string entry_id = entry.GetString(); - if (game_id == entry_id) { - setting_auto_apply = true; + const std::string entry_id = entry.GetString(); + + if (!setting_auto_apply) { + if (game_id == entry_id) { + // exact match + setting_auto_apply = true; + log_misc( + "patchmanager", + "matched auto apply entry by full game identifier: {}", + entry_id); + + } else if (is_game_id_wildcard_matched(entry_id)) { + // match on model and ext, ignoring dest/spec/rev + // sample: LDJ:J:E:A:2025011400 + setting_auto_apply = true; + log_misc( + "patchmanager", + "matched auto apply entry by partial game identifier: {}:?:?:?:{}", + avs::game::MODEL, avs::game::EXT); + } } // move to list setting_auto_apply_list.emplace_back(entry_id); } } + if (!setting_auto_apply) { + log_misc( + "patchmanager", + "no auto apply entry matched, patches will not load automatically"); + } } // read enabled patches @@ -1060,7 +1089,7 @@ namespace overlay::windows { auto game_id = avs::game::get_identifier(); bool game_id_added = false; for (auto &entry : setting_auto_apply_list) { - if (entry == game_id) { + if (entry == game_id || is_game_id_wildcard_matched(entry)) { if (!setting_auto_apply) { continue; } diff --git a/src/spice2x/overlay/windows/patch_manager.h b/src/spice2x/overlay/windows/patch_manager.h index 1c407ce..ec728e7 100644 --- a/src/spice2x/overlay/windows/patch_manager.h +++ b/src/spice2x/overlay/windows/patch_manager.h @@ -143,6 +143,8 @@ namespace overlay::windows { std::string pe_identifier_for_patch = ""); void show_patch_tooltip(const PatchData& patch); + + bool is_game_id_wildcard_matched(const std::string& id_from_config); }; PatchStatus is_patch_active(PatchData &patch);