From 3cfe481905b660e1f00fce44cddd8d06e3d1ee8a Mon Sep 17 00:00:00 2001 From: Ghabry Date: Tue, 27 Aug 2024 19:39:20 +0200 Subject: [PATCH] Add a bool to ProcessEvents to signal program exit. Calling Player::Exit in the Ui can crash because the Ui is deleted by it. Also the normal teardown codepath is too slow on WiiU and crashes the console when the home button is used. --- src/baseui.h | 4 +++- src/output.cpp | 6 +++--- src/platform/3ds/ui.cpp | 9 ++++++--- src/platform/3ds/ui.h | 2 +- src/platform/libretro/ui.cpp | 6 ++++-- src/platform/libretro/ui.h | 2 +- src/platform/psvita/ui.cpp | 4 +++- src/platform/psvita/ui.h | 2 +- src/platform/sdl/sdl2_ui.cpp | 7 ++++--- src/platform/sdl/sdl2_ui.h | 2 +- src/platform/sdl/sdl_ui.cpp | 4 +++- src/platform/sdl/sdl_ui.h | 2 +- src/platform/switch/ui.cpp | 4 +++- src/platform/switch/ui.h | 2 +- src/player.cpp | 15 ++++++++++++--- 15 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/baseui.h b/src/baseui.h index b4877cdf67..cb9eaeaf02 100644 --- a/src/baseui.h +++ b/src/baseui.h @@ -68,8 +68,10 @@ class BaseUi { /** * Processes events queue. + * + * @return When false requests an immediate Player shutdown */ - virtual void ProcessEvents() = 0; + virtual bool ProcessEvents() = 0; /** * Cleans video buffer. diff --git a/src/output.cpp b/src/output.cpp index 23129d9a1d..ed792352d7 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -214,9 +214,9 @@ static void HandleErrorOutput(const std::string& err) { #if !defined(USE_LIBRETRO) Game_Clock::SleepFor(1ms); #endif - DisplayUi->ProcessEvents(); - - if (Player::exit_flag) break; + if (!DisplayUi->ProcessEvents() || Player::exit_flag) { + break; + } Input::Update(); } diff --git a/src/platform/3ds/ui.cpp b/src/platform/3ds/ui.cpp index ea4472e36e..eab0b96408 100644 --- a/src/platform/3ds/ui.cpp +++ b/src/platform/3ds/ui.cpp @@ -217,9 +217,10 @@ CtrUi::~CtrUi() { ToggleBottomScreen(true); } -void CtrUi::ProcessEvents() { - if (!aptMainLoop()) - Player::Exit(); +bool CtrUi::ProcessEvents() { + if (!aptMainLoop()) { + return false; + } hidScanInput(); u32 input = hidKeysHeld(); @@ -324,6 +325,8 @@ void CtrUi::ProcessEvents() { } } #endif + + return true; } void CtrUi::UpdateDisplay() { diff --git a/src/platform/3ds/ui.h b/src/platform/3ds/ui.h index 9dc42b7122..febc4f3aa9 100644 --- a/src/platform/3ds/ui.h +++ b/src/platform/3ds/ui.h @@ -50,7 +50,7 @@ class CtrUi final : public BaseUi { */ /** @{ */ void UpdateDisplay() override; - void ProcessEvents() override; + bool ProcessEvents() override; void ToggleStretch() override; void ToggleTouchUi() override; void vGetConfig(Game_ConfigVideo& cfg) const override; diff --git a/src/platform/libretro/ui.cpp b/src/platform/libretro/ui.cpp index 0fd56faabd..efa65ca6b5 100644 --- a/src/platform/libretro/ui.cpp +++ b/src/platform/libretro/ui.cpp @@ -138,10 +138,10 @@ bool LibretroUi::vChangeDisplaySurfaceResolution(int new_width, int new_height) return true; } -void LibretroUi::ProcessEvents() { +bool LibretroUi::ProcessEvents() { # if defined(USE_JOYSTICK) && defined(SUPPORT_JOYSTICK) if (CheckInputState == nullptr) { - return; + return true; } LibretroUi::input_poll_cb(); @@ -184,6 +184,8 @@ void LibretroUi::ProcessEvents() { analog_input.trigger_right = normalize(CheckInputState(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_BUTTON, RETRO_DEVICE_ID_JOYPAD_R2)); # endif # endif + + return true; } retro_video_refresh_t LibretroUi::UpdateWindow = nullptr; diff --git a/src/platform/libretro/ui.h b/src/platform/libretro/ui.h index 6237d4642d..7f9ef8c3c9 100644 --- a/src/platform/libretro/ui.h +++ b/src/platform/libretro/ui.h @@ -47,7 +47,7 @@ class LibretroUi final : public BaseUi { /** @{ */ bool vChangeDisplaySurfaceResolution(int new_width, int new_height) override; void UpdateDisplay() override; - void ProcessEvents() override; + bool ProcessEvents() override; void vGetConfig(Game_ConfigVideo& cfg) const override; #ifdef SUPPORT_AUDIO diff --git a/src/platform/psvita/ui.cpp b/src/platform/psvita/ui.cpp index 397186bfa7..91afcc4120 100644 --- a/src/platform/psvita/ui.cpp +++ b/src/platform/psvita/ui.cpp @@ -207,7 +207,7 @@ Psp2Ui::~Psp2Ui() { vita2d_fini(); } -void Psp2Ui::ProcessEvents() { +bool Psp2Ui::ProcessEvents() { SceCtrlData input; SceTouchData touch; @@ -261,6 +261,8 @@ void Psp2Ui::ProcessEvents() { } } } + + return true; } void Psp2Ui::UpdateDisplay() { diff --git a/src/platform/psvita/ui.h b/src/platform/psvita/ui.h index 5f5fc59f49..d465f0620e 100644 --- a/src/platform/psvita/ui.h +++ b/src/platform/psvita/ui.h @@ -49,7 +49,7 @@ class Psp2Ui final : public BaseUi { */ /** @{ */ void UpdateDisplay() override; - void ProcessEvents() override; + bool ProcessEvents() override; void SetScalingMode(ConfigEnum::ScalingMode) override; void ToggleStretch() override; void ToggleTouchUi() override; diff --git a/src/platform/sdl/sdl2_ui.cpp b/src/platform/sdl/sdl2_ui.cpp index cf91ef4f4b..7c5d4ad72b 100644 --- a/src/platform/sdl/sdl2_ui.cpp +++ b/src/platform/sdl/sdl2_ui.cpp @@ -532,11 +532,10 @@ void Sdl2Ui::ToggleZoom() { #endif } -void Sdl2Ui::ProcessEvents() { +bool Sdl2Ui::ProcessEvents() { #if defined(__WIIU__) if (!WiiU_ProcessProcUI()) { - Player::Exit(); - return; + return false; } #endif @@ -555,6 +554,8 @@ void Sdl2Ui::ProcessEvents() { if (Player::exit_flag) break; } + + return true; } void Sdl2Ui::SetScalingMode(ConfigEnum::ScalingMode mode) { diff --git a/src/platform/sdl/sdl2_ui.h b/src/platform/sdl/sdl2_ui.h index bbade7033d..cef74fe1fd 100644 --- a/src/platform/sdl/sdl2_ui.h +++ b/src/platform/sdl/sdl2_ui.h @@ -65,7 +65,7 @@ class Sdl2Ui final : public BaseUi { void UpdateDisplay() override; void SetTitle(const std::string &title) override; bool ShowCursor(bool flag) override; - void ProcessEvents() override; + bool ProcessEvents() override; void SetScalingMode(ConfigEnum::ScalingMode) override; void ToggleStretch() override; void ToggleVsync() override; diff --git a/src/platform/sdl/sdl_ui.cpp b/src/platform/sdl/sdl_ui.cpp index 04961a612f..29fc05f7d2 100644 --- a/src/platform/sdl/sdl_ui.cpp +++ b/src/platform/sdl/sdl_ui.cpp @@ -404,7 +404,7 @@ void SdlUi::ToggleZoom() { EndDisplayModeChange(); } -void SdlUi::ProcessEvents() { +bool SdlUi::ProcessEvents() { SDL_Event evnt; // Poll SDL events and process them @@ -414,6 +414,8 @@ void SdlUi::ProcessEvents() { if (Player::exit_flag) break; } + + return true; } void SdlUi::UpdateDisplay() { diff --git a/src/platform/sdl/sdl_ui.h b/src/platform/sdl/sdl_ui.h index 775957ffa3..15c1797db5 100644 --- a/src/platform/sdl/sdl_ui.h +++ b/src/platform/sdl/sdl_ui.h @@ -63,7 +63,7 @@ class SdlUi final : public BaseUi { void UpdateDisplay() override; void SetTitle(const std::string &title) override; bool ShowCursor(bool flag) override; - void ProcessEvents() override; + bool ProcessEvents() override; void vGetConfig(Game_ConfigVideo& cfg) const override; #ifdef SUPPORT_AUDIO diff --git a/src/platform/switch/ui.cpp b/src/platform/switch/ui.cpp index 1291a15135..1ef3f28bd0 100644 --- a/src/platform/switch/ui.cpp +++ b/src/platform/switch/ui.cpp @@ -390,7 +390,7 @@ NxUi::~NxUi() { appletUnhook(&applet_hook_cookie); } -void NxUi::ProcessEvents() { +bool NxUi::ProcessEvents() { // handle system events appletMainLoop(); @@ -453,6 +453,8 @@ void NxUi::ProcessEvents() { } } } + + return true; } void NxUi::UpdateDisplay() { diff --git a/src/platform/switch/ui.h b/src/platform/switch/ui.h index 4c6ccf0027..d289f0d029 100644 --- a/src/platform/switch/ui.h +++ b/src/platform/switch/ui.h @@ -48,7 +48,7 @@ class NxUi final : public BaseUi { */ /** @{ */ void UpdateDisplay() override; - void ProcessEvents() override; + bool ProcessEvents() override; void ToggleStretch() override; void ToggleTouchUi() override; void vGetConfig(Game_ConfigVideo& cfg) const override; diff --git a/src/player.cpp b/src/player.cpp index ae4120e39a..7645c3f16b 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -229,10 +229,22 @@ void Player::MainLoop() { Player::UpdateInput(); + if (!DisplayUi->ProcessEvents()) { + Scene::PopUntil(Scene::Null); + Player::Exit(); + return; + } + int num_updates = 0; while (Game_Clock::NextGameTimeStep()) { if (num_updates > 0) { Player::UpdateInput(); + + if (!DisplayUi->ProcessEvents()) { + Scene::PopUntil(Scene::Null); + Player::Exit(); + return; + } } Scene::old_instances.clear(); @@ -306,9 +318,6 @@ void Player::UpdateInput() { if (Main_Data::game_quit) { reset_flag |= Main_Data::game_quit->ShouldQuit(); } - - // Update Logic: - DisplayUi->ProcessEvents(); } void Player::Update(bool update_scene) {