From 6467523f02d09d7beb0a2eebfbb41071d5d89a0c Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 3 Jun 2024 19:44:21 +0200 Subject: [PATCH] Wii U: Manually handle ProcUI without the WHB wrapper The ProcUI API is very unstable and querying it crashes when a shutdown was requested. For more control use it directly. --- CMakeLists.txt | 1 + src/output.cpp | 10 ++----- src/platform/sdl/sdl2_ui.cpp | 8 ------ src/platform/wiiu/main.cpp | 53 ++++++++++++++++++++++++++---------- src/platform/wiiu/main.h | 19 +++++++++++++ src/player.cpp | 8 ++++++ 6 files changed, 68 insertions(+), 31 deletions(-) create mode 100644 src/platform/wiiu/main.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 419f0161fd5..40e7ae712f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -590,6 +590,7 @@ if(${PLAYER_TARGET_PLATFORM} STREQUAL "SDL2") if(NINTENDO_WIIU) target_compile_definitions(${PROJECT_NAME} PUBLIC PLAYER_NINTENDO) target_sources(${PROJECT_NAME} PRIVATE + src/platform/wiiu/main.h src/platform/wiiu/input_buttons.cpp) endif() diff --git a/src/output.cpp b/src/output.cpp index 1b6b851361a..70d805a9d1c 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -31,8 +31,7 @@ #elif defined(__vita__) # include #elif defined(__WIIU__) -# include -# include +# include "platform/wiiu/main.h" #endif #include "output.h" @@ -323,12 +322,7 @@ void Output::ErrorStr(std::string const& err) { #ifdef __vita__ sceKernelExitProcess(EXIT_FAILURE); #elif defined(__WIIU__) - // cleanup procui (see FIXME in platform/wiiu/main.cpp) - SYSLaunchMenu(); - while(WHBProcIsRunning()) { - Output::Debug("Waiting for shutdown..."); - Game_Clock::SleepFor(1s); - } + WiiU_Exit(); #endif exit(EXIT_FAILURE); } diff --git a/src/platform/sdl/sdl2_ui.cpp b/src/platform/sdl/sdl2_ui.cpp index 316e48f0a80..22dd72f0687 100644 --- a/src/platform/sdl/sdl2_ui.cpp +++ b/src/platform/sdl/sdl2_ui.cpp @@ -14,7 +14,6 @@ * You should have received a copy of the GNU General Public License * along with EasyRPG Player. If not, see . */ - #include #include #include @@ -31,8 +30,6 @@ # include #elif defined(EMSCRIPTEN) # include -#elif defined(__WIIU__) -# include #endif #include "icon.h" @@ -520,11 +517,6 @@ void Sdl2Ui::ToggleZoom() { void Sdl2Ui::ProcessEvents() { SDL_Event evnt; -#ifdef __WIIU__ - if (!WHBProcIsRunning()) - Player::Exit(); -#endif - #if defined(USE_MOUSE) && defined(SUPPORT_MOUSE) // Reset Mouse scroll keys[Input::Keys::MOUSE_SCROLLUP] = false; diff --git a/src/platform/wiiu/main.cpp b/src/platform/wiiu/main.cpp index e67a7fb6847..16406ec4a75 100644 --- a/src/platform/wiiu/main.cpp +++ b/src/platform/wiiu/main.cpp @@ -27,8 +27,10 @@ #ifdef USE_SDL // SDL might wrap main() # include #endif + #include -#include +#include +#include #include using namespace std::chrono_literals; @@ -46,6 +48,7 @@ static void deinitLogging() {} static bool moduleLogInit = false; static bool cafeLogInit = false; static bool udpLogInit = false; +static bool prodUiExited = false; static void initLogging() { if (!(moduleLogInit = WHBLogModuleInit())) { @@ -81,6 +84,38 @@ static void LogCallback(LogLevel lvl, std::string const& msg, LogCallbackUserDat #endif } +static uint32_t SaveCallback(void*) { + OSSavesDone_ReadyToRelease(); + return 0; +} + +bool WiiU_ProcessProcUI() { + ProcUIStatus status = ProcUIProcessMessages(TRUE); + if (status == PROCUI_STATUS_EXITING) { + prodUiExited = true; + return false; + } else if (status == PROCUI_STATUS_RELEASE_FOREGROUND) { + ProcUIDrawDoneRelease(); + } + return true; +} + +void WiiU_Exit() { + Output::Debug("Shutdown Reason: {}", prodUiExited ? "HOME Menu" : "Player Exit"); + + if (!prodUiExited) { + // Exit was not through the Home Menu + // Manually launch the system menu + SYSLaunchMenu(); + Game_Clock::SleepFor(std::chrono::milliseconds(10)); + while (WiiU_ProcessProcUI()) {} + } + + ProcUIShutdown(); + + deinitLogging(); +} + /** * If the main function ever needs to change, be sure to update the `main()` * functions of the other platforms as well. @@ -89,7 +124,7 @@ extern "C" int main(int argc, char* argv[]) { std::vector args{argv, argv + argc}; initLogging(); - WHBProcInit(); + ProcUIInitEx(SaveCallback, nullptr); Output::SetLogCallback(LogCallback); @@ -118,19 +153,7 @@ extern "C" int main(int argc, char* argv[]) { Player::Init(std::move(args)); Player::Run(); - // FIXME: somehow the wiiu sdl2 port does not clean up procui - // without launching the menu manually -#if 1 - SYSLaunchMenu(); - while(WHBProcIsRunning()) { - Output::Debug("Waiting for shutdown..."); - Game_Clock::SleepFor(1s); - } -#else - WHBProcShutdown(); -#endif - - deinitLogging(); + WiiU_Exit(); return EXIT_SUCCESS; } diff --git a/src/platform/wiiu/main.h b/src/platform/wiiu/main.h new file mode 100644 index 00000000000..16f91bb38c1 --- /dev/null +++ b/src/platform/wiiu/main.h @@ -0,0 +1,19 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EasyRPG Player. If not, see . + */ + +bool WiiU_ProcessProcUI(); +void WiiU_Exit(); diff --git a/src/player.cpp b/src/player.cpp index 5f69eec6ab5..329007f80e4 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -31,6 +31,8 @@ # include #elif defined(EMSCRIPTEN) # include +#elif defined(__WIIU__) +# include "platform/wiiu/main.h" #endif #include "async_handler.h" @@ -219,6 +221,12 @@ void Player::Run() { // libretro invokes the MainLoop through a retro_run-callback #else while (Transition::instance().IsActive() || (Scene::instance && Scene::instance->type != Scene::Null)) { +#if defined(__WIIU__) + if (!WiiU_ProcessProcUI()) { + Player::Exit(); + return; + } +#endif MainLoop(); } #endif