From ff23f87010ce1102883ea0d3a224307ff082ef26 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 24 Jun 2023 21:05:31 +1000 Subject: [PATCH] FullscreenUI: Add patches/cheats to game settings --- pcsx2/ImGui/FullscreenUI.cpp | 158 ++++++++++++++++++++++++++++++++--- pcsx2/Patch.cpp | 2 +- pcsx2/Patch.h | 2 +- 3 files changed, 150 insertions(+), 12 deletions(-) diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 3471a68d47..5eaf3be022 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -36,6 +36,7 @@ #include "USB/USB.h" #include "VMManager.h" #include "ps2/BiosTools.h" +#include "Patch.h" #include "svnrev.h" #include "common/FileSystem.h" @@ -175,6 +176,8 @@ namespace FullscreenUI Achievements, Folders, Advanced, + Patches, + Cheats, GameFixes, Count }; @@ -295,6 +298,7 @@ namespace FullscreenUI static void DrawFoldersSettingsPage(); static void DrawAchievementsLoginWindow(); static void DrawAdvancedSettingsPage(); + static void DrawPatchesOrCheatsSettingsPage(bool cheats); static void DrawGameFixesSettingsPage(); static bool IsEditingGameSettings(SettingsInterface* bsi); @@ -358,6 +362,7 @@ namespace FullscreenUI static void DrawClampingModeSetting(SettingsInterface* bsi, const char* title, const char* summary, int vunum); static void PopulateGraphicsAdapterList(); static void PopulateGameListDirectoryCache(SettingsInterface* si); + static void PopulatePatchesAndCheatsList(const std::string_view& serial, u32 crc); static void BeginInputBinding(SettingsInterface* bsi, InputBindingInfo::Type type, const std::string_view& section, const std::string_view& key, const std::string_view& display_name); static void DrawInputBindingWindow(); @@ -373,6 +378,11 @@ namespace FullscreenUI static std::vector> s_game_list_directories_cache; static std::vector s_graphics_adapter_list_cache; static std::vector s_fullscreen_mode_list_cache; + static Patch::PatchInfoList s_game_patch_list; + static std::vector s_enabled_game_patch_cache; + static Patch::PatchInfoList s_game_cheats_list; + static std::vector s_enabled_game_cheat_cache; + static u32 s_game_cheat_unlabelled_count = 0; static std::vector s_hotkey_list_cache; static std::atomic_bool s_settings_changed{false}; static std::atomic_bool s_game_settings_changed{false}; @@ -742,6 +752,11 @@ void FullscreenUI::Shutdown(bool clear_state) s_cover_image_map.clear(); s_game_list_sorted_entries = {}; s_game_list_directories_cache = {}; + s_game_cheat_unlabelled_count = 0; + s_enabled_game_cheat_cache = {}; + s_game_cheats_list = {}; + s_enabled_game_patch_cache = {}; + s_game_patch_list = {}; s_fullscreen_mode_list_cache = {}; s_graphics_adapter_list_cache = {}; s_current_game_title = {}; @@ -2317,6 +2332,10 @@ void FullscreenUI::SwitchToSettings() { s_game_settings_entry.reset(); s_game_settings_interface.reset(); + s_game_patch_list = {}; + s_enabled_game_patch_cache = {}; + s_game_cheats_list = {}; + s_enabled_game_cheat_cache = {}; PopulateGraphicsAdapterList(); s_current_main_window = MainWindowType::Settings; @@ -2328,6 +2347,7 @@ void FullscreenUI::SwitchToGameSettings(const std::string_view& serial, u32 crc) s_game_settings_entry.reset(); s_game_settings_interface = std::make_unique(VMManager::GetGameSettingsPath(serial, crc)); s_game_settings_interface->Load(); + PopulatePatchesAndCheatsList(serial, crc); s_current_main_window = MainWindowType::Settings; s_settings_page = SettingsPage::Summary; QueueResetFocus(); @@ -2375,6 +2395,25 @@ void FullscreenUI::PopulateGameListDirectoryCache(SettingsInterface* si) s_game_list_directories_cache.emplace_back(std::move(dir), true); } +void FullscreenUI::PopulatePatchesAndCheatsList(const std::string_view& serial, u32 crc) +{ + constexpr auto sort_patches = [](Patch::PatchInfoList& list) { + std::sort(list.begin(), list.end(), + [](const Patch::PatchInfo& lhs, const Patch::PatchInfo& rhs) { return lhs.name < rhs.name; }); + }; + + s_game_patch_list = Patch::GetPatchInfo(serial, crc, false, nullptr); + sort_patches(s_game_patch_list); + s_game_cheats_list = Patch::GetPatchInfo(serial, crc, true, &s_game_cheat_unlabelled_count); + sort_patches(s_game_cheats_list); + + pxAssert(s_game_settings_interface); + s_enabled_game_patch_cache = + s_game_settings_interface->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY); + s_enabled_game_cheat_cache = + s_game_settings_interface->GetStringList(Patch::CHEATS_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY); +} + void FullscreenUI::DoCopyGameSettings() { if (!s_game_settings_interface) @@ -2424,18 +2463,21 @@ void FullscreenUI::DrawSettingsWindow() { static constexpr float ITEM_WIDTH = 25.0f; - static constexpr const char* global_icons[] = {ICON_FA_WINDOW_MAXIMIZE, ICON_FA_MICROCHIP, ICON_FA_SLIDERS_H, ICON_FA_MAGIC, - ICON_FA_HEADPHONES, ICON_FA_SD_CARD, ICON_FA_GAMEPAD, ICON_FA_KEYBOARD, ICON_FA_TROPHY, ICON_FA_FOLDER_OPEN, ICON_FA_COGS}; - static constexpr const char* per_game_icons[] = { - ICON_FA_PARAGRAPH, ICON_FA_SLIDERS_H, ICON_FA_MAGIC, ICON_FA_HEADPHONES, ICON_FA_SD_CARD, ICON_FA_GAMEPAD, ICON_FA_BAN}; - static constexpr SettingsPage global_pages[] = {SettingsPage::Interface, SettingsPage::BIOS, SettingsPage::Emulation, - SettingsPage::Graphics, SettingsPage::Audio, SettingsPage::MemoryCard, SettingsPage::Controller, SettingsPage::Hotkey, - SettingsPage::Achievements, SettingsPage::Folders, SettingsPage::Advanced}; - static constexpr SettingsPage per_game_pages[] = {SettingsPage::Summary, SettingsPage::Emulation, SettingsPage::Graphics, - SettingsPage::Audio, SettingsPage::MemoryCard, SettingsPage::Controller, SettingsPage::GameFixes}; + static constexpr const char* global_icons[] = {ICON_FA_WINDOW_MAXIMIZE, ICON_FA_MICROCHIP, ICON_FA_SLIDERS_H, + ICON_FA_MAGIC, ICON_FA_HEADPHONES, ICON_FA_SD_CARD, ICON_FA_GAMEPAD, ICON_FA_KEYBOARD, ICON_FA_TROPHY, + ICON_FA_FOLDER_OPEN, ICON_FA_COGS}; + static constexpr const char* per_game_icons[] = {ICON_FA_PARAGRAPH, ICON_FA_SLIDERS_H, ICON_FA_MICROCHIP, + ICON_FA_FROWN, ICON_FA_MAGIC, ICON_FA_HEADPHONES, ICON_FA_SD_CARD, ICON_FA_GAMEPAD, ICON_FA_BAN}; + static constexpr SettingsPage global_pages[] = {SettingsPage::Interface, SettingsPage::BIOS, + SettingsPage::Emulation, SettingsPage::Graphics, SettingsPage::Audio, SettingsPage::MemoryCard, + SettingsPage::Controller, SettingsPage::Hotkey, SettingsPage::Achievements, SettingsPage::Folders, + SettingsPage::Advanced}; + static constexpr SettingsPage per_game_pages[] = {SettingsPage::Summary, SettingsPage::Emulation, + SettingsPage::Patches, SettingsPage::Cheats, SettingsPage::Graphics, SettingsPage::Audio, + SettingsPage::MemoryCard, SettingsPage::Controller, SettingsPage::GameFixes}; static constexpr const char* titles[] = {"Summary", "Interface Settings", "BIOS Settings", "Emulation Settings", "Graphics Settings", "Audio Settings", "Memory Card Settings", "Controller Settings", "Hotkey Settings", - "Achievements Settings", "Folder Settings", "Advanced Settings", "Game Fixes"}; + "Achievements Settings", "Folder Settings", "Advanced Settings", "Patches", "Cheats", "Game Fixes"}; SettingsInterface* bsi = GetEditingSettingsInterface(); const bool game_settings = IsEditingGameSettings(bsi); @@ -2552,6 +2594,14 @@ void FullscreenUI::DrawSettingsWindow() DrawFoldersSettingsPage(); break; + case SettingsPage::Patches: + DrawPatchesOrCheatsSettingsPage(false); + break; + + case SettingsPage::Cheats: + DrawPatchesOrCheatsSettingsPage(true); + break; + case SettingsPage::Advanced: DrawAdvancedSettingsPage(); break; @@ -4201,6 +4251,94 @@ void FullscreenUI::DrawAdvancedSettingsPage() EndMenuButtons(); } +void FullscreenUI::DrawPatchesOrCheatsSettingsPage(bool cheats) +{ + SettingsInterface* bsi = GetEditingSettingsInterface(); + + const Patch::PatchInfoList& patch_list = cheats ? s_game_cheats_list : s_game_patch_list; + std::vector& enable_list = cheats ? s_enabled_game_cheat_cache : s_enabled_game_patch_cache; + const char* section = cheats ? Patch::CHEATS_CONFIG_SECTION : Patch::PATCHES_CONFIG_SECTION; + const bool master_enable = cheats ? GetEffectiveBoolSetting(bsi, "EmuCore", "EnableCheats", false) : true; + + BeginMenuButtons(); + + if (cheats) + { + MenuHeading("Settings"); + DrawToggleSetting( + bsi, "Enable Cheats", "Enables loading cheats from pnach files.", "EmuCore", "EnableCheats", false); + + if (patch_list.empty()) + { + ActiveButton("No cheats are available for this game.", false, false, + ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + } + else + { + MenuHeading("Cheat Codes"); + } + } + else + { + if (patch_list.empty()) + { + ActiveButton("No patches are available for this game.", false, false, + ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + } + else + { + MenuHeading("Game Patches"); + } + } + + for (const Patch::PatchInfo& pi : patch_list) + { + const auto enable_it = std::find(enable_list.begin(), enable_list.end(), pi.name); + + bool state = (enable_it != enable_list.end()); + if (ToggleButton(pi.name.c_str(), pi.description.c_str(), &state, master_enable)) + { + if (state) + { + bsi->AddToStringList(section, Patch::PATCH_ENABLE_CONFIG_KEY, pi.name.c_str()); + enable_list.push_back(pi.name); + } + else + { + bsi->RemoveFromStringList(section, Patch::PATCH_ENABLE_CONFIG_KEY, pi.name.c_str()); + enable_list.erase(enable_it); + } + + SetSettingsChanged(bsi); + } + } + + if (cheats && s_game_cheat_unlabelled_count > 0) + { + ActiveButton( + master_enable ? + fmt::format("{} unlabelled patch codes will automatically activate.", s_game_cheat_unlabelled_count) + .c_str() : + fmt::format("{} unlabelled patch codes found but not enabled.", s_game_cheat_unlabelled_count).c_str(), + false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + } + + if (!patch_list.empty() || (cheats && s_game_cheat_unlabelled_count > 0)) + { + ActiveButton( + cheats ? + "Activating cheats can cause unpredictable behavior, crashing, soft-locks, or broken saved games." : + "Activating game patches can cause unpredictable behavior, crashing, soft-locks, or broken saved " + "games.", + false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + ActiveButton("Use patches at your own risk, the PCSX2 team will provide no support for users who have enabled " + "game patches.", + false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + } + + EndMenuButtons(); +} + void FullscreenUI::DrawGameFixesSettingsPage() { SettingsInterface* bsi = GetEditingSettingsInterface(); diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index ada7f82805..05d432e539 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -444,7 +444,7 @@ std::string_view Patch::PatchInfo::GetNameParentPart() const return ret; } -Patch::PatchInfoList Patch::GetPatchInfo(const std::string& serial, u32 crc, bool cheats, u32* num_unlabelled_patches) +Patch::PatchInfoList Patch::GetPatchInfo(const std::string_view& serial, u32 crc, bool cheats, u32* num_unlabelled_patches) { PatchInfoList ret; diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index 0da5614b95..a4512f1015 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -93,7 +93,7 @@ namespace Patch extern const char* CHEATS_CONFIG_SECTION; extern const char* PATCH_ENABLE_CONFIG_KEY; - extern PatchInfoList GetPatchInfo(const std::string& serial, u32 crc, bool cheats, u32* num_unlabelled_patches); + extern PatchInfoList GetPatchInfo(const std::string_view& serial, u32 crc, bool cheats, u32* num_unlabelled_patches); /// 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);