diff --git a/pcsx2-qt/MainWindow.cpp b/pcsx2-qt/MainWindow.cpp index 9885320422..0a5303bc71 100644 --- a/pcsx2-qt/MainWindow.cpp +++ b/pcsx2-qt/MainWindow.cpp @@ -528,7 +528,7 @@ void MainWindow::recreate() new_main_window->activateWindow(); // Reload the sources we just closed. - g_emu_thread->reloadInputSources(); + g_emu_thread->applySettings(); if (was_display_created) { diff --git a/pcsx2-qt/QtHost.cpp b/pcsx2-qt/QtHost.cpp index ed0cce5aec..7eb0d05069 100644 --- a/pcsx2-qt/QtHost.cpp +++ b/pcsx2-qt/QtHost.cpp @@ -679,14 +679,7 @@ void EmuThread::reloadInputSources() return; } - std::unique_lock lock = Host::GetSettingsLock(); - SettingsInterface* si = Host::GetSettingsInterface(); - SettingsInterface* bindings_si = Host::GetSettingsInterfaceForBindings(); - InputManager::ReloadSources(*si, lock); - - // skip loading bindings if we're not running, since it'll get done on startup anyway - if (VMManager::HasValidVM()) - InputManager::ReloadBindings(*si, *bindings_si); + VMManager::ReloadInputSources(); } void EmuThread::reloadInputBindings() @@ -697,14 +690,7 @@ void EmuThread::reloadInputBindings() return; } - // skip loading bindings if we're not running, since it'll get done on startup anyway - if (!VMManager::HasValidVM()) - return; - - auto lock = Host::GetSettingsLock(); - SettingsInterface* si = Host::GetSettingsInterface(); - SettingsInterface* bindings_si = Host::GetSettingsInterfaceForBindings(); - InputManager::ReloadBindings(*si, *bindings_si); + VMManager::ReloadInputBindings(); } void EmuThread::reloadInputDevices() diff --git a/pcsx2/Host.cpp b/pcsx2/Host.cpp index 3a666370bf..2365794b81 100644 --- a/pcsx2/Host.cpp +++ b/pcsx2/Host.cpp @@ -172,12 +172,6 @@ SettingsInterface* Host::GetSettingsInterface() return &s_layered_settings_interface; } -SettingsInterface* Host::GetSettingsInterfaceForBindings() -{ - SettingsInterface* input_layer = s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_INPUT); - return input_layer ? input_layer : &s_layered_settings_interface; -} - std::string Host::GetBaseStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/) { std::unique_lock lock(s_settings_mutex); @@ -378,14 +372,12 @@ void Host::Internal::SetBaseSettingsLayer(SettingsInterface* sif) s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif); } -void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif) +void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock& settings_lock) { - std::unique_lock lock(s_settings_mutex); s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif); } -void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif) +void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif, std::unique_lock& settings_lock) { - std::unique_lock lock(s_settings_mutex); s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif); } diff --git a/pcsx2/Host.h b/pcsx2/Host.h index 20c70fbcf6..da7c87b28b 100644 --- a/pcsx2/Host.h +++ b/pcsx2/Host.h @@ -128,10 +128,6 @@ namespace Host std::unique_lock GetSettingsLock(); SettingsInterface* GetSettingsInterface(); - /// Returns the settings interface that controller bindings should be loaded from. - /// If an input profile is being used, this will be the input layer, otherwise the layered interface. - SettingsInterface* GetSettingsInterfaceForBindings(); - /// Sets host-specific default settings. void SetDefaultUISettings(SettingsInterface& si); @@ -150,10 +146,10 @@ namespace Host void SetBaseSettingsLayer(SettingsInterface* sif); /// Sets the game settings layer. Called by VMManager when the game changes. - void SetGameSettingsLayer(SettingsInterface* sif); + void SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock& settings_lock); /// Sets the input profile settings layer. Called by VMManager when the game changes. - void SetInputSettingsLayer(SettingsInterface* sif); + void SetInputSettingsLayer(SettingsInterface* sif, std::unique_lock& settings_lock); /// Implementation to retrieve a translated string. s32 GetTranslatedStringImpl(const std::string_view context, const std::string_view msg, char* tbuf, size_t tbuf_space); diff --git a/pcsx2/Input/InputManager.cpp b/pcsx2/Input/InputManager.cpp index f7f49530c0..17cf7cd132 100644 --- a/pcsx2/Input/InputManager.cpp +++ b/pcsx2/Input/InputManager.cpp @@ -1374,7 +1374,7 @@ bool InputManager::DoEventHook(InputBindingKey key, float value) // Binding Updater // ------------------------------------------------------------------------ -void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si) +void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si, SettingsInterface& hotkey_binding_si) { PauseVibration(); @@ -1386,8 +1386,7 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind s_pointer_move_callbacks.clear(); // Hotkeys use the base configuration, except if the custom hotkeys option is enabled. - const bool use_profile_hotkeys = si.GetBoolValue("Pad", "UseProfileHotkeyBindings", false); - AddHotkeyBindings(use_profile_hotkeys ? binding_si : si); + AddHotkeyBindings(hotkey_binding_si); // If there's an input profile, we load pad bindings from it alone, rather than // falling back to the base configuration. diff --git a/pcsx2/Input/InputManager.h b/pcsx2/Input/InputManager.h index ce7ace8d41..c4d6affabf 100644 --- a/pcsx2/Input/InputManager.h +++ b/pcsx2/Input/InputManager.h @@ -228,7 +228,7 @@ namespace InputManager bool IsInputSourceEnabled(SettingsInterface& si, InputSourceType type); /// Re-parses the config and registers all hotkey and pad bindings. - void ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si); + void ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si, SettingsInterface& hotkey_binding_si); /// Re-parses the sources part of the config and initializes any backends. void ReloadSources(SettingsInterface& si, std::unique_lock& settings_lock); diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 295491f009..1971e1760d 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -125,8 +125,9 @@ namespace VMManager s32 slot_for_message); static void LoadSettings(); - static void LoadCoreSettings(SettingsInterface* si); + static void LoadCoreSettings(SettingsInterface& si); static void ApplyCoreSettings(); + static void LoadInputBindings(SettingsInterface& si, std::unique_lock& lock); static void UpdateInhibitScreensaver(bool allow); static void AccumulateSessionPlaytime(); static void ResetResumeTimestamp(); @@ -578,11 +579,11 @@ void VMManager::LoadSettings() std::unique_lock lock = Host::GetSettingsLock(); SettingsInterface* si = Host::GetSettingsInterface(); - LoadCoreSettings(si); + LoadCoreSettings(*si); Pad::LoadConfig(*si); Host::LoadSettings(*si, lock); InputManager::ReloadSources(*si, lock); - InputManager::ReloadBindings(*si, *Host::GetSettingsInterfaceForBindings()); + LoadInputBindings(*si, lock); UpdateLoggingSettings(*si); if (HasValidOrInitializingVM()) @@ -592,9 +593,33 @@ void VMManager::LoadSettings() } } -void VMManager::LoadCoreSettings(SettingsInterface* si) +void VMManager::ReloadInputSources() { - SettingsLoadWrapper slw(*si); + FPControlRegisterBackup fpcr_backup(FPControlRegister::GetDefault()); + std::unique_lock lock = Host::GetSettingsLock(); + SettingsInterface* si = Host::GetSettingsInterface(); + InputManager::ReloadSources(*si, lock); + + // skip loading bindings if we're not running, since it'll get done on startup anyway + if (HasValidVM()) + LoadInputBindings(*si, lock); +} + +void VMManager::ReloadInputBindings() +{ + // skip loading bindings if we're not running, since it'll get done on startup anyway + if (!HasValidVM()) + return; + + FPControlRegisterBackup fpcr_backup(FPControlRegister::GetDefault()); + std::unique_lock lock = Host::GetSettingsLock(); + SettingsInterface* si = Host::GetSettingsInterface(); + LoadInputBindings(*si, lock); +} + +void VMManager::LoadCoreSettings(SettingsInterface& si) +{ + SettingsLoadWrapper slw(si); EmuConfig.LoadSave(slw); Patch::ApplyPatchSettingOverrides(); @@ -610,6 +635,35 @@ void VMManager::LoadCoreSettings(SettingsInterface* si) EmuConfig.Speedhacks.vuThread = false; } +void VMManager::LoadInputBindings(SettingsInterface& si, std::unique_lock& lock) +{ + // Hotkeys use the base configuration, except if the custom hotkeys option is enabled. + if (SettingsInterface* isi = Host::Internal::GetInputSettingsLayer()) + { + const bool use_profile_hotkeys = isi->GetBoolValue("Pad", "UseProfileHotkeyBindings", false); + if (use_profile_hotkeys) + { + InputManager::ReloadBindings(si, *isi, *isi); + } + else + { + // Temporarily disable the input profile layer, so it doesn't take precedence. + Host::Internal::SetInputSettingsLayer(nullptr, lock); + InputManager::ReloadBindings(si, *isi, si); + Host::Internal::SetInputSettingsLayer(s_input_settings_interface.get(), lock); + } + } + else if (SettingsInterface* gsi = Host::Internal::GetGameSettingsLayer(); + gsi && gsi->GetBoolValue("Pad", "UseGameSettingsForController", false)) + { + InputManager::ReloadBindings(si, *gsi, si); + } + else + { + InputManager::ReloadBindings(si, si, si); + } +} + void VMManager::ApplyGameFixes() { if (!HasBootedELF() && !GSDumpReplayer::IsReplayingDump()) @@ -678,7 +732,7 @@ void VMManager::ApplyCoreSettings() { FPControlRegisterBackup fpcr_backup(FPControlRegister::GetDefault()); std::unique_lock lock = Host::GetSettingsLock(); - LoadCoreSettings(Host::GetSettingsInterface()); + LoadCoreSettings(*Host::GetSettingsInterface()); WarnAboutUnsafeSettings(); ApplyGameFixes(); } @@ -879,53 +933,42 @@ bool VMManager::UpdateGameSettingsLayer() } std::string input_profile_name; - bool use_game_settings_for_controller = false; if (new_interface) { - new_interface->GetBoolValue("Pad", "UseGameSettingsForController", &use_game_settings_for_controller); - if (!use_game_settings_for_controller) + if (!new_interface->GetBoolValue("Pad", "UseGameSettingsForController", false)) new_interface->GetStringValue("EmuCore", "InputProfileName", &input_profile_name); } if (!s_game_settings_interface && !new_interface && s_input_profile_name == input_profile_name) return false; - Host::Internal::SetGameSettingsLayer(new_interface.get()); + auto lock = Host::GetSettingsLock(); + Host::Internal::SetGameSettingsLayer(new_interface.get(), lock); s_game_settings_interface = std::move(new_interface); std::unique_ptr input_interface; - if (!use_game_settings_for_controller) + if (!input_profile_name.empty()) { - if (!input_profile_name.empty()) + const std::string filename(GetInputProfilePath(input_profile_name)); + if (FileSystem::FileExists(filename.c_str())) { - const std::string filename(GetInputProfilePath(input_profile_name)); - if (FileSystem::FileExists(filename.c_str())) + Console.WriteLn("Loading input profile from '%s'...", filename.c_str()); + input_interface = std::make_unique(std::move(filename)); + if (!input_interface->Load()) { - Console.WriteLn("Loading input profile from '%s'...", filename.c_str()); - input_interface = std::make_unique(std::move(filename)); - if (!input_interface->Load()) - { - Console.Error("Failed to parse input profile ini '%s'", input_interface->GetFileName().c_str()); - input_interface.reset(); - input_profile_name = {}; - } - } - else - { - DevCon.WriteLn("No game settings found (tried '%s')", filename.c_str()); + Console.Error("Failed to parse input profile ini '%s'", input_interface->GetFileName().c_str()); + input_interface.reset(); input_profile_name = {}; } } - - Host::Internal::SetInputSettingsLayer( - input_interface ? input_interface.get() : Host::Internal::GetBaseSettingsLayer()); - } - else - { - // using game settings for bindings too - Host::Internal::SetInputSettingsLayer(s_game_settings_interface.get()); + else + { + DevCon.WriteLn("No game settings found (tried '%s')", filename.c_str()); + input_profile_name = {}; + } } + Host::Internal::SetInputSettingsLayer(input_interface.get(), lock); s_input_settings_interface = std::move(input_interface); s_input_profile_name = std::move(input_profile_name); return true; @@ -1725,7 +1768,7 @@ bool VMManager::DoLoadState(const char* filename) Error error; if (!SaveState_UnzipFromDisk(filename, &error)) { - Host::ReportErrorAsync(TRANSLATE_SV("VMManager","Failed to load save state"), error.GetDescription()); + Host::ReportErrorAsync(TRANSLATE_SV("VMManager", "Failed to load save state"), error.GetDescription()); return false; } @@ -2285,7 +2328,8 @@ inline void LogUserPowerPlan() " Power Profile = '{}'\n" " Power States (min/max)\n" " AC = {}% / {}%\n" - " Battery = {}% / {}%\n", friendlyName.c_str(), acMin, acMax, dcMin, dcMax); + " Battery = {}% / {}%\n", + friendlyName.c_str(), acMin, acMax, dcMin, dcMax); } #endif diff --git a/pcsx2/VMManager.h b/pcsx2/VMManager.h index eaa3383fce..8c9b29d7e2 100644 --- a/pcsx2/VMManager.h +++ b/pcsx2/VMManager.h @@ -110,6 +110,12 @@ namespace VMManager /// Reloads game patches. void ReloadPatches(bool reload_files, bool reload_enabled_list, bool verbose, bool verbose_if_changed); + /// Reloads input sources. + void ReloadInputSources(); + + /// Reloads input bindings. + void ReloadInputBindings(); + /// Returns the save state filename for the given game serial/crc. std::string GetSaveStateFileName(const char* game_serial, u32 game_crc, s32 slot);