From dc9c99438b4df11395d0e376ee4ac2aa61251400 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 23 Aug 2023 22:06:48 +1000 Subject: [PATCH] Misc: Post-refactor cleanups --- src/core/CMakeLists.txt | 6 +- src/core/achievements.cpp | 34 +- src/core/achievements.h | 177 ++++- src/core/achievements_private.h | 178 ----- src/core/analog_controller.cpp | 5 +- src/core/bios.cpp | 1 - src/core/common_host.h | 46 -- src/core/core.vcxproj | 6 +- src/core/core.vcxproj.filters | 6 +- src/core/fullscreen_ui.cpp | 10 +- src/core/game_list.cpp | 1 - src/core/gdb_protocol.cpp | 8 +- src/core/host.cpp | 309 ++++++++- src/core/host.h | 77 ++- src/core/host_settings.cpp | 192 ------ src/core/host_settings.h | 73 -- src/core/{common_host.cpp => hotkeys.cpp} | 623 +----------------- src/core/imgui_overlays.cpp | 99 ++- src/core/imgui_overlays.h | 3 +- src/core/settings.cpp | 46 +- src/core/settings.h | 8 + src/core/system.cpp | 309 ++++++++- src/core/system.h | 27 +- src/duckstation-nogui/cocoa_nogui_platform.mm | 4 - src/duckstation-nogui/nogui_host.cpp | 35 +- .../win32_nogui_platform.cpp | 1 - src/duckstation-qt/achievementlogindialog.cpp | 2 +- .../achievementsettingswidget.cpp | 2 +- src/duckstation-qt/audiosettingswidget.cpp | 1 - .../controllerbindingwidgets.cpp | 50 +- .../controllersettingsdialog.cpp | 13 +- .../controllersettingwidgetbinder.h | 15 +- src/duckstation-qt/gamelistwidget.cpp | 10 +- src/duckstation-qt/inputbindingwidgets.cpp | 11 +- src/duckstation-qt/mainwindow.cpp | 19 +- .../postprocessingchainconfigwidget.h | 2 +- src/duckstation-qt/qthost.cpp | 44 +- src/duckstation-qt/qthost.h | 4 +- src/duckstation-qt/settingsdialog.cpp | 3 +- src/duckstation-qt/settingwidgetbinder.h | 24 +- src/duckstation-regtest/regtest_host.cpp | 29 +- src/util/CMakeLists.txt | 1 - src/util/cocoa_tools.h | 16 +- src/util/cocoa_tools.mm | 15 - src/util/d3d11_device.cpp | 2 +- src/util/dinput_source.cpp | 7 +- src/util/gpu_device.cpp | 2 +- src/util/input_manager.cpp | 2 +- src/util/input_manager.h | 5 +- src/util/metal_device.mm | 1 - src/util/platform_misc.h | 18 +- src/util/platform_misc_mac.mm | 31 +- src/util/platform_misc_unix.cpp | 8 +- src/util/platform_misc_win32.cpp | 8 +- src/util/sdl_input_source.cpp | 10 +- 55 files changed, 1243 insertions(+), 1396 deletions(-) delete mode 100644 src/core/achievements_private.h delete mode 100644 src/core/common_host.h delete mode 100644 src/core/host_settings.cpp delete mode 100644 src/core/host_settings.h rename src/core/{common_host.cpp => hotkeys.cpp} (60%) delete mode 100644 src/util/cocoa_tools.mm diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cec43dc6f..63f1f9043 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -16,8 +16,6 @@ add_library(core cheats.h controller.cpp controller.h - common_host.cpp - common_host.h cpu_code_cache.cpp cpu_code_cache.h cpu_core.cpp @@ -62,8 +60,7 @@ add_library(core host.h host_interface_progress_callback.cpp host_interface_progress_callback.h - host_settings.cpp - host_settings.h + hotkeys.cpp input_types.h imgui_overlays.cpp imgui_overlays.h @@ -157,7 +154,6 @@ endif() if(ENABLE_CHEEVOS) target_sources(core PRIVATE achievements.cpp - achievements_private.h ) target_compile_definitions(core PUBLIC -DWITH_CHEEVOS=1) target_link_libraries(core PRIVATE rcheevos rapidjson) diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 25ffa0a47..b478561bc 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -1,13 +1,12 @@ // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) -#include "achievements_private.h" +#include "achievements.h" #include "bios.h" #include "bus.h" #include "cpu_core.h" #include "fullscreen_ui.h" #include "host.h" -#include "host_settings.h" #include "system.h" #include "scmversion/scmversion.h" @@ -682,8 +681,7 @@ void Achievements::FrameUpdate() #ifdef WITH_RAINTEGRATION if (IsUsingRAIntegration()) { - if (!System::IsPaused()) - RA_DoAchievementsFrame(); + RA_DoAchievementsFrame(); return; } #endif @@ -693,17 +691,8 @@ void Achievements::FrameUpdate() if (HasActiveGame()) { std::unique_lock lock(s_achievements_mutex); - if (!System::IsPaused()) - rc_runtime_do_frame(&s_rcheevos_runtime, &CheevosEventHandler, &PeekMemory, nullptr, nullptr); + rc_runtime_do_frame(&s_rcheevos_runtime, &CheevosEventHandler, &PeekMemory, nullptr, nullptr); UpdateRichPresence(); - - if (!IsTestModeActive()) - { - const s32 ping_frequency = - g_settings.achievements_rich_presence ? RICH_PRESENCE_PING_FREQUENCY : NO_RICH_PRESENCE_PING_FREQUENCY; - if (static_cast(s_last_ping_time.GetTimeSeconds()) >= ping_frequency) - SendPing(); - } } } @@ -714,7 +703,18 @@ void Achievements::ProcessPendingHTTPRequests() return; #endif + if (!s_http_downloader) + return; + s_http_downloader->PollRequests(); + + if (HasActiveGame() && !IsTestModeActive()) + { + const s32 ping_frequency = + g_settings.achievements_rich_presence ? RICH_PRESENCE_PING_FREQUENCY : NO_RICH_PRESENCE_PING_FREQUENCY; + if (static_cast(s_last_ping_time.GetTimeSeconds()) >= ping_frequency) + SendPing(); + } } bool Achievements::DoState(StateWrapper& sw) @@ -1029,7 +1029,7 @@ void Achievements::DisplayAchievementSummary() // Technically not going through the resource API, but since we're passing this to something else, we can't. if (g_settings.achievements_sound_effects) - FrontendCommon::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str()); + PlatformMisc::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str()); }); } @@ -1773,7 +1773,7 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, std::string conten // Technically not going through the resource API, but since we're passing this to something else, we can't. if (g_settings.achievements_sound_effects) - FrontendCommon::PlaySoundAsync(Path::Combine(EmuFolders::Resources, LBSUBMIT_SOUND_NAME).c_str()); + PlatformMisc::PlaySoundAsync(Path::Combine(EmuFolders::Resources, LBSUBMIT_SOUND_NAME).c_str()); } void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/) @@ -1818,7 +1818,7 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification / GetAchievementBadgePath(*achievement)); } if (g_settings.achievements_sound_effects) - FrontendCommon::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str()); + PlatformMisc::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str()); if (IsMastered()) DisplayMasteredNotification(); diff --git a/src/core/achievements.h b/src/core/achievements.h index 11574f042..91b162caf 100644 --- a/src/core/achievements.h +++ b/src/core/achievements.h @@ -1,10 +1,19 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once + +#include "settings.h" +#include "types.h" + +#include "common/string.h" #include "common/types.h" +#include +#include #include +#include +#include class StateWrapper; class CDImage; @@ -13,23 +22,157 @@ namespace Achievements { #ifdef WITH_CHEEVOS -// Implemented in Host. -extern bool ConfirmSystemReset(); -extern void ResetRuntime(); -extern bool DoState(StateWrapper& sw); -extern void GameChanged(const std::string& path, CDImage* image); +enum class AchievementCategory : u8 +{ + Local = 0, + Core = 3, + Unofficial = 5 +}; + +struct Achievement +{ + u32 id; + std::string title; + std::string description; + std::string memaddr; + std::string badge_name; + + // badge paths are mutable because they're resolved when they're needed. + mutable std::string locked_badge_path; + mutable std::string unlocked_badge_path; + + u32 points; + AchievementCategory category; + bool locked; + bool active; + bool primed; +}; + +struct Leaderboard +{ + u32 id; + std::string title; + std::string description; + int format; +}; + +struct LeaderboardEntry +{ + std::string user; + std::string formatted_score; + time_t submitted; + u32 rank; + bool is_self; +}; + +// RAIntegration only exists for Windows, so no point checking it on other platforms. +#ifdef WITH_RAINTEGRATION + +bool IsUsingRAIntegration(); + +#else + +static ALWAYS_INLINE bool IsUsingRAIntegration() +{ + return false; +} + +#endif + +bool IsActive(); +bool IsLoggedIn(); +bool ChallengeModeActive(); +bool LeaderboardsActive(); +bool IsTestModeActive(); +bool IsUnofficialTestModeActive(); +bool IsRichPresenceEnabled(); +bool HasActiveGame(); + +u32 GetGameID(); + +/// Acquires the achievements lock. Must be held when accessing any achievement state from another thread. +std::unique_lock GetLock(); + +void Initialize(); +void UpdateSettings(const Settings& old_config); +void ResetRuntime(); + +/// Called when the system is being reset. If it returns false, the reset should be aborted. +bool ConfirmSystemReset(); + +/// Called when the system is being shut down. If Shutdown() returns false, the shutdown should be aborted. +bool Shutdown(); + +/// Called when the system is being paused and resumed. +void OnSystemPaused(bool paused); + +/// Called once a frame at vsync time on the CPU thread. +void FrameUpdate(); + +/// Called when the system is paused, because FrameUpdate() won't be getting called. +void ProcessPendingHTTPRequests(); + +/// Saves/loads state. +bool DoState(StateWrapper& sw); + +/// Returns true if the current game has any achievements or leaderboards. +/// Does not need to have the lock held. +bool SafeHasAchievementsOrLeaderboards(); + +const std::string& GetUsername(); +const std::string& GetRichPresenceString(); + +bool LoginAsync(const char* username, const char* password); +bool Login(const char* username, const char* password); +void Logout(); + +void GameChanged(const std::string& path, CDImage* image); /// Re-enables hardcode mode if it is enabled in the settings. -extern bool ResetChallengeMode(); +bool ResetChallengeMode(); /// Forces hardcore mode off until next reset. -extern void DisableChallengeMode(); +void DisableChallengeMode(); /// Prompts the user to disable hardcore mode, if they agree, returns true. -extern bool ConfirmChallengeModeDisable(const char* trigger); +bool ConfirmChallengeModeDisable(const char* trigger); /// Returns true if features such as save states should be disabled. -extern bool ChallengeModeActive(); +bool ChallengeModeActive(); + +const std::string& GetGameTitle(); +const std::string& GetGameIcon(); + +bool EnumerateAchievements(std::function callback); +u32 GetUnlockedAchiementCount(); +u32 GetAchievementCount(); +u32 GetMaximumPointsForGame(); +u32 GetCurrentPointsForGame(); + +bool EnumerateLeaderboards(std::function callback); +std::optional TryEnumerateLeaderboardEntries(u32 id, std::function callback); +const Leaderboard* GetLeaderboardByID(u32 id); +u32 GetLeaderboardCount(); +bool IsLeaderboardTimeType(const Leaderboard& leaderboard); +u32 GetPrimedAchievementCount(); + +const Achievement* GetAchievementByID(u32 id); +std::pair GetAchievementProgress(const Achievement& achievement); +TinyString GetAchievementProgressText(const Achievement& achievement); +const std::string& GetAchievementBadgePath(const Achievement& achievement, bool download_if_missing = true, + bool force_unlocked_icon = false); +std::string GetAchievementBadgeURL(const Achievement& achievement); + +#ifdef WITH_RAINTEGRATION +void SwitchToRAIntegration(); + +namespace RAIntegration { +void MainWindowChanged(void* new_handle); +void GameChanged(); +std::vector> GetMenuItems(); +void ActivateMenuItem(int item); +} // namespace RAIntegration +#endif #else @@ -38,7 +181,9 @@ static inline bool ConfirmSystemReset() { return true; } -static inline void ResetRuntime() {} +static inline void ResetRuntime() +{ +} static inline bool DoState(StateWrapper& sw) { return true; @@ -53,7 +198,9 @@ static inline bool ResetChallengeMode() return false; } -static inline void DisableChallengeMode() {} +static inline void DisableChallengeMode() +{ +} static inline bool ConfirmChallengeModeDisable(const char* trigger) { @@ -63,3 +210,9 @@ static inline bool ConfirmChallengeModeDisable(const char* trigger) #endif } // namespace Achievements + +/// Functions implemented in the frontend. +namespace Host { +void OnAchievementsRefreshed(); +void OnAchievementsChallengeModeChanged(); +} // namespace Host diff --git a/src/core/achievements_private.h b/src/core/achievements_private.h deleted file mode 100644 index 171b347d6..000000000 --- a/src/core/achievements_private.h +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#pragma once - -#include "achievements.h" -#include "settings.h" -#include "types.h" - -#include "common/string.h" - -#include -#include -#include -#include -#include - -class CDImage; -class StateWrapper; - -namespace Achievements { -enum class AchievementCategory : u8 -{ - Local = 0, - Core = 3, - Unofficial = 5 -}; - -struct Achievement -{ - u32 id; - std::string title; - std::string description; - std::string memaddr; - std::string badge_name; - - // badge paths are mutable because they're resolved when they're needed. - mutable std::string locked_badge_path; - mutable std::string unlocked_badge_path; - - u32 points; - AchievementCategory category; - bool locked; - bool active; - bool primed; -}; - -struct Leaderboard -{ - u32 id; - std::string title; - std::string description; - int format; -}; - -struct LeaderboardEntry -{ - std::string user; - std::string formatted_score; - time_t submitted; - u32 rank; - bool is_self; -}; - -// RAIntegration only exists for Windows, so no point checking it on other platforms. -#ifdef WITH_RAINTEGRATION - -bool IsUsingRAIntegration(); - -#else - -static ALWAYS_INLINE bool IsUsingRAIntegration() -{ - return false; -} - -#endif - -bool IsActive(); -bool IsLoggedIn(); -bool ChallengeModeActive(); -bool LeaderboardsActive(); -bool IsTestModeActive(); -bool IsUnofficialTestModeActive(); -bool IsRichPresenceEnabled(); -bool HasActiveGame(); - -u32 GetGameID(); - -/// Acquires the achievements lock. Must be held when accessing any achievement state from another thread. -std::unique_lock GetLock(); - -void Initialize(); -void UpdateSettings(const Settings& old_config); - -/// Called when the system is being reset. If it returns false, the reset should be aborted. -bool ConfirmSystemReset(); - -/// Called when the system is being shut down. If Shutdown() returns false, the shutdown should be aborted. -bool Shutdown(); - -/// Called when the system is being paused and resumed. -void OnSystemPaused(bool paused); - -/// Called once a frame at vsync time on the CPU thread. -void FrameUpdate(); - -/// Called when the system is paused, because FrameUpdate() won't be getting called. -void ProcessPendingHTTPRequests(); - -/// Saves/loads state. -bool DoState(StateWrapper& sw); - -/// Returns true if the current game has any achievements or leaderboards. -/// Does not need to have the lock held. -bool SafeHasAchievementsOrLeaderboards(); - -const std::string& GetUsername(); -const std::string& GetRichPresenceString(); - -bool LoginAsync(const char* username, const char* password); -bool Login(const char* username, const char* password); -void Logout(); - -void GameChanged(const std::string& path, CDImage* image); - -/// Re-enables hardcode mode if it is enabled in the settings. -bool ResetChallengeMode(); - -/// Forces hardcore mode off until next reset. -void DisableChallengeMode(); - -/// Prompts the user to disable hardcore mode, if they agree, returns true. -bool ConfirmChallengeModeDisable(const char* trigger); - -/// Returns true if features such as save states should be disabled. -bool ChallengeModeActive(); - -const std::string& GetGameTitle(); -const std::string& GetGameIcon(); - -bool EnumerateAchievements(std::function callback); -u32 GetUnlockedAchiementCount(); -u32 GetAchievementCount(); -u32 GetMaximumPointsForGame(); -u32 GetCurrentPointsForGame(); - -bool EnumerateLeaderboards(std::function callback); -std::optional TryEnumerateLeaderboardEntries(u32 id, std::function callback); -const Leaderboard* GetLeaderboardByID(u32 id); -u32 GetLeaderboardCount(); -bool IsLeaderboardTimeType(const Leaderboard& leaderboard); -u32 GetPrimedAchievementCount(); - -const Achievement* GetAchievementByID(u32 id); -std::pair GetAchievementProgress(const Achievement& achievement); -TinyString GetAchievementProgressText(const Achievement& achievement); -const std::string& GetAchievementBadgePath(const Achievement& achievement, bool download_if_missing = true, - bool force_unlocked_icon = false); -std::string GetAchievementBadgeURL(const Achievement& achievement); - -#ifdef WITH_RAINTEGRATION -void SwitchToRAIntegration(); - -namespace RAIntegration { -void MainWindowChanged(void* new_handle); -void GameChanged(); -std::vector> GetMenuItems(); -void ActivateMenuItem(int item); -} // namespace RAIntegration -#endif -} // namespace Achievements - -/// Functions implemented in the frontend. -namespace Host { -void OnAchievementsRefreshed(); -void OnAchievementsChallengeModeChanged(); -} // namespace Host diff --git a/src/core/analog_controller.cpp b/src/core/analog_controller.cpp index f34f14a2a..eb4591928 100644 --- a/src/core/analog_controller.cpp +++ b/src/core/analog_controller.cpp @@ -8,6 +8,7 @@ #include "host.h" #include "settings.h" #include "system.h" +#include "util/input_manager.h" #include "util/state_wrapper.h" #include Log_SetChannel(AnalogController); @@ -348,7 +349,7 @@ void AnalogController::UpdateHostVibration() hvalues[motor] = (state != 0) ? static_cast(strength / 65535.0) : 0.0f; } - Host::SetPadVibrationIntensity(m_index, hvalues[0], hvalues[1]); + InputManager::SetPadVibrationIntensity(m_index, hvalues[0], hvalues[1]); } u8 AnalogController::GetExtraButtonMaskLSB() const @@ -820,7 +821,7 @@ static const Controller::ControllerBindingInfo s_binding_info[] = { AXIS("RRight", TRANSLATE_NOOP("AnalogController", "Right Stick Right"), AnalogController::HalfAxis::RRight, GenericInputBinding::RightStickRight), AXIS("RDown", TRANSLATE_NOOP("AnalogController", "Right Stick Down"), AnalogController::HalfAxis::RDown, GenericInputBinding::RightStickDown), AXIS("RUp", TRANSLATE_NOOP("AnalogController", "Right Stick Up"), AnalogController::HalfAxis::RUp, GenericInputBinding::RightStickUp), - // clang-format on +// clang-format on #undef AXIS #undef BUTTON diff --git a/src/core/bios.cpp b/src/core/bios.cpp index 9d70cd942..23d5616b1 100644 --- a/src/core/bios.cpp +++ b/src/core/bios.cpp @@ -9,7 +9,6 @@ #include "common/path.h" #include "cpu_disasm.h" #include "host.h" -#include "host_settings.h" #include "settings.h" #include Log_SetChannel(BIOS); diff --git a/src/core/common_host.h b/src/core/common_host.h deleted file mode 100644 index c6efb1e27..000000000 --- a/src/core/common_host.h +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#pragma once - -#include "system.h" - -#include -#include -#include -#include -#include - -class SettingsInterface; - -class AudioStream; -enum class AudioStretchMode : u8; - -namespace CommonHost { -/// Initializes configuration. -void UpdateLogSettings(); - -void Initialize(); -void Shutdown(); - -void SetDefaultSettings(SettingsInterface& si); -void SetDefaultControllerSettings(SettingsInterface& si); -void SetDefaultHotkeyBindings(SettingsInterface& si); -void LoadSettings(SettingsInterface& si, std::unique_lock& lock); -void CheckForSettingsChanges(const Settings& old_settings); -void OnSystemStarting(); -void OnSystemStarted(); -void OnSystemDestroyed(); -void OnSystemPaused(); -void OnSystemResumed(); -void OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name); -void PumpMessagesOnCPUThread(); - -/// Returns the time elapsed in the current play session. -u64 GetSessionPlayedTime(); - -} // namespace CommonHost - -namespace ImGuiManager { -void RenderDebugWindows(); -} diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 74a2b4d7e..a41b44cb0 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -10,7 +10,6 @@ - @@ -49,7 +48,7 @@ - + @@ -74,7 +73,6 @@ - @@ -83,7 +81,6 @@ - @@ -118,7 +115,6 @@ - diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 854d98dea..6aecabbdc 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -54,11 +54,10 @@ - - + @@ -113,7 +112,6 @@ - @@ -121,8 +119,6 @@ - - \ No newline at end of file diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index e505c1af0..d30c45c42 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -7,14 +7,12 @@ #include "achievements.h" #include "bios.h" #include "cheats.h" -#include "common_host.h" #include "controller.h" #include "core/memory_card_image.h" #include "cpu_core.h" #include "game_list.h" #include "gpu.h" #include "host.h" -#include "host_settings.h" #include "resources.h" #include "settings.h" #include "system.h" @@ -53,10 +51,6 @@ Log_SetChannel(FullscreenUI); -#ifdef WITH_CHEEVOS -#include "achievements_private.h" -#endif - #define TR_CONTEXT "FullscreenUI" namespace { @@ -3170,7 +3164,7 @@ void FullscreenUI::ResetControllerSettings() { SettingsInterface* dsi = GetEditingSettingsInterface(); - CommonHost::SetDefaultControllerSettings(*dsi); + Settings::SetDefaultControllerConfig(*dsi); ShowToast(std::string(), FSUI_STR("Controller settings reset to default.")); } @@ -4831,7 +4825,7 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type) if (!serial.empty()) { const std::time_t cached_played_time = GameList::GetCachedPlayedTimeForSerial(serial); - const std::time_t session_time = static_cast(CommonHost::GetSessionPlayedTime()); + const std::time_t session_time = static_cast(System::GetSessionPlayedTime()); buffer.Fmt(FSUI_FSTR("Session: {}"), GameList::FormatTimespan(session_time, true).GetStringView()); const ImVec2 session_size(g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits::max(), diff --git a/src/core/game_list.cpp b/src/core/game_list.cpp index 79f0818e8..cd55dbf73 100644 --- a/src/core/game_list.cpp +++ b/src/core/game_list.cpp @@ -4,7 +4,6 @@ #include "game_list.h" #include "bios.h" #include "host.h" -#include "host_settings.h" #include "psf_loader.h" #include "settings.h" #include "system.h" diff --git a/src/core/gdb_protocol.cpp b/src/core/gdb_protocol.cpp index bdc5a78ed..bb5a0b909 100644 --- a/src/core/gdb_protocol.cpp +++ b/src/core/gdb_protocol.cpp @@ -4,17 +4,19 @@ #include "gdb_protocol.h" #include "bus.h" #include "cpu_core_private.h" +#include "cpu_core.h" +#include "system.h" + #include "common/log.h" #include "common/string_util.h" -#include "cpu_core.h" -#include "common_host.h" -#include "system.h" + #include #include #include #include #include #include + Log_SetChannel(GDBProtocol); namespace GDBProtocol diff --git a/src/core/host.cpp b/src/core/host.cpp index cb50f2ccd..ecf4508e6 100644 --- a/src/core/host.cpp +++ b/src/core/host.cpp @@ -2,15 +2,17 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "host.h" -#include "common_host.h" #include "fullscreen_ui.h" #include "imgui_overlays.h" +#include "shader_cache_version.h" +#include "system.h" #include "util/gpu_device.h" #include "util/imgui_manager.h" #include "common/assert.h" #include "common/heterogeneous_containers.h" +#include "common/layered_settings_interface.h" #include "common/log.h" #include "common/string_util.h" @@ -23,6 +25,9 @@ namespace Host { static std::pair LookupTranslationString(const std::string_view& context, const std::string_view& msg); +static std::mutex s_settings_mutex; +static LayeredSettingsInterface s_layered_settings_interface; + static constexpr u32 TRANSLATION_STRING_CACHE_SIZE = 4 * 1024 * 1024; using TranslationStringMap = UnorderedStringMap>; using TranslationStringContextMap = UnorderedStringMap; @@ -32,6 +37,196 @@ static std::vector s_translation_string_cache; static u32 s_translation_string_cache_pos; } // namespace Host +std::unique_lock Host::GetSettingsLock() +{ + return std::unique_lock(s_settings_mutex); +} + +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); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->GetStringValue(section, key, default_value); +} + +bool Host::GetBaseBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->GetBoolValue(section, key, default_value); +} + +s32 Host::GetBaseIntSettingValue(const char* section, const char* key, s32 default_value /*= 0*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->GetIntValue(section, key, default_value); +} + +u32 Host::GetBaseUIntSettingValue(const char* section, const char* key, u32 default_value /*= 0*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->GetUIntValue(section, key, default_value); +} + +float Host::GetBaseFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->GetFloatValue(section, key, default_value); +} + +double Host::GetBaseDoubleSettingValue(const char* section, const char* key, double default_value /* = 0.0f */) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->GetDoubleValue(section, key, default_value); +} + +std::vector Host::GetBaseStringListSetting(const char* section, const char* key) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetStringList(section, key); +} + +std::string Host::GetStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetStringValue(section, key, default_value); +} + +bool Host::GetBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetBoolValue(section, key, default_value); +} + +s32 Host::GetIntSettingValue(const char* section, const char* key, s32 default_value /*= 0*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetIntValue(section, key, default_value); +} + +u32 Host::GetUIntSettingValue(const char* section, const char* key, u32 default_value /*= 0*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetUIntValue(section, key, default_value); +} + +float Host::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetFloatValue(section, key, default_value); +} + +double Host::GetDoubleSettingValue(const char* section, const char* key, double default_value /*= 0.0f*/) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetDoubleValue(section, key, default_value); +} + +std::vector Host::GetStringListSetting(const char* section, const char* key) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetStringList(section, key); +} + +void Host::SetBaseBoolSettingValue(const char* section, const char* key, bool value) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetBoolValue(section, key, value); +} + +void Host::SetBaseIntSettingValue(const char* section, const char* key, int value) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetIntValue(section, key, value); +} + +void Host::SetBaseFloatSettingValue(const char* section, const char* key, float value) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetFloatValue(section, key, value); +} + +void Host::SetBaseStringSettingValue(const char* section, const char* key, const char* value) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringValue(section, key, value); +} + +void Host::SetBaseStringListSettingValue(const char* section, const char* key, const std::vector& values) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringList(section, key, values); +} + +bool Host::AddValueToBaseStringListSetting(const char* section, const char* key, const char* value) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->AddToStringList(section, key, value); +} + +bool Host::RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value) +{ + std::unique_lock lock(s_settings_mutex); + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) + ->RemoveFromStringList(section, key, value); +} + +void Host::DeleteBaseSettingValue(const char* section, const char* key) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->DeleteValue(section, key); +} + +SettingsInterface* Host::Internal::GetBaseSettingsLayer() +{ + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE); +} + +SettingsInterface* Host::Internal::GetGameSettingsLayer() +{ + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_GAME); +} + +SettingsInterface* Host::Internal::GetInputSettingsLayer() +{ + return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_INPUT); +} + +void Host::Internal::SetBaseSettingsLayer(SettingsInterface* sif) +{ + AssertMsg(s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) == nullptr, + "Base layer has not been set"); + s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif); +} + +void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif); +} + +void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif) +{ + std::unique_lock lock(s_settings_mutex); + s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif); +} + std::pair Host::LookupTranslationString(const std::string_view& context, const std::string_view& msg) { // TODO: TranslatableString, compile-time hashing. @@ -162,6 +357,118 @@ void Host::ReportFormattedDebuggerMessage(const char* format, ...) ReportDebuggerMessage(message); } +bool Host::CreateGPUDevice(RenderAPI api) +{ + DebugAssert(!g_gpu_device); + + Log_InfoPrintf("Trying to create a %s GPU device...", GPUDevice::RenderAPIToString(api)); + g_gpu_device = GPUDevice::CreateDeviceForAPI(api); + + // TODO: FSUI should always use vsync.. + const bool vsync = System::IsValid() ? System::ShouldUseVSync() : g_settings.video_sync_enabled; + if (!g_gpu_device || !g_gpu_device->Create(g_settings.gpu_adapter, + g_settings.gpu_disable_shader_cache ? std::string_view() : + std::string_view(EmuFolders::Cache), + SHADER_CACHE_VERSION, g_settings.gpu_use_debug_device, vsync, + g_settings.gpu_threaded_presentation)) + { + Log_ErrorPrintf("Failed to initialize GPU device."); + if (g_gpu_device) + g_gpu_device->Destroy(); + g_gpu_device.reset(); + return false; + } + + if (!ImGuiManager::Initialize()) + { + Log_ErrorPrintf("Failed to initialize ImGuiManager."); + g_gpu_device->Destroy(); + g_gpu_device.reset(); + return false; + } + + return true; +} + +void Host::UpdateDisplayWindow() +{ + if (!g_gpu_device) + return; + + if (!g_gpu_device->UpdateWindow()) + { + Host::ReportErrorAsync("Error", "Failed to change window after update. The log may contain more information."); + return; + } + + ImGuiManager::WindowResized(); + + // If we're paused, re-present the current frame at the new window size. + if (System::IsValid() && System::IsPaused()) + RenderDisplay(false); +} + +void Host::ResizeDisplayWindow(s32 width, s32 height, float scale) +{ + if (!g_gpu_device) + return; + + Log_DevPrintf("Display window resized to %dx%d", width, height); + + g_gpu_device->ResizeWindow(width, height, scale); + ImGuiManager::WindowResized(); + + // If we're paused, re-present the current frame at the new window size. + if (System::IsValid()) + { + if (System::IsPaused()) + RenderDisplay(false); + + System::HostDisplayResized(); + } +} + +void Host::ReleaseGPUDevice() +{ + if (!g_gpu_device) + return; + + SaveStateSelectorUI::DestroyTextures(); + FullscreenUI::Shutdown(); + ImGuiManager::Shutdown(); + + Log_InfoPrintf("Destroying %s GPU device...", GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI())); + g_gpu_device->Destroy(); + g_gpu_device.reset(); +} + +#ifndef __ANDROID__ + +std::unique_ptr Host::CreateAudioStream(AudioBackend backend, u32 sample_rate, u32 channels, u32 buffer_ms, + u32 latency_ms, AudioStretchMode stretch) +{ + switch (backend) + { +#ifdef WITH_CUBEB + case AudioBackend::Cubeb: + return AudioStream::CreateCubebAudioStream(sample_rate, channels, buffer_ms, latency_ms, stretch); +#endif + +#ifdef _WIN32 + case AudioBackend::XAudio2: + return AudioStream::CreateXAudio2Stream(sample_rate, channels, buffer_ms, latency_ms, stretch); +#endif + + case AudioBackend::Null: + return AudioStream::CreateNullStream(sample_rate, channels, buffer_ms); + + default: + return nullptr; + } +} + +#endif + void Host::RenderDisplay(bool skip_present) { Host::BeginPresentFrame(); diff --git a/src/core/host.h b/src/core/host.h index bf733717c..8408e3298 100644 --- a/src/core/host.h +++ b/src/core/host.h @@ -9,14 +9,17 @@ #include #include #include +#include #include #include #include #include +class SettingsInterface; struct WindowInfo; enum class AudioBackend : u8; enum class AudioStretchMode : u8; +enum class RenderAPI : u32; class AudioStream; class CDImage; @@ -38,6 +41,46 @@ std::optional ReadResourceFileToString(const char* filename); /// Returns the modified time of a resource. std::optional GetResourceFileTimestamp(const char* filename); +// Base setting retrieval, bypasses layers. +std::string GetBaseStringSettingValue(const char* section, const char* key, const char* default_value = ""); +bool GetBaseBoolSettingValue(const char* section, const char* key, bool default_value = false); +s32 GetBaseIntSettingValue(const char* section, const char* key, s32 default_value = 0); +u32 GetBaseUIntSettingValue(const char* section, const char* key, u32 default_value = 0); +float GetBaseFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); +double GetBaseDoubleSettingValue(const char* section, const char* key, double default_value = 0.0); +std::vector GetBaseStringListSetting(const char* section, const char* key); + +// Allows the emucore to write settings back to the frontend. Use with care. +// You should call CommitBaseSettingChanges() if you directly write to the layer (i.e. not these functions), or it may +// not be written to disk. +void SetBaseBoolSettingValue(const char* section, const char* key, bool value); +void SetBaseIntSettingValue(const char* section, const char* key, s32 value); +void SetBaseUIntSettingValue(const char* section, const char* key, u32 value); +void SetBaseFloatSettingValue(const char* section, const char* key, float value); +void SetBaseStringSettingValue(const char* section, const char* key, const char* value); +void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector& values); +bool AddValueToBaseStringListSetting(const char* section, const char* key, const char* value); +bool RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value); +void DeleteBaseSettingValue(const char* section, const char* key); +void CommitBaseSettingChanges(); + +// Settings access, thread-safe. +std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = ""); +bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false); +int GetIntSettingValue(const char* section, const char* key, s32 default_value = 0); +u32 GetUIntSettingValue(const char* section, const char* key, u32 default_value = 0); +float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); +double GetDoubleSettingValue(const char* section, const char* key, double default_value = 0.0); +std::vector GetStringListSetting(const char* section, const char* key); + +/// Direct access to settings interface. Must hold the lock when calling GetSettingsInterface() and while using it. +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(); + /// Returns a localized version of the specified string within the specified context. /// The pointer is guaranteed to be valid until the next language change. const char* TranslateToCString(const std::string_view& context, const std::string_view& msg); @@ -85,10 +128,6 @@ void ReportFormattedDebuggerMessage(const char* format, ...); /// such as compiling shaders when starting up. void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1, int progress_value = -1); -/// Internal method used by pads to dispatch vibration updates to input sources. -/// Intensity is normalized from 0 to 1. -void SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity); - /// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates. void SetMouseMode(bool relative, bool hide_cursor); @@ -105,6 +144,18 @@ bool CopyTextToClipboard(const std::string_view& text); /// if the user cancels the shutdown confirmation. void RequestExit(bool allow_confirm); +/// Attempts to create the rendering device backend. +bool CreateGPUDevice(RenderAPI api); + +/// Handles fullscreen transitions and such. +void UpdateDisplayWindow(); + +/// Called when the window is resized. +void ResizeDisplayWindow(s32 width, s32 height, float scale); + +/// Destroys any active rendering device. +void ReleaseGPUDevice(); + /// Called before drawing the OSD and other display elements. void BeginPresentFrame(); @@ -113,6 +164,24 @@ void RenderDisplay(bool skip_present); void InvalidateDisplay(); namespace Internal { +/// Retrieves the base settings layer. Must call with lock held. +SettingsInterface* GetBaseSettingsLayer(); + +/// Retrieves the game settings layer, if present. Must call with lock held. +SettingsInterface* GetGameSettingsLayer(); + +/// Retrieves the input settings layer, if present. Must call with lock held. +SettingsInterface* GetInputSettingsLayer(); + +/// Sets the base settings layer. Should be called by the host at initialization time. +void SetBaseSettingsLayer(SettingsInterface* sif); + +/// Sets the game settings layer. Called by VMManager when the game changes. +void SetGameSettingsLayer(SettingsInterface* sif); + +/// Sets the input profile settings layer. Called by VMManager when the game changes. +void SetInputSettingsLayer(SettingsInterface* sif); + /// 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/src/core/host_settings.cpp b/src/core/host_settings.cpp deleted file mode 100644 index c342174e2..000000000 --- a/src/core/host_settings.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#include "core/host.h" -#include "core/host_settings.h" -#include "common/assert.h" -#include "common/layered_settings_interface.h" - -static std::mutex s_settings_mutex; -static LayeredSettingsInterface s_layered_settings_interface; - -std::unique_lock Host::GetSettingsLock() -{ - return std::unique_lock(s_settings_mutex); -} - -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); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetStringValue(section, key, default_value); -} - -bool Host::GetBaseBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetBoolValue(section, key, default_value); -} - -s32 Host::GetBaseIntSettingValue(const char* section, const char* key, s32 default_value /*= 0*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetIntValue(section, key, default_value); -} - -u32 Host::GetBaseUIntSettingValue(const char* section, const char* key, u32 default_value /*= 0*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetUIntValue(section, key, default_value); -} - -float Host::GetBaseFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetFloatValue(section, key, default_value); -} - -double Host::GetBaseDoubleSettingValue(const char* section, const char* key, double default_value /* = 0.0f */) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetDoubleValue(section, key, default_value); -} - -std::vector Host::GetBaseStringListSetting(const char* section, const char* key) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->GetStringList(section, key); -} - -std::string Host::GetStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetStringValue(section, key, default_value); -} - -bool Host::GetBoolSettingValue(const char* section, const char* key, bool default_value /*= false*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetBoolValue(section, key, default_value); -} - -s32 Host::GetIntSettingValue(const char* section, const char* key, s32 default_value /*= 0*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetIntValue(section, key, default_value); -} - -u32 Host::GetUIntSettingValue(const char* section, const char* key, u32 default_value /*= 0*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetUIntValue(section, key, default_value); -} - -float Host::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetFloatValue(section, key, default_value); -} - -double Host::GetDoubleSettingValue(const char* section, const char* key, double default_value /*= 0.0f*/) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetDoubleValue(section, key, default_value); -} - -std::vector Host::GetStringListSetting(const char* section, const char* key) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetStringList(section, key); -} - -void Host::SetBaseBoolSettingValue(const char* section, const char* key, bool value) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetBoolValue(section, key, value); -} - -void Host::SetBaseIntSettingValue(const char* section, const char* key, int value) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetIntValue(section, key, value); -} - -void Host::SetBaseFloatSettingValue(const char* section, const char* key, float value) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetFloatValue(section, key, value); -} - -void Host::SetBaseStringSettingValue(const char* section, const char* key, const char* value) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringValue(section, key, value); -} - -void Host::SetBaseStringListSettingValue(const char* section, const char* key, const std::vector& values) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringList(section, key, values); -} - -bool Host::AddValueToBaseStringListSetting(const char* section, const char* key, const char* value) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->AddToStringList(section, key, value); -} - -bool Host::RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value) -{ - std::unique_lock lock(s_settings_mutex); - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) - ->RemoveFromStringList(section, key, value); -} - -void Host::DeleteBaseSettingValue(const char* section, const char* key) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->DeleteValue(section, key); -} - -SettingsInterface* Host::Internal::GetBaseSettingsLayer() -{ - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE); -} - -SettingsInterface* Host::Internal::GetGameSettingsLayer() -{ - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_GAME); -} - -SettingsInterface* Host::Internal::GetInputSettingsLayer() -{ - return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_INPUT); -} - -void Host::Internal::SetBaseSettingsLayer(SettingsInterface* sif) -{ - AssertMsg(s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) == nullptr, "Base layer has not been set"); - s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif); -} - -void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif); -} - -void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif) -{ - std::unique_lock lock(s_settings_mutex); - s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif); -} diff --git a/src/core/host_settings.h b/src/core/host_settings.h deleted file mode 100644 index 384a98ab6..000000000 --- a/src/core/host_settings.h +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#pragma once - -#include "common/types.h" -#include -#include -#include - -class SettingsInterface; - -namespace Host { -// Base setting retrieval, bypasses layers. -std::string GetBaseStringSettingValue(const char* section, const char* key, const char* default_value = ""); -bool GetBaseBoolSettingValue(const char* section, const char* key, bool default_value = false); -s32 GetBaseIntSettingValue(const char* section, const char* key, s32 default_value = 0); -u32 GetBaseUIntSettingValue(const char* section, const char* key, u32 default_value = 0); -float GetBaseFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); -double GetBaseDoubleSettingValue(const char* section, const char* key, double default_value = 0.0); -std::vector GetBaseStringListSetting(const char* section, const char* key); - -// Allows the emucore to write settings back to the frontend. Use with care. -// You should call CommitBaseSettingChanges() if you directly write to the layer (i.e. not these functions), or it may -// not be written to disk. -void SetBaseBoolSettingValue(const char* section, const char* key, bool value); -void SetBaseIntSettingValue(const char* section, const char* key, s32 value); -void SetBaseUIntSettingValue(const char* section, const char* key, u32 value); -void SetBaseFloatSettingValue(const char* section, const char* key, float value); -void SetBaseStringSettingValue(const char* section, const char* key, const char* value); -void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector& values); -bool AddValueToBaseStringListSetting(const char* section, const char* key, const char* value); -bool RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value); -void DeleteBaseSettingValue(const char* section, const char* key); -void CommitBaseSettingChanges(); - -// Settings access, thread-safe. -std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = ""); -bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false); -int GetIntSettingValue(const char* section, const char* key, s32 default_value = 0); -u32 GetUIntSettingValue(const char* section, const char* key, u32 default_value = 0); -float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); -double GetDoubleSettingValue(const char* section, const char* key, double default_value = 0.0); -std::vector GetStringListSetting(const char* section, const char* key); - -/// Direct access to settings interface. Must hold the lock when calling GetSettingsInterface() and while using it. -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(); - -namespace Internal { -/// Retrieves the base settings layer. Must call with lock held. -SettingsInterface* GetBaseSettingsLayer(); - -/// Retrieves the game settings layer, if present. Must call with lock held. -SettingsInterface* GetGameSettingsLayer(); - -/// Retrieves the input settings layer, if present. Must call with lock held. -SettingsInterface* GetInputSettingsLayer(); - -/// Sets the base settings layer. Should be called by the host at initialization time. -void SetBaseSettingsLayer(SettingsInterface* sif); - -/// Sets the game settings layer. Called by VMManager when the game changes. -void SetGameSettingsLayer(SettingsInterface* sif); - -/// Sets the input profile settings layer. Called by VMManager when the game changes. -void SetInputSettingsLayer(SettingsInterface* sif); -} // namespace Internal -} // namespace Host \ No newline at end of file diff --git a/src/core/common_host.cpp b/src/core/hotkeys.cpp similarity index 60% rename from src/core/common_host.cpp rename to src/core/hotkeys.cpp index 7d94a0ac4..00d58a254 100644 --- a/src/core/common_host.cpp +++ b/src/core/hotkeys.cpp @@ -1,375 +1,28 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) -#include "common_host.h" -#include "cdrom.h" -#include "cheats.h" -#include "controller.h" #include "cpu_code_cache.h" -#include "dma.h" +#include "cpu_core.h" #include "fullscreen_ui.h" -#include "game_list.h" #include "gpu.h" -#include "gte.h" #include "host.h" -#include "host_settings.h" #include "imgui_overlays.h" -#include "mdec.h" #include "pgxp.h" -#include "resources.h" -#include "save_state_version.h" #include "settings.h" -#include "shader_cache_version.h" #include "spu.h" #include "system.h" #include "texture_replacements.h" -#include "timers.h" -#include "scmversion/scmversion.h" - -#include "util/audio_stream.h" #include "util/gpu_device.h" -#include "util/imgui_fullscreen.h" -#include "util/imgui_manager.h" -#include "util/ini_settings_interface.h" #include "util/input_manager.h" -#include "util/platform_misc.h" -#include "common/assert.h" -#include "common/byte_stream.h" -#include "common/crash_handler.h" #include "common/file_system.h" -#include "common/log.h" -#include "common/path.h" -#include "common/string_util.h" #include "IconsFontAwesome5.h" -#include "imgui.h" #include -#include -#include -#include -#ifdef WITH_DISCORD_PRESENCE -#include "discord_rpc.h" -#endif - -#ifdef WITH_CHEEVOS -#include "achievements_private.h" -#endif - -#ifdef _WIN32 -#include "common/windows_headers.h" -#include -#include -#include -#endif - -Log_SetChannel(CommonHostInterface); - -namespace CommonHost { -static void UpdateSessionTime(const std::string& new_serial); - -#ifdef WITH_DISCORD_PRESENCE -static void SetDiscordPresenceEnabled(bool enabled); -static void InitializeDiscordPresence(); -static void ShutdownDiscordPresence(); -static void UpdateDiscordPresence(bool rich_presence_only); -static void PollDiscordPresence(); -#endif -} // namespace CommonHost - -// Used to track play time. We use a monotonic timer here, in case of clock changes. -static u64 s_session_start_time = 0; -static std::string s_session_serial; - -#ifdef WITH_DISCORD_PRESENCE -// discord rich presence -bool m_discord_presence_enabled = false; -bool m_discord_presence_active = false; -#ifdef WITH_CHEEVOS -std::string m_discord_presence_cheevos_string; -#endif -#endif - -void CommonHost::Initialize() -{ - // This will call back to Host::LoadSettings() -> ReloadSources(). - System::LoadSettings(false); - -#ifdef WITH_CHEEVOS -#ifdef WITH_RAINTEGRATION - if (Host::GetBaseBoolSettingValue("Cheevos", "UseRAIntegration", false)) - Achievements::SwitchToRAIntegration(); -#endif - if (g_settings.achievements_enabled) - Achievements::Initialize(); -#endif -} - -void CommonHost::Shutdown() -{ -#ifdef WITH_DISCORD_PRESENCE - CommonHost::ShutdownDiscordPresence(); -#endif - -#ifdef WITH_CHEEVOS - Achievements::Shutdown(); -#endif - - InputManager::CloseSources(); -} - -void CommonHost::PumpMessagesOnCPUThread() -{ - InputManager::PollSources(); - -#ifdef WITH_DISCORD_PRESENCE - PollDiscordPresence(); -#endif - -#ifdef WITH_CHEEVOS - if (Achievements::IsActive()) - Achievements::FrameUpdate(); -#endif -} - -bool Host::CreateGPUDevice(RenderAPI api) -{ - DebugAssert(!g_gpu_device); - - Log_InfoPrintf("Trying to create a %s GPU device...", GPUDevice::RenderAPIToString(api)); - g_gpu_device = GPUDevice::CreateDeviceForAPI(api); - - // TODO: FSUI should always use vsync.. - const bool vsync = System::IsValid() ? System::ShouldUseVSync() : g_settings.video_sync_enabled; - if (!g_gpu_device || !g_gpu_device->Create(g_settings.gpu_adapter, - g_settings.gpu_disable_shader_cache ? std::string_view() : - std::string_view(EmuFolders::Cache), - SHADER_CACHE_VERSION, g_settings.gpu_use_debug_device, vsync, - g_settings.gpu_threaded_presentation)) - { - Log_ErrorPrintf("Failed to initialize GPU device."); - if (g_gpu_device) - g_gpu_device->Destroy(); - g_gpu_device.reset(); - return false; - } - - if (!ImGuiManager::Initialize()) - { - Log_ErrorPrintf("Failed to initialize ImGuiManager."); - g_gpu_device->Destroy(); - g_gpu_device.reset(); - return false; - } - - return true; -} - -void Host::UpdateDisplayWindow() -{ - if (!g_gpu_device) - return; - - if (!g_gpu_device->UpdateWindow()) - { - Host::ReportErrorAsync("Error", "Failed to change window after update. The log may contain more information."); - return; - } - - ImGuiManager::WindowResized(); - - // If we're paused, re-present the current frame at the new window size. - if (System::IsValid() && System::IsPaused()) - RenderDisplay(false); -} - -void Host::ResizeDisplayWindow(s32 width, s32 height, float scale) -{ - if (!g_gpu_device) - return; - - Log_DevPrintf("Display window resized to %dx%d", width, height); - - g_gpu_device->ResizeWindow(width, height, scale); - ImGuiManager::WindowResized(); - - // If we're paused, re-present the current frame at the new window size. - if (System::IsValid()) - { - if (System::IsPaused()) - RenderDisplay(false); - - System::HostDisplayResized(); - } -} - -void Host::ReleaseGPUDevice() -{ - if (!g_gpu_device) - return; - - SaveStateSelectorUI::DestroyTextures(); - FullscreenUI::Shutdown(); - ImGuiManager::Shutdown(); - - Log_InfoPrintf("Destroying %s GPU device...", GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI())); - g_gpu_device->Destroy(); - g_gpu_device.reset(); -} - -#ifndef __ANDROID__ - -std::unique_ptr Host::CreateAudioStream(AudioBackend backend, u32 sample_rate, u32 channels, u32 buffer_ms, - u32 latency_ms, AudioStretchMode stretch) -{ - switch (backend) - { -#ifdef WITH_CUBEB - case AudioBackend::Cubeb: - return AudioStream::CreateCubebAudioStream(sample_rate, channels, buffer_ms, latency_ms, stretch); -#endif - -#ifdef _WIN32 - case AudioBackend::XAudio2: - return AudioStream::CreateXAudio2Stream(sample_rate, channels, buffer_ms, latency_ms, stretch); -#endif - - case AudioBackend::Null: - return AudioStream::CreateNullStream(sample_rate, channels, buffer_ms); - - default: - return nullptr; - } -} - -#endif - -void CommonHost::UpdateLogSettings() -{ - Log::SetFilterLevel(g_settings.log_level); - Log::SetConsoleOutputParams(g_settings.log_to_console, - g_settings.log_filter.empty() ? nullptr : g_settings.log_filter.c_str(), - g_settings.log_level); - Log::SetDebugOutputParams(g_settings.log_to_debug, - g_settings.log_filter.empty() ? nullptr : g_settings.log_filter.c_str(), - g_settings.log_level); - - if (g_settings.log_to_file) - { - Log::SetFileOutputParams(g_settings.log_to_file, Path::Combine(EmuFolders::DataRoot, "duckstation.log").c_str(), - true, g_settings.log_filter.empty() ? nullptr : g_settings.log_filter.c_str(), - g_settings.log_level); - } - else - { - Log::SetFileOutputParams(false, nullptr); - } -} - -void CommonHost::OnSystemStarting() -{ - // -} - -void CommonHost::OnSystemStarted() -{ - FullscreenUI::OnSystemStarted(); - - if (g_settings.inhibit_screensaver) - FrontendCommon::SuspendScreensaver(); -} - -void CommonHost::OnSystemPaused() -{ - FullscreenUI::OnSystemPaused(); - - InputManager::PauseVibration(); - -#ifdef WITH_CHEEVOS - Achievements::OnSystemPaused(true); -#endif - - if (g_settings.inhibit_screensaver) - FrontendCommon::ResumeScreensaver(); -} - -void CommonHost::OnSystemResumed() -{ - FullscreenUI::OnSystemResumed(); - -#ifdef WITH_CHEEVOS - Achievements::OnSystemPaused(false); -#endif - - if (g_settings.inhibit_screensaver) - FrontendCommon::SuspendScreensaver(); -} - -void CommonHost::OnSystemDestroyed() -{ - Host::ClearOSDMessages(); - - SaveStateSelectorUI::Close(true); - FullscreenUI::OnSystemDestroyed(); - - InputManager::PauseVibration(); - - if (g_settings.inhibit_screensaver) - FrontendCommon::ResumeScreensaver(); -} - -void CommonHost::OnGameChanged(const std::string& disc_path, const std::string& game_serial, - const std::string& game_name) -{ -#ifdef WITH_DISCORD_PRESENCE - UpdateDiscordPresence(false); -#endif - - UpdateSessionTime(game_serial); - - SaveStateSelectorUI::RefreshList(); -} - -void CommonHost::SetDefaultSettings(SettingsInterface& si) -{ -#ifdef WITH_DISCORD_PRESENCE - si.SetBoolValue("Main", "EnableDiscordPresence", false); -#endif - -#if defined(WITH_CHEEVOS) && defined(WITH_RAINTEGRATION) - si.SetBoolValue("Cheevos", "UseRAIntegration", false); -#endif -} - -void CommonHost::SetDefaultControllerSettings(SettingsInterface& si) -{ - InputManager::SetDefaultConfig(si); - - // Global Settings - si.SetStringValue("ControllerPorts", "MultitapMode", Settings::GetMultitapModeName(Settings::DEFAULT_MULTITAP_MODE)); - si.SetFloatValue("ControllerPorts", "PointerXScale", 8.0f); - si.SetFloatValue("ControllerPorts", "PointerYScale", 8.0f); - si.SetBoolValue("ControllerPorts", "PointerXInvert", false); - si.SetBoolValue("ControllerPorts", "PointerYInvert", false); - - // Default pad types and parameters. - for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) - { - const std::string section(Controller::GetSettingsSection(i)); - si.ClearSection(section.c_str()); - si.SetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(i)); - } - -#ifndef __ANDROID__ - // Use the automapper to set this up. - InputManager::MapController(si, 0, InputManager::GetGenericBindingMapping("Keyboard")); -#endif -} - -void CommonHost::SetDefaultHotkeyBindings(SettingsInterface& si) +void Settings::SetDefaultHotkeyConfig(SettingsInterface& si) { si.ClearSection("Hotkeys"); @@ -387,276 +40,6 @@ void CommonHost::SetDefaultHotkeyBindings(SettingsInterface& si) #endif } -void CommonHost::LoadSettings(SettingsInterface& si, std::unique_lock& lock) -{ - UpdateLogSettings(); - InputManager::ReloadSources(si, lock); - InputManager::ReloadBindings(si, *Host::GetSettingsInterfaceForBindings()); - -#ifdef WITH_DISCORD_PRESENCE - SetDiscordPresenceEnabled(si.GetBoolValue("Main", "EnableDiscordPresence", false)); -#endif -} - -void CommonHost::CheckForSettingsChanges(const Settings& old_settings) -{ - if (System::IsValid()) - { - if (g_settings.inhibit_screensaver != old_settings.inhibit_screensaver) - { - if (g_settings.inhibit_screensaver) - FrontendCommon::SuspendScreensaver(); - else - FrontendCommon::ResumeScreensaver(); - } - } - -#ifdef WITH_CHEEVOS - Achievements::UpdateSettings(old_settings); -#endif - - FullscreenUI::CheckForConfigChanges(old_settings); - - if (g_settings.log_level != old_settings.log_level || g_settings.log_filter != old_settings.log_filter || - g_settings.log_to_console != old_settings.log_to_console || - g_settings.log_to_debug != old_settings.log_to_debug || g_settings.log_to_window != old_settings.log_to_window || - g_settings.log_to_file != old_settings.log_to_file) - { - UpdateLogSettings(); - } -} - -void CommonHost::UpdateSessionTime(const std::string& new_serial) -{ - if (s_session_serial == new_serial) - return; - - const u64 ctime = Common::Timer::GetCurrentValue(); - if (!s_session_serial.empty()) - { - // round up to seconds - const std::time_t etime = - static_cast(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time))); - const std::time_t wtime = std::time(nullptr); - GameList::AddPlayedTimeForSerial(s_session_serial, wtime, etime); - } - - s_session_serial = new_serial; - s_session_start_time = ctime; -} - -u64 CommonHost::GetSessionPlayedTime() -{ - const u64 ctime = Common::Timer::GetCurrentValue(); - return static_cast(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time))); -} - -void Host::SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity) -{ - InputManager::SetPadVibrationIntensity(pad_index, large_or_single_motor_intensity, small_motor_intensity); -} - -void Host::DisplayLoadingScreen(const char* message, int progress_min /*= -1*/, int progress_max /*= -1*/, - int progress_value /*= -1*/) -{ - const auto& io = ImGui::GetIO(); - const float scale = ImGuiManager::GetGlobalScale(); - const float width = (400.0f * scale); - const bool has_progress = (progress_min < progress_max); - - // eat the last imgui frame, it might've been partially rendered by the caller. - ImGui::EndFrame(); - ImGui::NewFrame(); - - const float logo_width = 260.0f * scale; - const float logo_height = 260.0f * scale; - - ImGui::SetNextWindowSize(ImVec2(logo_width, logo_height), ImGuiCond_Always); - ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, (io.DisplaySize.y * 0.5f) - (50.0f * scale)), - ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - if (ImGui::Begin("LoadingScreenLogo", nullptr, - ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | - ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | - ImGuiWindowFlags_NoBackground)) - { - GPUTexture* tex = ImGuiFullscreen::GetCachedTexture("images/duck.png"); - if (tex) - ImGui::Image(tex, ImVec2(logo_width, logo_height)); - } - ImGui::End(); - - const float padding_and_rounding = 15.0f * scale; - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, padding_and_rounding); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(padding_and_rounding, padding_and_rounding)); - ImGui::SetNextWindowSize(ImVec2(width, (has_progress ? 80.0f : 50.0f) * scale), ImGuiCond_Always); - ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, (io.DisplaySize.y * 0.5f) + (100.0f * scale)), - ImGuiCond_Always, ImVec2(0.5f, 0.0f)); - if (ImGui::Begin("LoadingScreen", nullptr, - ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | - ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing)) - { - if (has_progress) - { - ImGui::TextUnformatted(message); - - TinyString buf; - buf.Fmt("{}/{}", progress_value, progress_max); - - const ImVec2 prog_size = ImGui::CalcTextSize(buf.GetCharArray(), buf.GetCharArray() + buf.GetLength()); - ImGui::SameLine(); - ImGui::SetCursorPosX(width - padding_and_rounding - prog_size.x); - ImGui::TextUnformatted(buf.GetCharArray(), buf.GetCharArray() + buf.GetLength()); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f); - - ImGui::ProgressBar(static_cast(progress_value) / static_cast(progress_max - progress_min), - ImVec2(-1.0f, 0.0f), ""); - Log_InfoPrintf("%s: %d/%d", message, progress_value, progress_max); - } - else - { - const ImVec2 text_size(ImGui::CalcTextSize(message)); - ImGui::SetCursorPosX((width - text_size.x) / 2.0f); - ImGui::TextUnformatted(message); - Log_InfoPrintf("%s", message); - } - } - ImGui::End(); - ImGui::PopStyleVar(2); - - ImGui::EndFrame(); - g_gpu_device->Render(false); - ImGui::NewFrame(); -} - -void ImGuiManager::RenderDebugWindows() -{ - if (System::IsValid()) - { - if (g_settings.debugging.show_gpu_state) - g_gpu->DrawDebugStateWindow(); - if (g_settings.debugging.show_cdrom_state) - CDROM::DrawDebugWindow(); - if (g_settings.debugging.show_timers_state) - Timers::DrawDebugStateWindow(); - if (g_settings.debugging.show_spu_state) - SPU::DrawDebugStateWindow(); - if (g_settings.debugging.show_mdec_state) - MDEC::DrawDebugStateWindow(); - if (g_settings.debugging.show_dma_state) - DMA::DrawDebugStateWindow(); - } -} - -#ifdef WITH_DISCORD_PRESENCE - -void CommonHost::SetDiscordPresenceEnabled(bool enabled) -{ - if (m_discord_presence_enabled == enabled) - return; - - m_discord_presence_enabled = enabled; - if (enabled) - InitializeDiscordPresence(); - else - ShutdownDiscordPresence(); -} - -void CommonHost::InitializeDiscordPresence() -{ - if (m_discord_presence_active) - return; - - DiscordEventHandlers handlers = {}; - Discord_Initialize("705325712680288296", &handlers, 0, nullptr); - m_discord_presence_active = true; - - UpdateDiscordPresence(false); -} - -void CommonHost::ShutdownDiscordPresence() -{ - if (!m_discord_presence_active) - return; - - Discord_ClearPresence(); - Discord_Shutdown(); - m_discord_presence_active = false; -#ifdef WITH_CHEEVOS - m_discord_presence_cheevos_string.clear(); -#endif -} - -void CommonHost::UpdateDiscordPresence(bool rich_presence_only) -{ - if (!m_discord_presence_active) - return; - -#ifdef WITH_CHEEVOS - // Update only if RetroAchievements rich presence has changed - const std::string& new_rich_presence = Achievements::GetRichPresenceString(); - if (new_rich_presence == m_discord_presence_cheevos_string && rich_presence_only) - { - return; - } - m_discord_presence_cheevos_string = new_rich_presence; -#else - if (rich_presence_only) - { - return; - } -#endif - - // https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields - DiscordRichPresence rp = {}; - rp.largeImageKey = "duckstation_logo"; - rp.largeImageText = "DuckStation PS1/PSX Emulator"; - rp.startTimestamp = std::time(nullptr); - - SmallString details_string; - if (!System::IsShutdown()) - { - details_string.AppendFormattedString("%s (%s)", System::GetGameTitle().c_str(), System::GetGameSerial().c_str()); - } - else - { - details_string.AppendString("No Game Running"); - } - -#ifdef WITH_CHEEVOS - SmallString state_string; - // Trim to 128 bytes as per Discord-RPC requirements - if (m_discord_presence_cheevos_string.length() >= 128) - { - // 124 characters + 3 dots + null terminator - state_string = m_discord_presence_cheevos_string.substr(0, 124); - state_string.AppendString("..."); - } - else - { - state_string = m_discord_presence_cheevos_string; - } - - rp.state = state_string; -#endif - rp.details = details_string; - - Discord_UpdatePresence(&rp); -} - -void CommonHost::PollDiscordPresence() -{ - if (!m_discord_presence_active) - return; - - UpdateDiscordPresence(true); - - Discord_RunCallbacks(); -} - -#endif - static void HotkeyModifyResolutionScale(s32 increment) { const u32 new_resolution_scale = std::clamp( diff --git a/src/core/imgui_overlays.cpp b/src/core/imgui_overlays.cpp index 5a3542248..bf60dd474 100644 --- a/src/core/imgui_overlays.cpp +++ b/src/core/imgui_overlays.cpp @@ -1,12 +1,14 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "imgui_overlays.h" +#include "cdrom.h" #include "controller.h" +#include "dma.h" #include "fullscreen_ui.h" #include "gpu.h" #include "host.h" -#include "host_settings.h" +#include "mdec.h" #include "resources.h" #include "settings.h" #include "spu.h" @@ -131,6 +133,99 @@ static std::tuple GetMinMax(gsl::span values) static bool s_save_state_selector_ui_open = false; +void Host::DisplayLoadingScreen(const char* message, int progress_min /*= -1*/, int progress_max /*= -1*/, + int progress_value /*= -1*/) +{ + const auto& io = ImGui::GetIO(); + const float scale = ImGuiManager::GetGlobalScale(); + const float width = (400.0f * scale); + const bool has_progress = (progress_min < progress_max); + + // eat the last imgui frame, it might've been partially rendered by the caller. + ImGui::EndFrame(); + ImGui::NewFrame(); + + const float logo_width = 260.0f * scale; + const float logo_height = 260.0f * scale; + + ImGui::SetNextWindowSize(ImVec2(logo_width, logo_height), ImGuiCond_Always); + ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, (io.DisplaySize.y * 0.5f) - (50.0f * scale)), + ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + if (ImGui::Begin("LoadingScreenLogo", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoBackground)) + { + GPUTexture* tex = ImGuiFullscreen::GetCachedTexture("images/duck.png"); + if (tex) + ImGui::Image(tex, ImVec2(logo_width, logo_height)); + } + ImGui::End(); + + const float padding_and_rounding = 15.0f * scale; + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, padding_and_rounding); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(padding_and_rounding, padding_and_rounding)); + ImGui::SetNextWindowSize(ImVec2(width, (has_progress ? 80.0f : 50.0f) * scale), ImGuiCond_Always); + ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, (io.DisplaySize.y * 0.5f) + (100.0f * scale)), + ImGuiCond_Always, ImVec2(0.5f, 0.0f)); + if (ImGui::Begin("LoadingScreen", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing)) + { + if (has_progress) + { + ImGui::TextUnformatted(message); + + TinyString buf; + buf.Fmt("{}/{}", progress_value, progress_max); + + const ImVec2 prog_size = ImGui::CalcTextSize(buf.GetCharArray(), buf.GetCharArray() + buf.GetLength()); + ImGui::SameLine(); + ImGui::SetCursorPosX(width - padding_and_rounding - prog_size.x); + ImGui::TextUnformatted(buf.GetCharArray(), buf.GetCharArray() + buf.GetLength()); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f); + + ImGui::ProgressBar(static_cast(progress_value) / static_cast(progress_max - progress_min), + ImVec2(-1.0f, 0.0f), ""); + Log_InfoPrintf("%s: %d/%d", message, progress_value, progress_max); + } + else + { + const ImVec2 text_size(ImGui::CalcTextSize(message)); + ImGui::SetCursorPosX((width - text_size.x) / 2.0f); + ImGui::TextUnformatted(message); + Log_InfoPrintf("%s", message); + } + } + ImGui::End(); + ImGui::PopStyleVar(2); + + ImGui::EndFrame(); + g_gpu_device->Render(false); + ImGui::NewFrame(); +} + +void ImGuiManager::RenderDebugWindows() +{ + if (System::IsValid()) + { + if (g_settings.debugging.show_gpu_state) + g_gpu->DrawDebugStateWindow(); + if (g_settings.debugging.show_cdrom_state) + CDROM::DrawDebugWindow(); + if (g_settings.debugging.show_timers_state) + Timers::DrawDebugStateWindow(); + if (g_settings.debugging.show_spu_state) + SPU::DrawDebugStateWindow(); + if (g_settings.debugging.show_mdec_state) + MDEC::DrawDebugStateWindow(); + if (g_settings.debugging.show_dma_state) + DMA::DrawDebugStateWindow(); + } +} + void ImGuiManager::RenderTextOverlays() { const System::State state = System::GetState(); diff --git a/src/core/imgui_overlays.h b/src/core/imgui_overlays.h index 3a5378224..599e5fcc8 100644 --- a/src/core/imgui_overlays.h +++ b/src/core/imgui_overlays.h @@ -7,8 +7,9 @@ namespace ImGuiManager { void RenderTextOverlays(); +void RenderDebugWindows(); void RenderOverlayWindows(); -} +} // namespace ImGuiManager namespace SaveStateSelectorUI { diff --git a/src/core/settings.cpp b/src/core/settings.cpp index abd1d4724..93ce49c49 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -5,10 +5,10 @@ #include "achievements.h" #include "controller.h" #include "host.h" -#include "host_settings.h" #include "system.h" #include "util/gpu_device.h" +#include "util/input_manager.h" #include "common/assert.h" #include "common/file_system.h" @@ -182,6 +182,7 @@ void Settings::Load(SettingsInterface& si) apply_game_settings = si.GetBoolValue("Main", "ApplyGameSettings", true); auto_load_cheats = si.GetBoolValue("Main", "AutoLoadCheats", true); disable_all_enhancements = si.GetBoolValue("Main", "DisableAllEnhancements", false); + enable_discord_presence = si.GetBoolValue("Main", "EnableDiscordPresence", false); rewind_enable = si.GetBoolValue("Main", "RewindEnable", false); rewind_save_frequency = si.GetFloatValue("Main", "RewindFrequency", 10.0f); rewind_save_slots = static_cast(si.GetIntValue("Main", "RewindSaveSlots", 10)); @@ -369,6 +370,7 @@ void Settings::Load(SettingsInterface& si) achievements_notifications = si.GetBoolValue("Cheevos", "Notifications", true); achievements_sound_effects = si.GetBoolValue("Cheevos", "SoundEffects", true); achievements_primed_indicators = si.GetBoolValue("Cheevos", "PrimedIndicators", true); + achievements_use_raintegration = si.GetBoolValue("Cheevos", "UseRAIntegration", false); log_level = ParseLogLevelName(si.GetStringValue("Logging", "LogLevel", GetLogLevelName(DEFAULT_LOG_LEVEL)).c_str()) .value_or(DEFAULT_LOG_LEVEL); @@ -426,6 +428,7 @@ void Settings::Save(SettingsInterface& si) const si.SetBoolValue("Main", "ApplyGameSettings", apply_game_settings); si.SetBoolValue("Main", "AutoLoadCheats", auto_load_cheats); si.SetBoolValue("Main", "DisableAllEnhancements", disable_all_enhancements); + si.SetBoolValue("Main", "EnableDiscordPresence", enable_discord_presence); si.SetBoolValue("Main", "RewindEnable", rewind_enable); si.SetFloatValue("Main", "RewindFrequency", rewind_save_frequency); si.SetIntValue("Main", "RewindSaveSlots", rewind_save_slots); @@ -565,6 +568,7 @@ void Settings::Save(SettingsInterface& si) const si.SetBoolValue("Cheevos", "Notifications", achievements_notifications); si.SetBoolValue("Cheevos", "SoundEffects", achievements_sound_effects); si.SetBoolValue("Cheevos", "PrimedIndicators", achievements_primed_indicators); + si.SetBoolValue("Cheevos", "UseRAIntegration", achievements_use_raintegration); si.SetStringValue("Logging", "LogLevel", GetLogLevelName(log_level)); si.SetStringValue("Logging", "LogFilter", log_filter.c_str()); @@ -726,6 +730,46 @@ void Settings::FixIncompatibleSettings(bool display_osd_messages) } } +void Settings::UpdateLogSettings() +{ + Log::SetFilterLevel(log_level); + Log::SetConsoleOutputParams(log_to_console, log_filter.empty() ? nullptr : log_filter.c_str(), log_level); + Log::SetDebugOutputParams(log_to_debug, log_filter.empty() ? nullptr : log_filter.c_str(), log_level); + + if (log_to_file) + { + Log::SetFileOutputParams(log_to_file, Path::Combine(EmuFolders::DataRoot, "duckstation.log").c_str(), true, + log_filter.empty() ? nullptr : log_filter.c_str(), log_level); + } + else + { + Log::SetFileOutputParams(false, nullptr); + } +} + +void Settings::SetDefaultControllerConfig(SettingsInterface& si) +{ + // Global Settings + si.SetStringValue("ControllerPorts", "MultitapMode", GetMultitapModeName(Settings::DEFAULT_MULTITAP_MODE)); + si.SetFloatValue("ControllerPorts", "PointerXScale", 8.0f); + si.SetFloatValue("ControllerPorts", "PointerYScale", 8.0f); + si.SetBoolValue("ControllerPorts", "PointerXInvert", false); + si.SetBoolValue("ControllerPorts", "PointerYInvert", false); + + // Default pad types and parameters. + for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) + { + const std::string section(Controller::GetSettingsSection(i)); + si.ClearSection(section.c_str()); + si.SetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(i)); + } + +#ifndef __ANDROID__ + // Use the automapper to set this up. + InputManager::MapController(si, 0, InputManager::GetGenericBindingMapping("Keyboard")); +#endif +} + static std::array s_log_level_names = { {"None", "Error", "Warning", "Perf", "Info", "Verbose", "Dev", "Profile", "Debug", "Trace"}}; static std::array s_log_level_display_names = { diff --git a/src/core/settings.h b/src/core/settings.h index 95239c9fb..19cbda1d5 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -85,6 +85,7 @@ struct Settings bool apply_game_settings = true; bool auto_load_cheats = true; bool disable_all_enhancements = false; + bool enable_discord_presence = false; bool rewind_enable = false; float rewind_save_frequency = 10.0f; @@ -190,6 +191,7 @@ struct Settings bool achievements_notifications = true; bool achievements_sound_effects = true; bool achievements_primed_indicators = true; + bool achievements_use_raintegration = false; struct DebugSettings { @@ -336,6 +338,12 @@ struct Settings void FixIncompatibleSettings(bool display_osd_messages); + /// Initializes configuration. + void UpdateLogSettings(); + + static void SetDefaultControllerConfig(SettingsInterface& si); + static void SetDefaultHotkeyConfig(SettingsInterface& si); + static std::optional ParseLogLevelName(const char* str); static const char* GetLogLevelName(LOGLEVEL level); static const char* GetLogLevelDisplayName(LOGLEVEL level); diff --git a/src/core/system.cpp b/src/core/system.cpp index 9d88fdbcf..26c12a1eb 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -12,14 +12,14 @@ #include "cpu_code_cache.h" #include "cpu_core.h" #include "dma.h" -#include "fmt/chrono.h" -#include "fmt/format.h" +#include "fullscreen_ui.h" #include "game_database.h" +#include "game_list.h" #include "gpu.h" #include "gte.h" #include "host.h" #include "host_interface_progress_callback.h" -#include "host_settings.h" +#include "imgui_overlays.h" #include "interrupt_controller.h" #include "mdec.h" #include "memory_card.h" @@ -38,7 +38,9 @@ #include "util/cd_image.h" #include "util/gpu_device.h" #include "util/ini_settings_interface.h" +#include "util/input_manager.h" #include "util/iso_reader.h" +#include "util/platform_misc.h" #include "util/state_wrapper.h" #include "common/error.h" @@ -49,6 +51,8 @@ #include "common/string_util.h" #include "common/threading.h" +#include "fmt/chrono.h" +#include "fmt/format.h" #include "xxhash.h" #include @@ -67,6 +71,10 @@ Log_SetChannel(System); #include #endif +#ifdef WITH_DISCORD_PRESENCE +#include "discord_rpc.h" +#endif + // #define PROFILE_MEMORY_SAVE_STATES 1 SystemBootParameters::SystemBootParameters() = default; @@ -130,7 +138,16 @@ static void UpdateRunningGame(const char* path, CDImage* image, bool booting); static bool CheckForSBIFile(CDImage* image); static std::unique_ptr GetMemoryCardForSlot(u32 slot, MemoryCardType type); +static void UpdateSessionTime(const std::string& prev_serial); + static void SetTimerResolutionIncreased(bool enabled); + +#ifdef WITH_DISCORD_PRESENCE +static void InitializeDiscordPresence(); +static void ShutdownDiscordPresence(); +static void UpdateDiscordPresence(bool rich_presence_only); +static void PollDiscordPresence(); +#endif } // namespace System static constexpr const float PERFORMANCE_COUNTER_UPDATE_INTERVAL = 1.0f; @@ -222,11 +239,63 @@ static bool s_runahead_replay_pending = false; static u32 s_runahead_frames = 0; static u32 s_runahead_replay_frames = 0; +// Used to track play time. We use a monotonic timer here, in case of clock changes. +static u64 s_session_start_time = 0; + +#ifdef WITH_DISCORD_PRESENCE +// discord rich presence +static bool s_discord_presence_active = false; +#ifdef WITH_CHEEVOS +static std::string s_discord_presence_cheevos_string; +#endif +#endif + static TinyString GetTimestampStringForFileName() { return TinyString::FromFmt("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(std::time(nullptr))); } +void System::Internal::ProcessStartup() +{ + // This will call back to Host::LoadSettings() -> ReloadSources(). + LoadSettings(false); + +#ifdef WITH_CHEEVOS +#ifdef WITH_RAINTEGRATION + if (Host::GetBaseBoolSettingValue("Cheevos", "UseRAIntegration", false)) + Achievements::SwitchToRAIntegration(); +#endif + if (g_settings.achievements_enabled) + Achievements::Initialize(); +#endif +} + +void System::Internal::ProcessShutdown() +{ +#ifdef WITH_DISCORD_PRESENCE + ShutdownDiscordPresence(); +#endif + +#ifdef WITH_CHEEVOS + Achievements::Shutdown(); +#endif + + InputManager::CloseSources(); +} + +void System::Internal::IdlePollUpdate() +{ + InputManager::PollSources(); + +#ifdef WITH_DISCORD_PRESENCE + PollDiscordPresence(); +#endif + +#ifdef WITH_CHEEVOS + Achievements::ProcessPendingHTTPRequests(); +#endif +} + System::State System::GetState() { return s_state; @@ -845,7 +914,11 @@ void System::LoadSettings(bool display_osd_messages) std::unique_lock lock = Host::GetSettingsLock(); SettingsInterface& si = *Host::GetSettingsInterface(); g_settings.Load(si); + g_settings.UpdateLogSettings(); + Host::LoadSettings(si, lock); + InputManager::ReloadSources(si, lock); + InputManager::ReloadBindings(si, *Host::GetSettingsInterfaceForBindings()); // apply compatibility settings if (g_settings.apply_compatibility_settings && !s_running_game_serial.empty()) @@ -1017,12 +1090,34 @@ void System::PauseSystem(bool paused) if (paused) { + FullscreenUI::OnSystemPaused(); + + InputManager::PauseVibration(); + +#ifdef WITH_CHEEVOS + Achievements::OnSystemPaused(true); +#endif + + if (g_settings.inhibit_screensaver) + PlatformMisc::ResumeScreensaver(); + Host::OnSystemPaused(); } else { - Host::OnSystemResumed(); + FullscreenUI::OnSystemResumed(); + +#ifdef WITH_CHEEVOS + Achievements::OnSystemPaused(false); +#endif + + if (g_settings.inhibit_screensaver) + PlatformMisc::SuspendScreensaver(); + UpdateDisplaySync(); + + Host::OnSystemResumed(); + ResetPerformanceCounters(); ResetThrottler(); } @@ -1330,16 +1425,16 @@ bool System::BootSystem(SystemBootParameters parameters) } // Good to go. - s_state = - (g_settings.start_paused || parameters.override_start_paused.value_or(false)) ? State::Paused : State::Running; + s_state = State::Running; UpdateSoftwareCursor(); SPU::GetOutputStream()->SetPaused(false); - Host::OnSystemStarted(); - if (s_state == State::Paused) - Host::OnSystemPaused(); - else - Host::OnSystemResumed(); + FullscreenUI::OnSystemStarted(); + + if (g_settings.inhibit_screensaver) + PlatformMisc::SuspendScreensaver(); + + Host::OnSystemStarted(); // try to load the state, if it fails, bail out if (!parameters.save_state.empty()) @@ -1371,6 +1466,9 @@ bool System::BootSystem(SystemBootParameters parameters) if (g_settings.audio_dump_on_boot) StartDumpingAudio(); + if (g_settings.start_paused || parameters.override_start_paused.value_or(false)) + PauseSystem(true); + ResetPerformanceCounters(); if (IsRunning()) UpdateSpeedLimiterState(); @@ -1520,6 +1618,16 @@ void System::DestroySystem() if (s_state == State::Shutdown) return; + Host::ClearOSDMessages(); + + SaveStateSelectorUI::Close(true); + FullscreenUI::OnSystemDestroyed(); + + InputManager::PauseVibration(); + + if (g_settings.inhibit_screensaver) + PlatformMisc::ResumeScreensaver(); + SetTimerResolutionIncreased(false); s_cpu_thread_usage = {}; @@ -1569,6 +1677,8 @@ void System::DestroySystem() void System::ClearRunningGame() { + UpdateSessionTime(s_running_game_serial); + s_running_game_serial.clear(); s_running_game_path.clear(); s_running_game_title.clear(); @@ -1580,6 +1690,10 @@ void System::ClearRunningGame() #ifdef WITH_CHEEVOS Achievements::GameChanged(s_running_game_path, nullptr); #endif + +#ifdef WITH_DISCORD_PRESENCE + UpdateDiscordPresence(false); +#endif } bool System::FastForwardToFirstFrame() @@ -1644,6 +1758,7 @@ void System::FrameDone() g_gpu->FlushRender(); // Generate any pending samples from the SPU before sleeping, this way we reduce the chances of underruns. + // TODO: when running ahead, we can skip this (and the flush above) SPU::GeneratePendingSamples(); if (s_cheat_list) @@ -1677,6 +1792,8 @@ void System::FrameDone() // *technically* this means higher input latency (by less than a frame), but runahead itself // counter-acts that. Host::PumpMessagesOnCPUThread(); + InputManager::PollSources(); + if (IsExecutionInterrupted()) { s_system_interrupted = false; @@ -1694,6 +1811,15 @@ void System::FrameDone() SaveRunaheadState(); } +#ifdef WITH_CHEEVOS + if (Achievements::IsActive()) + Achievements::FrameUpdate(); +#endif + +#ifdef WITH_DISCORD_PRESENCE + PollDiscordPresence(); +#endif + const Common::Timer::Value current_time = Common::Timer::GetCurrentValue(); if (current_time < s_next_frame_time || s_display_all_frames || s_last_frame_skipped) { @@ -1722,6 +1848,7 @@ void System::FrameDone() if (s_runahead_frames == 0) { Host::PumpMessagesOnCPUThread(); + InputManager::PollSources(); if (IsExecutionInterrupted()) { @@ -3150,8 +3277,10 @@ void System::UpdateRunningGame(const char* path, CDImage* image, bool booting) if (!booting && s_running_game_path == path) return; + const std::string prev_serial = std::move(s_running_game_serial); + s_running_game_path.clear(); - s_running_game_serial.clear(); + s_running_game_serial = {}; s_running_game_title.clear(); s_running_game_entry = nullptr; s_running_game_hash = 0; @@ -3207,6 +3336,15 @@ void System::UpdateRunningGame(const char* path, CDImage* image, bool booting) if (g_settings.auto_load_cheats && !Achievements::ChallengeModeActive()) LoadCheatListFromGameTitle(); + if (s_running_game_serial != prev_serial) + UpdateSessionTime(prev_serial); + + SaveStateSelectorUI::RefreshList(); + +#ifdef WITH_DISCORD_PRESENCE + UpdateDiscordPresence(false); +#endif + Host::OnGameChanged(s_running_game_path, s_running_game_serial, s_running_game_title); } @@ -3541,6 +3679,14 @@ void System::CheckForSettingsChanges(const Settings& old_settings) g_gpu_device->SetPostProcessingChain({}); } } + + if (g_settings.inhibit_screensaver != old_settings.inhibit_screensaver) + { + if (g_settings.inhibit_screensaver) + PlatformMisc::SuspendScreensaver(); + else + PlatformMisc::ResumeScreensaver(); + } } bool controllers_updated = false; @@ -3566,6 +3712,28 @@ void System::CheckForSettingsChanges(const Settings& old_settings) if (g_settings.multitap_mode != old_settings.multitap_mode) UpdateMultitaps(); + +#ifdef WITH_CHEEVOS + Achievements::UpdateSettings(old_settings); +#endif + + FullscreenUI::CheckForConfigChanges(old_settings); + + if (g_settings.enable_discord_presence != old_settings.enable_discord_presence) + { + if (g_settings.enable_discord_presence) + InitializeDiscordPresence(); + else + ShutdownDiscordPresence(); + } + + if (g_settings.log_level != old_settings.log_level || g_settings.log_filter != old_settings.log_filter || + g_settings.log_to_console != old_settings.log_to_console || + g_settings.log_to_debug != old_settings.log_to_debug || g_settings.log_to_window != old_settings.log_to_window || + g_settings.log_to_file != old_settings.log_to_file) + { + g_settings.UpdateLogSettings(); + } } void System::CalculateRewindMemoryUsage(u32 num_saves, u64* ram_usage, u64* vram_usage) @@ -4538,3 +4706,120 @@ void System::SetTimerResolutionIncreased(bool enabled) timeEndPeriod(1); #endif } + +void System::UpdateSessionTime(const std::string& prev_serial) +{ + const u64 ctime = Common::Timer::GetCurrentValue(); + if (!prev_serial.empty()) + { + // round up to seconds + const std::time_t etime = + static_cast(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time))); + const std::time_t wtime = std::time(nullptr); + GameList::AddPlayedTimeForSerial(prev_serial, wtime, etime); + } + + s_session_start_time = ctime; +} + +u64 System::GetSessionPlayedTime() +{ + const u64 ctime = Common::Timer::GetCurrentValue(); + return static_cast(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time))); +} + +#ifdef WITH_DISCORD_PRESENCE + +void System::InitializeDiscordPresence() +{ + if (s_discord_presence_active) + return; + + DiscordEventHandlers handlers = {}; + Discord_Initialize("705325712680288296", &handlers, 0, nullptr); + s_discord_presence_active = true; + + UpdateDiscordPresence(false); +} + +void System::ShutdownDiscordPresence() +{ + if (!s_discord_presence_active) + return; + + Discord_ClearPresence(); + Discord_Shutdown(); + s_discord_presence_active = false; +#ifdef WITH_CHEEVOS + s_discord_presence_cheevos_string.clear(); +#endif +} + +void System::UpdateDiscordPresence(bool rich_presence_only) +{ + if (!s_discord_presence_active) + return; + +#ifdef WITH_CHEEVOS + // Update only if RetroAchievements rich presence has changed + const std::string& new_rich_presence = Achievements::GetRichPresenceString(); + if (new_rich_presence == s_discord_presence_cheevos_string && rich_presence_only) + { + return; + } + s_discord_presence_cheevos_string = new_rich_presence; +#else + if (rich_presence_only) + { + return; + } +#endif + + // https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields + DiscordRichPresence rp = {}; + rp.largeImageKey = "duckstation_logo"; + rp.largeImageText = "DuckStation PS1/PSX Emulator"; + rp.startTimestamp = std::time(nullptr); + + SmallString details_string; + if (!System::IsShutdown()) + { + details_string.AppendFormattedString("%s (%s)", System::GetGameTitle().c_str(), System::GetGameSerial().c_str()); + } + else + { + details_string.AppendString("No Game Running"); + } + +#ifdef WITH_CHEEVOS + SmallString state_string; + // Trim to 128 bytes as per Discord-RPC requirements + if (s_discord_presence_cheevos_string.length() >= 128) + { + // 124 characters + 3 dots + null terminator + state_string = s_discord_presence_cheevos_string.substr(0, 124); + state_string.AppendString("..."); + } + else + { + state_string = s_discord_presence_cheevos_string; + } + + rp.state = state_string; +#endif + rp.details = details_string; + + Discord_UpdatePresence(&rp); +} + +void System::PollDiscordPresence() +{ + if (!s_discord_presence_active) + return; + + UpdateDiscordPresence(true); + + Discord_RunCallbacks(); +} + +#endif diff --git a/src/core/system.h b/src/core/system.h index ba1833b3e..c2bb8f0b9 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -194,6 +194,9 @@ GameHash GetGameHash(); bool IsRunningUnknownGame(); bool WasFastBooted(); +/// Returns the time elapsed in the current play session. +u64 GetSessionPlayedTime(); + const BIOS::ImageInfo* GetBIOSImageInfo(); const BIOS::Hash& GetBIOSHash(); @@ -459,6 +462,18 @@ void UpdateMemorySaveStateSettings(); bool LoadRewindState(u32 skip_saves = 0, bool consume_state = true); void SetRunaheadReplayFlag(); +namespace Internal +{ +/// Called on process startup. +void ProcessStartup(); + +/// Called on process shutdown. +void ProcessShutdown(); + +/// Polls input, updates subsystems which are present while paused/inactive. +void IdlePollUpdate(); +} + } // namespace System namespace Host { @@ -497,16 +512,4 @@ void RequestResizeHostDisplay(s32 width, s32 height); /// Requests shut down of the current virtual machine. void RequestSystemShutdown(bool allow_confirm, bool save_state); - -/// Attempts to create the rendering device backend. -bool CreateGPUDevice(RenderAPI api); - -/// Handles fullscreen transitions and such. -void UpdateDisplayWindow(); - -/// Called when the window is resized. -void ResizeDisplayWindow(s32 width, s32 height, float scale); - -/// Destroys any active rendering device. -void ReleaseGPUDevice(); } // namespace Host diff --git a/src/duckstation-nogui/cocoa_nogui_platform.mm b/src/duckstation-nogui/cocoa_nogui_platform.mm index fb3b0b8a1..61e81f582 100644 --- a/src/duckstation-nogui/cocoa_nogui_platform.mm +++ b/src/duckstation-nogui/cocoa_nogui_platform.mm @@ -6,7 +6,6 @@ #include "nogui_host.h" #include "core/host.h" -#include "core/host_settings.h" #include "util/cocoa_tools.h" #include "util/imgui_manager.h" @@ -28,9 +27,6 @@ constexpr NSWindowStyleMask WINDOWED_STYLE = NSWindowStyleMaskTitled | NSWindowS - (BOOL)canBecomeKeyView { return YES; } -- (void)viewDidEndLiveResize:(NSEvent *)event { - [super viewDidEndLiveResize:event]; -} - (void)mouseDown:(NSEvent *)event { NoGUIHost::ProcessPlatformMouseButtonEvent(0, true); } diff --git a/src/duckstation-nogui/nogui_host.cpp b/src/duckstation-nogui/nogui_host.cpp index 4b3272e83..1a905b459 100644 --- a/src/duckstation-nogui/nogui_host.cpp +++ b/src/duckstation-nogui/nogui_host.cpp @@ -6,13 +6,12 @@ #include "scmversion/scmversion.h" -#include "core/common_host.h" +#include "core/achievements.h" #include "core/controller.h" #include "core/fullscreen_ui.h" #include "core/game_list.h" #include "core/gpu.h" #include "core/host.h" -#include "core/host_settings.h" #include "core/imgui_overlays.h" #include "core/settings.h" #include "core/system.h" @@ -21,6 +20,7 @@ #include "util/imgui_manager.h" #include "util/ini_settings_interface.h" #include "util/input_manager.h" +#include "util/platform_misc.h" #include "imgui.h" #include "imgui_internal.h" @@ -43,10 +43,6 @@ Log_SetChannel(NoGUIHost); -#ifdef WITH_CHEEVOS -#include "core/achievements_private.h" -#endif - #ifdef _WIN32 #include "common/windows_headers.h" #include @@ -278,15 +274,15 @@ void NoGUIHost::SetDefaultSettings(SettingsInterface& si, bool system, bool cont if (system) { System::SetDefaultSettings(si); - CommonHost::SetDefaultSettings(si); EmuFolders::SetDefaults(); EmuFolders::Save(si); } if (controller) { - CommonHost::SetDefaultControllerSettings(si); - CommonHost::SetDefaultHotkeyBindings(si); + InputManager::SetDefaultSourceConfig(si); + Settings::SetDefaultControllerConfig(si); + Settings::SetDefaultHotkeyConfig(si); } g_nogui_window->SetDefaultConfig(si); @@ -384,12 +380,10 @@ std::optional Host::GetResourceFileTimestamp(const char* filename) void Host::LoadSettings(SettingsInterface& si, std::unique_lock& lock) { - CommonHost::LoadSettings(si, lock); } void Host::CheckForSettingsChanges(const Settings& old_settings) { - CommonHost::CheckForSettingsChanges(old_settings); } void Host::CommitBaseSettingChanges() @@ -614,7 +608,7 @@ void NoGUIHost::CPUThreadEntryPoint() Threading::SetNameOfCurrentThread("CPU Thread"); // input source setup must happen on emu thread - CommonHost::Initialize(); + System::Internal::ProcessStartup(); // start the fullscreen UI and get it going if (Host::CreateGPUDevice(Settings::GetRenderAPIForRenderer(g_settings.gpu_renderer)) && FullscreenUI::Initialize()) @@ -640,7 +634,7 @@ void NoGUIHost::CPUThreadEntryPoint() Host::ReleaseGPUDevice(); Host::ReleaseRenderWindow(); - CommonHost::Shutdown(); + System::Internal::ProcessShutdown(); g_nogui_window->QuitMessageLoop(); } @@ -655,6 +649,7 @@ void NoGUIHost::CPUThreadMainLoop() } Host::PumpMessagesOnCPUThread(); + System::Internal::IdlePollUpdate(); Host::RenderDisplay(false); if (!g_gpu_device->IsVsyncEnabled()) g_gpu_device->ThrottlePresentation(); @@ -708,34 +703,24 @@ void Host::ReleaseRenderWindow() void Host::OnSystemStarting() { - CommonHost::OnSystemStarting(); - Log_VerbosePrintf("Host::OnSystemStarting()"); s_save_state_on_shutdown = false; s_was_paused_by_focus_loss = false; } void Host::OnSystemStarted() { - CommonHost::OnSystemStarted(); - Log_VerbosePrintf("Host::OnSystemStarted()"); } void Host::OnSystemPaused() { - CommonHost::OnSystemPaused(); - Log_VerbosePrintf("Host::OnSystemPaused()"); } void Host::OnSystemResumed() { - CommonHost::OnSystemResumed(); - Log_VerbosePrintf("Host::OnSystemResumed()"); } void Host::OnSystemDestroyed() { - CommonHost::OnSystemDestroyed(); - Log_VerbosePrintf("Host::OnSystemDestroyed()"); } void Host::BeginPresentFrame() @@ -764,18 +749,15 @@ void Host::OnPerformanceCountersUpdated() void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name) { - CommonHost::OnGameChanged(disc_path, game_serial, game_name); Log_VerbosePrintf("Host::OnGameChanged(\"%s\", \"%s\", \"%s\")", disc_path.c_str(), game_serial.c_str(), game_name.c_str()); NoGUIHost::UpdateWindowTitle(game_name); } -#ifdef WITH_CHEEVOS void Host::OnAchievementsRefreshed() { // noop } -#endif void Host::SetMouseMode(bool relative, bool hide_cursor) { @@ -793,7 +775,6 @@ void Host::PumpMessagesOnCPUThread() { NoGUIHost::ProcessCPUThreadPlatformMessages(); NoGUIHost::ProcessCPUThreadEvents(false); - CommonHost::PumpMessagesOnCPUThread(); // calls InputManager::PollSources() } std::unique_ptr NoGUIHost::CreatePlatform() diff --git a/src/duckstation-nogui/win32_nogui_platform.cpp b/src/duckstation-nogui/win32_nogui_platform.cpp index 0e7d81e1a..3526d657a 100644 --- a/src/duckstation-nogui/win32_nogui_platform.cpp +++ b/src/duckstation-nogui/win32_nogui_platform.cpp @@ -7,7 +7,6 @@ #include "common/string_util.h" #include "common/threading.h" #include "core/host.h" -#include "core/host_settings.h" #include "util/imgui_manager.h" #include "nogui_host.h" #include "resource.h" diff --git a/src/duckstation-qt/achievementlogindialog.cpp b/src/duckstation-qt/achievementlogindialog.cpp index c0b49adb7..e966a8b3a 100644 --- a/src/duckstation-qt/achievementlogindialog.cpp +++ b/src/duckstation-qt/achievementlogindialog.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "achievementlogindialog.h" -#include "core/achievements_private.h" +#include "core/achievements.h" #include "qthost.h" #include diff --git a/src/duckstation-qt/achievementsettingswidget.cpp b/src/duckstation-qt/achievementsettingswidget.cpp index 40dae2877..aa4dae496 100644 --- a/src/duckstation-qt/achievementsettingswidget.cpp +++ b/src/duckstation-qt/achievementsettingswidget.cpp @@ -8,7 +8,7 @@ #include "settingsdialog.h" #include "settingwidgetbinder.h" -#include "core/achievements_private.h" +#include "core/achievements.h" #include "core/system.h" #include "common/string_util.h" diff --git a/src/duckstation-qt/audiosettingswidget.cpp b/src/duckstation-qt/audiosettingswidget.cpp index f8d92b053..bb6fb49f2 100644 --- a/src/duckstation-qt/audiosettingswidget.cpp +++ b/src/duckstation-qt/audiosettingswidget.cpp @@ -5,7 +5,6 @@ #include "settingsdialog.h" #include "settingwidgetbinder.h" -#include "core/common_host.h" #include "core/spu.h" #include "util/audio_stream.h" diff --git a/src/duckstation-qt/controllerbindingwidgets.cpp b/src/duckstation-qt/controllerbindingwidgets.cpp index aed88cd5a..ee57d7029 100644 --- a/src/duckstation-qt/controllerbindingwidgets.cpp +++ b/src/duckstation-qt/controllerbindingwidgets.cpp @@ -2,17 +2,21 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "controllerbindingwidgets.h" -#include "common/log.h" -#include "common/string_util.h" #include "controllersettingsdialog.h" #include "controllersettingwidgetbinder.h" -#include "core/controller.h" -#include "core/host_settings.h" -#include "util/input_manager.h" #include "qthost.h" #include "qtutils.h" #include "settingsdialog.h" #include "settingwidgetbinder.h" + +#include "core/controller.h" +#include "core/host.h" + +#include "util/input_manager.h" + +#include "common/log.h" +#include "common/string_util.h" + #include #include #include @@ -519,7 +523,9 @@ ControllerCustomSettingsWidget::ControllerCustomSettingsWidget(ControllerBinding layout->addStretch(1); } -ControllerCustomSettingsWidget::~ControllerCustomSettingsWidget() {} +ControllerCustomSettingsWidget::~ControllerCustomSettingsWidget() +{ +} void ControllerCustomSettingsWidget::createSettingWidgets(ControllerBindingWidget* parent, QWidget* parent_widget, QGridLayout* layout, const Controller::ControllerInfo* cinfo) @@ -720,9 +726,13 @@ void ControllerCustomSettingsWidget::restoreDefaults() ////////////////////////////////////////////////////////////////////////// -ControllerBindingWidget_Base::ControllerBindingWidget_Base(ControllerBindingWidget* parent) : QWidget(parent) {} +ControllerBindingWidget_Base::ControllerBindingWidget_Base(ControllerBindingWidget* parent) : QWidget(parent) +{ +} -ControllerBindingWidget_Base::~ControllerBindingWidget_Base() {} +ControllerBindingWidget_Base::~ControllerBindingWidget_Base() +{ +} QIcon ControllerBindingWidget_Base::getIcon() const { @@ -792,7 +802,9 @@ ControllerBindingWidget_DigitalController::ControllerBindingWidget_DigitalContro initBindingWidgets(); } -ControllerBindingWidget_DigitalController::~ControllerBindingWidget_DigitalController() {} +ControllerBindingWidget_DigitalController::~ControllerBindingWidget_DigitalController() +{ +} QIcon ControllerBindingWidget_DigitalController::getIcon() const { @@ -813,7 +825,9 @@ ControllerBindingWidget_AnalogController::ControllerBindingWidget_AnalogControll initBindingWidgets(); } -ControllerBindingWidget_AnalogController::~ControllerBindingWidget_AnalogController() {} +ControllerBindingWidget_AnalogController::~ControllerBindingWidget_AnalogController() +{ +} QIcon ControllerBindingWidget_AnalogController::getIcon() const { @@ -834,7 +848,9 @@ ControllerBindingWidget_AnalogJoystick::ControllerBindingWidget_AnalogJoystick(C initBindingWidgets(); } -ControllerBindingWidget_AnalogJoystick::~ControllerBindingWidget_AnalogJoystick() {} +ControllerBindingWidget_AnalogJoystick::~ControllerBindingWidget_AnalogJoystick() +{ +} QIcon ControllerBindingWidget_AnalogJoystick::getIcon() const { @@ -872,7 +888,9 @@ ControllerBindingWidget_NeGcon::ControllerBindingWidget_NeGcon(ControllerBinding } } -ControllerBindingWidget_NeGcon::~ControllerBindingWidget_NeGcon() {} +ControllerBindingWidget_NeGcon::~ControllerBindingWidget_NeGcon() +{ +} QIcon ControllerBindingWidget_NeGcon::getIcon() const { @@ -893,7 +911,9 @@ ControllerBindingWidget_GunCon::ControllerBindingWidget_GunCon(ControllerBinding initBindingWidgets(); } -ControllerBindingWidget_GunCon::~ControllerBindingWidget_GunCon() {} +ControllerBindingWidget_GunCon::~ControllerBindingWidget_GunCon() +{ +} QIcon ControllerBindingWidget_GunCon::getIcon() const { @@ -914,7 +934,9 @@ ControllerBindingWidget_Mouse::ControllerBindingWidget_Mouse(ControllerBindingWi initBindingWidgets(); } -ControllerBindingWidget_Mouse::~ControllerBindingWidget_Mouse() {} +ControllerBindingWidget_Mouse::~ControllerBindingWidget_Mouse() +{ +} QIcon ControllerBindingWidget_Mouse::getIcon() const { diff --git a/src/duckstation-qt/controllersettingsdialog.cpp b/src/duckstation-qt/controllersettingsdialog.cpp index a32c9035d..7dc6cc702 100644 --- a/src/duckstation-qt/controllersettingsdialog.cpp +++ b/src/duckstation-qt/controllersettingsdialog.cpp @@ -2,16 +2,19 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "controllersettingsdialog.h" -#include "common/assert.h" -#include "common/file_system.h" #include "controllerbindingwidgets.h" #include "controllerglobalsettingswidget.h" -#include "core/controller.h" -#include "core/host_settings.h" -#include "util/input_manager.h" #include "hotkeysettingswidget.h" #include "qthost.h" + +#include "core/controller.h" +#include "core/host.h" + #include "util/ini_settings_interface.h" +#include "util/input_manager.h" + +#include "common/assert.h" +#include "common/file_system.h" #include #include diff --git a/src/duckstation-qt/controllersettingwidgetbinder.h b/src/duckstation-qt/controllersettingwidgetbinder.h index a47d78c23..e2f7834b4 100644 --- a/src/duckstation-qt/controllersettingwidgetbinder.h +++ b/src/duckstation-qt/controllersettingwidgetbinder.h @@ -1,7 +1,12 @@ +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin +// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) + #pragma once -#include -#include +#include "qthost.h" +#include "settingwidgetbinder.h" + +#include "core/host.h" #include #include @@ -11,10 +16,8 @@ #include #include #include - -#include "core/host_settings.h" -#include "qthost.h" -#include "settingwidgetbinder.h" +#include +#include /// This nastyness is required because input profiles aren't overlaid settings like the rest of them, it's /// input profile *or* global, not both. diff --git a/src/duckstation-qt/gamelistwidget.cpp b/src/duckstation-qt/gamelistwidget.cpp index b09b324a9..d7c12fb90 100644 --- a/src/duckstation-qt/gamelistwidget.cpp +++ b/src/duckstation-qt/gamelistwidget.cpp @@ -8,7 +8,7 @@ #include "qtutils.h" #include "core/game_list.h" -#include "core/host_settings.h" +#include "core/host.h" #include "core/settings.h" #include "common/assert.h" @@ -83,7 +83,9 @@ private: QString m_filter_name; }; -GameListWidget::GameListWidget(QWidget* parent /* = nullptr */) : QWidget(parent) {} +GameListWidget::GameListWidget(QWidget* parent /* = nullptr */) : QWidget(parent) +{ +} GameListWidget::~GameListWidget() = default; @@ -585,7 +587,9 @@ const GameList::Entry* GameListWidget::getSelectedEntry() const } } -GameListGridListView::GameListGridListView(QWidget* parent /*= nullptr*/) : QListView(parent) {} +GameListGridListView::GameListGridListView(QWidget* parent /*= nullptr*/) : QListView(parent) +{ +} void GameListGridListView::wheelEvent(QWheelEvent* e) { diff --git a/src/duckstation-qt/inputbindingwidgets.cpp b/src/duckstation-qt/inputbindingwidgets.cpp index c4aceda53..3a85c71fc 100644 --- a/src/duckstation-qt/inputbindingwidgets.cpp +++ b/src/duckstation-qt/inputbindingwidgets.cpp @@ -2,12 +2,15 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "inputbindingwidgets.h" -#include "common/bitutils.h" #include "controllersettingsdialog.h" -#include "core/host_settings.h" #include "inputbindingdialog.h" #include "qthost.h" #include "qtutils.h" + +#include "core/host.h" + +#include "common/bitutils.h" + #include #include #include @@ -408,7 +411,9 @@ InputVibrationBindingWidget::InputVibrationBindingWidget(QWidget* parent, Contro setKey(dialog, std::move(section_name), std::move(key_name)); } -InputVibrationBindingWidget::~InputVibrationBindingWidget() {} +InputVibrationBindingWidget::~InputVibrationBindingWidget() +{ +} void InputVibrationBindingWidget::setKey(ControllerSettingsDialog* dialog, std::string section_name, std::string key_name) diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 78d4648d0..6381953a1 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -25,7 +25,6 @@ #include "util/cd_image.h" #include "util/gpu_device.h" -#include "util/platform_misc.h" #include "common/assert.h" #include "common/file_system.h" @@ -46,15 +45,15 @@ #include #include -#ifdef WITH_CHEEVOS -#include "core/achievements_private.h" -#endif - #ifdef _WIN32 #include "common/windows_headers.h" #include #endif +#ifdef __APPLE__ +#include "util/cocoa_tools.h" +#endif + Log_SetChannel(MainWindow); static constexpr char DISC_IMAGE_FILTER[] = QT_TRANSLATE_NOOP( @@ -65,11 +64,7 @@ static constexpr char DISC_IMAGE_FILTER[] = QT_TRANSLATE_NOOP( "(*.ecm);;Media Descriptor Sidecar Images (*.mds);;PlayStation EBOOTs (*.pbp *.PBP);;PlayStation Executables (*.exe " "*.psexe *.ps-exe);;Portable Sound Format Files (*.psf *.minipsf);;Playlists (*.m3u)"); -#ifdef __APPLE__ -const char* DEFAULT_THEME_NAME = ""; -#else const char* DEFAULT_THEME_NAME = "darkfusion"; -#endif MainWindow* g_main_window = nullptr; static QString s_unthemed_style_name; @@ -123,7 +118,7 @@ MainWindow::~MainWindow() unregisterForDeviceNotifications(); #endif #ifdef __APPLE__ - FrontendCommon::RemoveThemeChangeHandler(this); + CocoaTools::RemoveThemeChangeHandler(this); #endif } @@ -159,8 +154,8 @@ void MainWindow::initialize() #endif #ifdef __APPLE__ - FrontendCommon::AddThemeChangeHandler(this, - [](void* ctx) { QtHost::RunOnUIThread([] { g_main_window->updateTheme(); }); }); + CocoaTools::AddThemeChangeHandler(this, + [](void* ctx) { QtHost::RunOnUIThread([] { g_main_window->updateTheme(); }); }); #endif } diff --git a/src/duckstation-qt/postprocessingchainconfigwidget.h b/src/duckstation-qt/postprocessingchainconfigwidget.h index 1b90984f5..e3b3e65bb 100644 --- a/src/duckstation-qt/postprocessingchainconfigwidget.h +++ b/src/duckstation-qt/postprocessingchainconfigwidget.h @@ -13,7 +13,7 @@ #include #include -namespace FrontendCommon { +namespace PlatformMisc { class PostProcessingChain; } diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 1d2d79752..f184be96d 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -7,6 +7,7 @@ #include "qtprogresscallback.h" #include "qtutils.h" +#include "core/achievements.h" #include "core/cheats.h" #include "core/controller.h" #include "core/fullscreen_ui.h" @@ -14,7 +15,6 @@ #include "core/game_list.h" #include "core/gpu.h" #include "core/host.h" -#include "core/host_settings.h" #include "core/imgui_overlays.h" #include "core/memory_card.h" #include "core/spu.h" @@ -32,6 +32,7 @@ #include "util/imgui_manager.h" #include "util/ini_settings_interface.h" #include "util/input_manager.h" +#include "util/platform_misc.h" #include "scmversion/scmversion.h" @@ -62,10 +63,6 @@ Log_SetChannel(QtHost); #include #endif -#ifdef WITH_CHEEVOS -#include "core/achievements_private.h" -#endif - static constexpr u32 SETTINGS_VERSION = 3; static constexpr u32 SETTINGS_SAVE_DELAY = 1000; @@ -321,7 +318,6 @@ void QtHost::SetDataDirectory() void Host::LoadSettings(SettingsInterface& si, std::unique_lock& lock) { - CommonHost::LoadSettings(si, lock); g_emu_thread->loadSettings(si); } @@ -358,7 +354,6 @@ void EmuThread::checkForSettingsChanges(const Settings& old_settings) void Host::CheckForSettingsChanges(const Settings& old_settings) { - CommonHost::CheckForSettingsChanges(old_settings); g_emu_thread->checkForSettingsChanges(old_settings); } @@ -385,15 +380,15 @@ void QtHost::SetDefaultSettings(SettingsInterface& si, bool system, bool control if (system) { System::SetDefaultSettings(si); - CommonHost::SetDefaultSettings(si); EmuFolders::SetDefaults(); EmuFolders::Save(si); } if (controller) { - CommonHost::SetDefaultControllerSettings(si); - CommonHost::SetDefaultHotkeyBindings(si); + InputManager::SetDefaultSourceConfig(si); + Settings::SetDefaultControllerConfig(si); + Settings::SetDefaultHotkeyConfig(si); } } @@ -745,15 +740,11 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget) void Host::OnSystemStarting() { - CommonHost::OnSystemStarting(); - emit g_emu_thread->systemStarting(); } void Host::OnSystemStarted() { - CommonHost::OnSystemStarted(); - g_emu_thread->wakeThread(); g_emu_thread->stopBackgroundControllerPollTimer(); @@ -762,8 +753,6 @@ void Host::OnSystemStarted() void Host::OnSystemPaused() { - CommonHost::OnSystemPaused(); - emit g_emu_thread->systemPaused(); g_emu_thread->startBackgroundControllerPollTimer(); Host::InvalidateDisplay(); @@ -771,8 +760,6 @@ void Host::OnSystemPaused() void Host::OnSystemResumed() { - CommonHost::OnSystemResumed(); - // if we were surfaceless (view->game list, system->unpause), get our display widget back if (g_emu_thread->isSurfaceless()) g_emu_thread->setSurfaceless(false); @@ -785,8 +772,6 @@ void Host::OnSystemResumed() void Host::OnSystemDestroyed() { - CommonHost::OnSystemDestroyed(); - g_emu_thread->resetPerformanceCounters(); g_emu_thread->startBackgroundControllerPollTimer(); emit g_emu_thread->systemDestroyed(); @@ -1227,10 +1212,9 @@ void EmuThread::saveScreenshot() System::SaveScreenshot(nullptr, true, true); } -#ifdef WITH_CHEEVOS - void Host::OnAchievementsRefreshed() { +#ifdef WITH_CHEEVOS u32 game_id = 0; u32 achievement_count = 0; u32 max_points = 0; @@ -1264,18 +1248,19 @@ void Host::OnAchievementsRefreshed() } emit g_emu_thread->achievementsRefreshed(game_id, game_info, achievement_count, max_points); +#endif } void Host::OnAchievementsChallengeModeChanged() { +#ifdef WITH_CHEEVOS emit g_emu_thread->achievementsChallengeModeChanged(); -} - #endif +} void EmuThread::doBackgroundControllerPoll() { - InputManager::PollSources(); + System::Internal::IdlePollUpdate(); } void EmuThread::createBackgroundControllerPollTimer() @@ -1346,7 +1331,7 @@ void EmuThread::run() m_started_semaphore.release(); // input source setup must happen on emu thread - CommonHost::Initialize(); + System::Internal::ProcessStartup(); // bind buttons/axises createBackgroundControllerPollTimer(); @@ -1370,7 +1355,7 @@ void EmuThread::run() } m_event_loop->processEvents(QEventLoop::AllEvents); - CommonHost::PumpMessagesOnCPUThread(); + System::Internal::IdlePollUpdate(); if (g_gpu_device) { Host::RenderDisplay(false); @@ -1384,7 +1369,7 @@ void EmuThread::run() System::ShutdownSystem(false); destroyBackgroundControllerPollTimer(); - CommonHost::Shutdown(); + System::Internal::ProcessShutdown(); // move back to UI thread moveToThread(m_ui_thread); @@ -1585,8 +1570,6 @@ void Host::OnPerformanceCountersUpdated() void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name) { - CommonHost::OnGameChanged(disc_path, game_serial, game_name); - emit g_emu_thread->runningGameChanged(QString::fromStdString(disc_path), QString::fromStdString(game_serial), QString::fromStdString(game_name)); } @@ -1606,7 +1589,6 @@ void Host::SetMouseMode(bool relative, bool hide_cursor) void Host::PumpMessagesOnCPUThread() { g_emu_thread->getEventLoop()->processEvents(QEventLoop::AllEvents); - CommonHost::PumpMessagesOnCPUThread(); // calls InputManager::PollSources() } void QtHost::SaveSettings() diff --git a/src/duckstation-qt/qthost.h b/src/duckstation-qt/qthost.h index db70915bd..7a8ef3611 100644 --- a/src/duckstation-qt/qthost.h +++ b/src/duckstation-qt/qthost.h @@ -6,12 +6,10 @@ #include "gdbserver.h" #include "qtutils.h" +#include "core/game_list.h" #include "core/host.h" -#include "core/host_settings.h" #include "core/system.h" #include "core/types.h" -#include "core/common_host.h" -#include "core/game_list.h" #include "util/gpu_device.h" #include "util/input_manager.h" diff --git a/src/duckstation-qt/settingsdialog.cpp b/src/duckstation-qt/settingsdialog.cpp index d4bab9722..aa7adebb6 100644 --- a/src/duckstation-qt/settingsdialog.cpp +++ b/src/duckstation-qt/settingsdialog.cpp @@ -20,7 +20,6 @@ #include "qthost.h" #include "core/host.h" -#include "core/host_settings.h" #include "util/ini_settings_interface.h" @@ -32,7 +31,7 @@ #ifdef WITH_CHEEVOS #include "achievementsettingswidget.h" -#include "core/achievements_private.h" +#include "core/achievements.h" #endif static QList s_open_game_properties_dialogs; diff --git a/src/duckstation-qt/settingwidgetbinder.h b/src/duckstation-qt/settingwidgetbinder.h index b85a5bc2a..8f2a61c9e 100644 --- a/src/duckstation-qt/settingwidgetbinder.h +++ b/src/duckstation-qt/settingwidgetbinder.h @@ -1,10 +1,17 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once -#include -#include +#include "qthost.h" +#include "qtutils.h" +#include "settingsdialog.h" + +#include "core/host.h" +#include "core/settings.h" + +#include "common/assert.h" +#include "common/path.h" #include #include @@ -17,15 +24,8 @@ #include #include #include - -#include "common/assert.h" -#include "common/path.h" -#include "core/host_settings.h" -#include "core/settings.h" - -#include "qthost.h" -#include "qtutils.h" -#include "settingsdialog.h" +#include +#include namespace SettingWidgetBinder { static constexpr const char* NULLABLE_PROPERTY = "SettingWidgetBinder_isNullable"; diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index e1699a751..e428a978b 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -1,6 +1,18 @@ // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) +#include "core/achievements.h" +#include "core/game_list.h" +#include "core/host.h" +#include "core/system.h" + +#include "scmversion/scmversion.h" + +#include "util/gpu_device.h" +#include "util/imgui_manager.h" +#include "util/input_manager.h" +#include "util/platform_misc.h" + #include "common/assert.h" #include "common/crash_handler.h" #include "common/file_system.h" @@ -8,22 +20,11 @@ #include "common/memory_settings_interface.h" #include "common/path.h" #include "common/string_util.h" -#include "core/common_host.h" -#include "core/game_list.h" -#include "core/host.h" -#include "core/host_settings.h" -#include "core/system.h" -#include "scmversion/scmversion.h" -#include "util/gpu_device.h" -#include "util/imgui_manager.h" -#include "util/input_manager.h" + #include #include -Log_SetChannel(RegTestHost); -#ifdef WITH_CHEEVOS -#include "core/achievements_private.h" -#endif +Log_SetChannel(RegTestHost); namespace RegTestHost { static bool ParseCommandLineParameters(int argc, char* argv[], std::optional& autoboot); @@ -157,12 +158,10 @@ s32 Host::Internal::GetTranslatedStringImpl(const std::string_view& context, con void Host::LoadSettings(SettingsInterface& si, std::unique_lock& lock) { - CommonHost::LoadSettings(si, lock); } void Host::CheckForSettingsChanges(const Settings& old_settings) { - CommonHost::CheckForSettingsChanges(old_settings); } void Host::CommitBaseSettingChanges() diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index e2f9c4ed4..f81ebd1ef 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -232,7 +232,6 @@ if(WIN32) elseif(APPLE) target_sources(util PRIVATE cocoa_tools.h - cocoa_tools.mm metal_device.h metal_device.mm metal_stream_buffer.h diff --git a/src/util/cocoa_tools.h b/src/util/cocoa_tools.h index 5955a5c90..cd4b5436c 100644 --- a/src/util/cocoa_tools.h +++ b/src/util/cocoa_tools.h @@ -3,9 +3,23 @@ #include -#include +struct WindowInfo; + +#ifdef __OBJC__ +#import +#import namespace CocoaTools { NSString* StringViewToNSString(const std::string_view& str); } +#endif + +namespace CocoaTools { + /// Add a handler to be run when macOS changes between dark and light themes + void AddThemeChangeHandler(void* ctx, void(handler)(void* ctx)); + + /// Remove a handler previously added using AddThemeChangeHandler with the given context + void RemoveThemeChangeHandler(void* ctx); +} + diff --git a/src/util/cocoa_tools.mm b/src/util/cocoa_tools.mm deleted file mode 100644 index 0464349ac..000000000 --- a/src/util/cocoa_tools.mm +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#include "cocoa_tools.h" - -NSString* CocoaTools::StringViewToNSString(const std::string_view& str) -{ - if (str.empty()) - return nil; - - return [[[NSString alloc] initWithBytes:str.data() - length:static_cast(str.length()) - encoding:NSUTF8StringEncoding] autorelease]; -} - diff --git a/src/util/d3d11_device.cpp b/src/util/d3d11_device.cpp index 3c3cbb480..869bd71b9 100644 --- a/src/util/d3d11_device.cpp +++ b/src/util/d3d11_device.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "d3d11_device.h" -#include "core/host_settings.h" // TODO: Remove me +#include "core/host.h" // TODO: Remove me #include "d3d11_pipeline.h" #include "d3d11_texture.h" #include "d3d_common.h" diff --git a/src/util/dinput_source.cpp b/src/util/dinput_source.cpp index 0fcc5071a..9a9f3b461 100644 --- a/src/util/dinput_source.cpp +++ b/src/util/dinput_source.cpp @@ -4,13 +4,16 @@ #define INITGUID #include "dinput_source.h" +#include "input_manager.h" +#include "platform_misc.h" + #include "common/assert.h" #include "common/log.h" #include "common/make_array.h" #include "common/string_util.h" -#include "core/host.h" + #include "fmt/format.h" -#include "input_manager.h" + #include #include Log_SetChannel(DInputSource); diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 1c5e2aca9..dbedc9e9a 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "gpu_device.h" -#include "core/host_settings.h" +#include "core/host.h" #include "core/settings.h" #include "core/system.h" #include "postprocessing_chain.h" diff --git a/src/util/input_manager.cpp b/src/util/input_manager.cpp index 5e48982b0..a12f48212 100644 --- a/src/util/input_manager.cpp +++ b/src/util/input_manager.cpp @@ -1071,7 +1071,7 @@ bool InputManager::HasPointerAxisBinds() return false; } -void InputManager::SetDefaultConfig(SettingsInterface& si) +void InputManager::SetDefaultSourceConfig(SettingsInterface& si) { si.ClearSection("InputSources"); si.SetBoolValue("InputSources", "SDL", true); diff --git a/src/util/input_manager.h b/src/util/input_manager.h index 642bf4dbe..8c621ebac 100644 --- a/src/util/input_manager.h +++ b/src/util/input_manager.h @@ -319,7 +319,7 @@ bool IsUsingRawInput(); bool HasPointerAxisBinds(); /// Restores default configuration. -void SetDefaultConfig(SettingsInterface& si); +void SetDefaultSourceConfig(SettingsInterface& si); /// Clears all bindings for a given port. void ClearPortBindings(SettingsInterface& si, u32 port); @@ -343,9 +343,6 @@ void OnInputDeviceDisconnected(const std::string_view& identifier); } // namespace InputManager namespace Host { -/// Return the current window handle. Needed for DInput. -std::optional GetTopLevelWindowInfo(); - /// Called when a new input device is connected. void OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name); diff --git a/src/util/metal_device.mm b/src/util/metal_device.mm index f6874299c..36b4ffeda 100644 --- a/src/util/metal_device.mm +++ b/src/util/metal_device.mm @@ -2,7 +2,6 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "metal_device.h" -#include "core/host_settings.h" #include "spirv_compiler.h" #include "common/align.h" diff --git a/src/util/platform_misc.h b/src/util/platform_misc.h index 2fe9e3c5c..69e64bded 100644 --- a/src/util/platform_misc.h +++ b/src/util/platform_misc.h @@ -1,18 +1,20 @@ // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) -namespace FrontendCommon { +#include "window_info.h" + +#include + +namespace PlatformMisc { void SuspendScreensaver(); void ResumeScreensaver(); /// Abstracts platform-specific code for asynchronously playing a sound. /// On Windows, this will use PlaySound(). On Linux, it will shell out to aplay. On MacOS, it uses NSSound. bool PlaySoundAsync(const char* path); +} // namespace PlatformMisc -#ifdef __APPLE__ -/// Add a handler to be run when macOS changes between dark and light themes -void AddThemeChangeHandler(void* ctx, void(handler)(void* ctx)); -/// Remove a handler previously added using AddThemeChangeHandler with the given context -void RemoveThemeChangeHandler(void* ctx); -#endif -} // namespace FrontendCommon +namespace Host { +/// Return the current window handle. Needed for DInput. +std::optional GetTopLevelWindowInfo(); +} // namespace Host \ No newline at end of file diff --git a/src/util/platform_misc_mac.mm b/src/util/platform_misc_mac.mm index efe510a03..57d2b08b8 100644 --- a/src/util/platform_misc_mac.mm +++ b/src/util/platform_misc_mac.mm @@ -2,16 +2,23 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "platform_misc.h" +#include "window_info.h" +#include "cocoa_tools.h" + #include "common/log.h" #include "common/string.h" + #include #include #include #include #include -Log_SetChannel(FrontendCommon); -#import +Log_SetChannel(PlatformMisc); + +#if __has_feature(objc_arc) +#error ARC should not be enabled. +#endif static IOPMAssertionID s_prevent_idle_assertion = kIOPMNullAssertionID; @@ -39,7 +46,7 @@ static bool SetScreensaverInhibitMacOS(bool inhibit) static bool s_screensaver_suspended; -void FrontendCommon::SuspendScreensaver() +void PlatformMisc::SuspendScreensaver() { if (s_screensaver_suspended) @@ -52,7 +59,7 @@ void FrontendCommon::SuspendScreensaver() s_screensaver_suspended = true; } -void FrontendCommon::ResumeScreensaver() +void PlatformMisc::ResumeScreensaver() { if (!s_screensaver_suspended) return; @@ -63,7 +70,7 @@ void FrontendCommon::ResumeScreensaver() s_screensaver_suspended = false; } -bool FrontendCommon::PlaySoundAsync(const char* path) +bool PlatformMisc::PlaySoundAsync(const char* path) { NSString* nspath = [[NSString alloc] initWithUTF8String:path]; NSSound* sound = [[NSSound alloc] initWithContentsOfFile:nspath byReference:YES]; @@ -73,6 +80,16 @@ bool FrontendCommon::PlaySoundAsync(const char* path) return result; } +NSString* CocoaTools::StringViewToNSString(const std::string_view& str) +{ + if (str.empty()) + return nil; + + return [[[NSString alloc] initWithBytes:str.data() + length:static_cast(str.length()) + encoding:NSUTF8StringEncoding] autorelease]; +} + // From https://github.com/PCSX2/pcsx2/blob/1b673d9dd0829a48f5f0b6604c1de2108e981399/common/CocoaTools.mm @interface PCSX2KVOHelper : NSObject @@ -110,7 +127,7 @@ bool FrontendCommon::PlaySoundAsync(const char* path) static PCSX2KVOHelper* s_themeChangeHandler; -void FrontendCommon::AddThemeChangeHandler(void* ctx, void(handler)(void* ctx)) +void CocoaTools::AddThemeChangeHandler(void* ctx, void(handler)(void* ctx)) { assert([NSThread isMainThread]); if (!s_themeChangeHandler) @@ -125,7 +142,7 @@ void FrontendCommon::AddThemeChangeHandler(void* ctx, void(handler)(void* ctx)) [s_themeChangeHandler addCallback:ctx run:handler]; } -void FrontendCommon::RemoveThemeChangeHandler(void* ctx) +void CocoaTools::RemoveThemeChangeHandler(void* ctx) { assert([NSThread isMainThread]); [s_themeChangeHandler removeCallback:ctx]; diff --git a/src/util/platform_misc_unix.cpp b/src/util/platform_misc_unix.cpp index c9dd0ad57..ffce1e54c 100644 --- a/src/util/platform_misc_unix.cpp +++ b/src/util/platform_misc_unix.cpp @@ -7,7 +7,7 @@ #include "input_manager.h" #include "platform_misc.h" #include -Log_SetChannel(FrontendCommon); +Log_SetChannel(PlatformMisc); #include #include @@ -146,7 +146,7 @@ static bool SetScreensaverInhibit(bool inhibit) static bool s_screensaver_suspended; -void FrontendCommon::SuspendScreensaver() +void PlatformMisc::SuspendScreensaver() { if (s_screensaver_suspended) return; @@ -160,7 +160,7 @@ void FrontendCommon::SuspendScreensaver() s_screensaver_suspended = true; } -void FrontendCommon::ResumeScreensaver() +void PlatformMisc::ResumeScreensaver() { if (!s_screensaver_suspended) return; @@ -171,7 +171,7 @@ void FrontendCommon::ResumeScreensaver() s_screensaver_suspended = false; } -bool FrontendCommon::PlaySoundAsync(const char* path) +bool PlatformMisc::PlaySoundAsync(const char* path) { #ifdef __linux__ // This is... pretty awful. But I can't think of a better way without linking to e.g. gstreamer. diff --git a/src/util/platform_misc_win32.cpp b/src/util/platform_misc_win32.cpp index ad0c099b0..495d34107 100644 --- a/src/util/platform_misc_win32.cpp +++ b/src/util/platform_misc_win32.cpp @@ -6,7 +6,7 @@ #include "common/string_util.h" #include "platform_misc.h" #include -Log_SetChannel(FrontendCommon); +Log_SetChannel(PlatformMisc); #include "common/windows_headers.h" #include @@ -24,7 +24,7 @@ static bool SetScreensaverInhibitWin32(bool inhibit) static bool s_screensaver_suspended; -void FrontendCommon::SuspendScreensaver() +void PlatformMisc::SuspendScreensaver() { if (s_screensaver_suspended) return; @@ -38,7 +38,7 @@ void FrontendCommon::SuspendScreensaver() s_screensaver_suspended = true; } -void FrontendCommon::ResumeScreensaver() +void PlatformMisc::ResumeScreensaver() { if (!s_screensaver_suspended) return; @@ -49,7 +49,7 @@ void FrontendCommon::ResumeScreensaver() s_screensaver_suspended = false; } -bool FrontendCommon::PlaySoundAsync(const char* path) +bool PlatformMisc::PlaySoundAsync(const char* path) { const std::wstring wpath(StringUtil::UTF8StringToWideString(path)); return PlaySoundW(wpath.c_str(), NULL, SND_ASYNC | SND_NODEFAULT); diff --git a/src/util/sdl_input_source.cpp b/src/util/sdl_input_source.cpp index d8d7eeb0f..6ce5c170f 100644 --- a/src/util/sdl_input_source.cpp +++ b/src/util/sdl_input_source.cpp @@ -2,17 +2,21 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "sdl_input_source.h" +#include "input_manager.h" + +#include "core/host.h" + #include "common/assert.h" #include "common/bitutils.h" #include "common/log.h" #include "common/string_util.h" -#include "core/host.h" -#include "core/host_settings.h" -#include "input_manager.h" + #include + #ifdef __APPLE__ #include #endif + Log_SetChannel(SDLInputSource); static constexpr const char* s_sdl_axis_names[] = {