diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index a4fd3b4ed..aaddad28d 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -1913,7 +1913,18 @@ void CDROM::UpdatePhysicalPosition(bool update_logical) const u32 ticks = TimingEvents::GetGlobalTickCounter(); if (IsSeeking() || IsReadingOrPlaying() || !m_secondary_status.motor_on) { - // set by the event + // If we're seeking+reading the first sector (no stat bits set), we need to return the set/current lba, not the last + // physical LBA. Failing to do so may result in a track-jumped position getting returned in GetlocP, which causes + // Mad Panic Coaster to go into a seek+play loop. + if ((m_secondary_status.bits & (STAT_READING | STAT_PLAYING_CDDA | STAT_MOTOR_ON)) == STAT_MOTOR_ON && + m_current_lba != m_physical_lba) + { + Log_WarningPrintf("Jumping to hold position [%u->%u] while %s first sector", m_physical_lba, m_current_lba, + (m_drive_state == DriveState::Reading) ? "reading" : "playing"); + SetHoldPosition(m_current_lba, true); + } + + // Otherwise, this gets updated by the read event. return; } diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index d0f25fe4f..efb9bbf0c 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -456,25 +456,6 @@ bool HostInterface::SaveState(const char* filename) return result; } -void HostInterface::OnSystemCreated() {} - -void HostInterface::OnSystemPaused(bool paused) {} - -void HostInterface::OnSystemDestroyed() {} - -void HostInterface::OnSystemPerformanceCountersUpdated() {} - -void HostInterface::OnDisplayInvalidated() {} - -void HostInterface::OnSystemStateSaved(bool global, s32 slot) {} - -void HostInterface::OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code, - const std::string& game_title) -{ -} - -void HostInterface::OnControllerTypeChanged(u32 slot) {} - std::string HostInterface::GetShaderCacheBasePath() const { return GetUserDirectoryRelativePath("cache/"); @@ -1197,13 +1178,3 @@ void HostInterface::RecreateSystem() System::ResetThrottler(); OnDisplayInvalidated(); } - -void HostInterface::SetMouseMode(bool relative, bool hide_cursor) {} - -void HostInterface::DisplayLoadingScreen(const char* message, int progress_min /*= -1*/, int progress_max /*= -1*/, - int progress_value /*= -1*/) -{ - Log_InfoPrintf("Loading: %s %d of %d-%d", message, progress_value, progress_min, progress_max); -} - -void HostInterface::GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) {} diff --git a/src/core/host_interface.h b/src/core/host_interface.h index 0b03a90f8..bf606b99e 100644 --- a/src/core/host_interface.h +++ b/src/core/host_interface.h @@ -88,10 +88,10 @@ public: /// Displays a loading screen with the logo, rendered with ImGui. Use when executing possibly-time-consuming tasks /// such as compiling shaders when starting up. virtual void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1, - int progress_value = -1); + int progress_value = -1) = 0; /// Retrieves information about specified game from game list. - virtual void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title); + virtual void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) = 0; /// Returns the directory where per-game memory cards will be saved. virtual std::string GetMemoryCardDirectory() const; @@ -147,11 +147,11 @@ public: virtual std::unique_ptr OpenPackageFile(const char* path, u32 flags) = 0; virtual void OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code, - const std::string& game_title); - virtual void OnSystemPerformanceCountersUpdated(); + const std::string& game_title) = 0; + virtual void OnSystemPerformanceCountersUpdated() = 0; /// Called when the display is invalidated (e.g. a state is loaded). - virtual void OnDisplayInvalidated(); + virtual void OnDisplayInvalidated() = 0; protected: virtual bool AcquireHostDisplay() = 0; @@ -159,11 +159,10 @@ protected: virtual std::unique_ptr CreateAudioStream(AudioBackend backend) = 0; virtual s32 GetAudioOutputVolume() const; - virtual void OnSystemCreated(); - virtual void OnSystemPaused(bool paused); - virtual void OnSystemDestroyed(); - virtual void OnSystemStateSaved(bool global, s32 slot); - virtual void OnControllerTypeChanged(u32 slot); + virtual void OnSystemCreated() = 0; + virtual void OnSystemPaused(bool paused) = 0; + virtual void OnSystemDestroyed() = 0; + virtual void OnControllerTypeChanged(u32 slot) = 0; /// Restores all settings to defaults. virtual void SetDefaultSettings(SettingsInterface& si); @@ -184,7 +183,7 @@ protected: virtual void RecreateSystem(); /// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates. - virtual void SetMouseMode(bool relative, bool hide_cursor); + virtual void SetMouseMode(bool relative, bool hide_cursor) = 0; /// Call when host display size changes, use with "match display" aspect ratio setting. virtual void OnHostDisplayResized(); diff --git a/src/duckstation-nogui/nogui_host_interface.cpp b/src/duckstation-nogui/nogui_host_interface.cpp index 638af4eaa..403be7490 100644 --- a/src/duckstation-nogui/nogui_host_interface.cpp +++ b/src/duckstation-nogui/nogui_host_interface.cpp @@ -89,6 +89,10 @@ void NoGUIHostInterface::SetDefaultSettings(SettingsInterface& si) si.SetStringValue("Hotkeys", "OpenQuickMenu", "Keyboard/Escape"); } +void NoGUIHostInterface::OnDisplayInvalidated() {} + +void NoGUIHostInterface::OnSystemPerformanceCountersUpdated() {} + bool NoGUIHostInterface::CreateDisplay(bool fullscreen) { std::optional wi = GetPlatformWindowInfo(); diff --git a/src/duckstation-nogui/nogui_host_interface.h b/src/duckstation-nogui/nogui_host_interface.h index cfda03ff2..a2a01222e 100644 --- a/src/duckstation-nogui/nogui_host_interface.h +++ b/src/duckstation-nogui/nogui_host_interface.h @@ -31,6 +31,9 @@ public: void RunLater(std::function callback) override; + virtual void OnDisplayInvalidated() override; + virtual void OnSystemPerformanceCountersUpdated() override; + protected: enum : u32 { diff --git a/src/duckstation-nogui/sdl_host_interface.cpp b/src/duckstation-nogui/sdl_host_interface.cpp index ccd935f57..37f1a4ca3 100644 --- a/src/duckstation-nogui/sdl_host_interface.cpp +++ b/src/duckstation-nogui/sdl_host_interface.cpp @@ -260,6 +260,8 @@ std::optional SDLHostInterface::GetHostKeyCode return static_cast(*code); } +void SDLHostInterface::SetMouseMode(bool relative, bool hide_cursor) {} + void SDLHostInterface::PollAndUpdate() { // Process SDL events before the controller interface can steal them. diff --git a/src/duckstation-nogui/sdl_host_interface.h b/src/duckstation-nogui/sdl_host_interface.h index 6eece50bb..7ac5dbdae 100644 --- a/src/duckstation-nogui/sdl_host_interface.h +++ b/src/duckstation-nogui/sdl_host_interface.h @@ -21,6 +21,8 @@ public: bool SetFullscreen(bool enabled) override; protected: + void SetMouseMode(bool relative, bool hide_cursor) override; + void PollAndUpdate() override; std::optional GetHostKeyCode(const std::string_view key_code) const override; diff --git a/src/duckstation-nogui/vty_host_interface.cpp b/src/duckstation-nogui/vty_host_interface.cpp index aa753e7d1..9b7b5a239 100644 --- a/src/duckstation-nogui/vty_host_interface.cpp +++ b/src/duckstation-nogui/vty_host_interface.cpp @@ -111,6 +111,8 @@ void VTYHostInterface::PollAndUpdate() NoGUIHostInterface::PollAndUpdate(); } +void VTYHostInterface::SetMouseMode(bool relative, bool hide_cursor) {} + void VTYHostInterface::OpenEVDevFDs() { for (int i = 0; i < 1000; i++) diff --git a/src/duckstation-nogui/vty_host_interface.h b/src/duckstation-nogui/vty_host_interface.h index e18841e1a..169d665ae 100644 --- a/src/duckstation-nogui/vty_host_interface.h +++ b/src/duckstation-nogui/vty_host_interface.h @@ -29,6 +29,8 @@ protected: void PollAndUpdate() override; + void SetMouseMode(bool relative, bool hide_cursor) override; + private: static void SIGTERMHandler(int sig); diff --git a/src/duckstation-nogui/win32_host_interface.cpp b/src/duckstation-nogui/win32_host_interface.cpp index 27ebe9eec..51f99d483 100644 --- a/src/duckstation-nogui/win32_host_interface.cpp +++ b/src/duckstation-nogui/win32_host_interface.cpp @@ -57,6 +57,8 @@ bool Win32HostInterface::RegisterWindowClass() return true; } +void Win32HostInterface::SetMouseMode(bool relative, bool hide_cursor) {} + bool Win32HostInterface::CreatePlatformWindow() { m_hwnd = CreateWindowExW(WS_EX_CLIENTEDGE, WINDOW_CLASS_NAME, L"DuckStation", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, diff --git a/src/duckstation-nogui/win32_host_interface.h b/src/duckstation-nogui/win32_host_interface.h index c25a067ec..86bc60cb4 100644 --- a/src/duckstation-nogui/win32_host_interface.h +++ b/src/duckstation-nogui/win32_host_interface.h @@ -16,6 +16,8 @@ public: static std::unique_ptr Create(); protected: + void SetMouseMode(bool relative, bool hide_cursor) override; + bool CreatePlatformWindow() override; void DestroyPlatformWindow() override; std::optional GetPlatformWindowInfo() override; diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 80522783b..b43fb1317 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -784,8 +784,6 @@ void QtHostInterface::OnSystemDestroyed() void QtHostInterface::OnSystemPerformanceCountersUpdated() { - HostInterface::OnSystemPerformanceCountersUpdated(); - GPURenderer renderer = GPURenderer::Count; u32 render_width = 0; u32 render_height = 0; diff --git a/src/duckstation-regtest/regtest_host_interface.cpp b/src/duckstation-regtest/regtest_host_interface.cpp index d38b589f6..8e8bce643 100644 --- a/src/duckstation-regtest/regtest_host_interface.cpp +++ b/src/duckstation-regtest/regtest_host_interface.cpp @@ -104,8 +104,6 @@ void RegTestHostInterface::GetGameInfo(const char* path, CDImage* image, std::st void RegTestHostInterface::OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code, const std::string& game_title) { - HostInterface::OnRunningGameChanged(path, image, game_code, game_title); - Log_InfoPrintf("Game Path: %s", path.c_str()); Log_InfoPrintf("Game Code: %s", game_code.c_str()); Log_InfoPrintf("Game Title: %s", game_title.c_str()); @@ -128,6 +126,10 @@ void RegTestHostInterface::OnRunningGameChanged(const std::string& path, CDImage UpdateSettings(); } +void RegTestHostInterface::OnSystemPerformanceCountersUpdated() {} + +void RegTestHostInterface::OnDisplayInvalidated() {} + std::string RegTestHostInterface::GetStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/) { @@ -284,6 +286,16 @@ std::unique_ptr RegTestHostInterface::CreateAudioStream(AudioBacken return AudioStream::CreateNullAudioStream(); } +void RegTestHostInterface::OnSystemCreated() {} + +void RegTestHostInterface::OnSystemPaused(bool paused) {} + +void RegTestHostInterface::OnSystemDestroyed() {} + +void RegTestHostInterface::OnControllerTypeChanged(u32 slot) {} + +void RegTestHostInterface::SetMouseMode(bool relative, bool hide_cursor) {} + static void PrintCommandLineVersion() { const bool was_console_enabled = Log::IsConsoleOutputEnabled(); diff --git a/src/duckstation-regtest/regtest_host_interface.h b/src/duckstation-regtest/regtest_host_interface.h index b2e98c6c8..cb5626b68 100644 --- a/src/duckstation-regtest/regtest_host_interface.h +++ b/src/duckstation-regtest/regtest_host_interface.h @@ -2,7 +2,7 @@ #include "core/host_interface.h" #include "regtest_settings_interface.h" -class RegTestHostInterface : public HostInterface +class RegTestHostInterface final : public HostInterface { public: RegTestHostInterface(); @@ -34,12 +34,22 @@ public: std::unique_ptr OpenPackageFile(const char* path, u32 flags) override; + void OnSystemPerformanceCountersUpdated() override; + void OnDisplayInvalidated() override; + protected: bool AcquireHostDisplay() override; void ReleaseHostDisplay() override; std::unique_ptr CreateAudioStream(AudioBackend backend) override; + void OnSystemCreated() override; + void OnSystemPaused(bool paused) override; + void OnSystemDestroyed() override; + void OnControllerTypeChanged(u32 slot) override; + + void SetMouseMode(bool relative, bool hide_cursor) override; + private: void LoadGameSettingsDatabase(); void InitializeSettings(); diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index 400328acf..1c32a6d32 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -840,11 +840,7 @@ bool CommonHostInterface::SaveState(bool global, s32 slot) std::string save_path = global ? GetGlobalSaveStateFileName(slot) : GetGameSaveStateFileName(code.c_str(), slot); RenameCurrentSaveStateToBackup(save_path.c_str()); - if (!SaveState(save_path.c_str())) - return false; - - OnSystemStateSaved(global, slot); - return true; + return SaveState(save_path.c_str()); } bool CommonHostInterface::CanResumeSystemFromFile(const char* filename) @@ -1090,8 +1086,6 @@ void CommonHostInterface::SetUserDirectory() void CommonHostInterface::OnSystemCreated() { - HostInterface::OnSystemCreated(); - if (m_fullscreen_ui_enabled) FullscreenUI::SystemCreated(); @@ -1127,8 +1121,6 @@ void CommonHostInterface::OnSystemDestroyed() if (m_display) m_display->SetDisplayMaxFPS(0.0f); - HostInterface::OnSystemDestroyed(); - if (m_fullscreen_ui_enabled) FullscreenUI::SystemDestroyed(); @@ -1139,8 +1131,6 @@ void CommonHostInterface::OnSystemDestroyed() void CommonHostInterface::OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code, const std::string& game_title) { - HostInterface::OnRunningGameChanged(path, image, game_code, game_title); - if (g_settings.apply_game_settings) ApplySettings(true); @@ -1166,8 +1156,6 @@ void CommonHostInterface::OnRunningGameChanged(const std::string& path, CDImage* void CommonHostInterface::OnControllerTypeChanged(u32 slot) { - HostInterface::OnControllerTypeChanged(slot); - UpdateInputMap(); } @@ -2821,8 +2809,8 @@ bool CommonHostInterface::ApplyInputProfile(const char* profile_path) continue; } + // We don't need to call ControllerTypeChanged here because we're already updating the input map. g_settings.controller_types[controller_index - 1] = *ctype; - HostInterface::OnControllerTypeChanged(controller_index - 1); m_settings_interface->SetStringValue(section_name, "Type", Settings::GetControllerTypeName(*ctype));