From d8467ca6c0eff0ea0fc619043893abb0a2cebf9f Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 25 Sep 2021 23:14:49 -0400 Subject: [PATCH 1/3] core: Add Exit and ExitCallback This allows ISelfController::Exit to stop the currently running application. This is typically used by homebrew to exit back to the homebrew menu after calling consoleExit with libnx. --- src/core/core.cpp | 13 +++++++++++++ src/core/core.h | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/core/core.cpp b/src/core/core.cpp index 50d5dab4ba..bb268a3197 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -421,6 +421,7 @@ struct System::Impl { bool is_async_gpu{}; ExecuteProgramCallback execute_program_callback; + ExitCallback exit_callback; std::array dynarmic_ticks{}; std::array microprofile_dynarmic{}; @@ -798,6 +799,18 @@ void System::ExecuteProgram(std::size_t program_index) { } } +void System::RegisterExitCallback(ExitCallback&& callback) { + impl->exit_callback = std::move(callback); +} + +void System::Exit() { + if (impl->exit_callback) { + impl->exit_callback(); + } else { + LOG_CRITICAL(Core, "exit_callback must be initialized by the frontend"); + } +} + void System::ApplySettings() { if (IsPoweredOn()) { Renderer().RefreshBaseSettings(); diff --git a/src/core/core.h b/src/core/core.h index 715ab88e7f..a796472b22 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -387,6 +387,18 @@ public: */ void ExecuteProgram(std::size_t program_index); + /// Type used for the frontend to designate a callback for System to exit the application. + using ExitCallback = std::function; + + /** + * Registers a callback from the frontend for System to exit the application. + * @param callback Callback from the frontend to exit the application. + */ + void RegisterExitCallback(ExitCallback&& callback); + + /// Instructs the frontend to exit the application. + void Exit(); + /// Applies any changes to settings to this core instance. void ApplySettings(); From 282bdfd1bf87de150f4a2e7686a4f062b4b9f7c1 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 25 Sep 2021 23:18:14 -0400 Subject: [PATCH 2/3] yuzu: main: Register a callback for Exit --- src/yuzu/bootmanager.cpp | 5 +++++ src/yuzu/bootmanager.h | 4 ++++ src/yuzu/main.cpp | 7 +++++++ src/yuzu/main.h | 1 + 4 files changed, 17 insertions(+) diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 1519a46edd..8b9e186b05 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -302,12 +302,17 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram, Qt::QueuedConnection); + connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection); } void GRenderWindow::ExecuteProgram(std::size_t program_index) { emit ExecuteProgramSignal(program_index); } +void GRenderWindow::Exit() { + emit ExitSignal(); +} + GRenderWindow::~GRenderWindow() { input_subsystem->Shutdown(); } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 402dd2ee17..54c4e21427 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -181,6 +181,9 @@ public: */ void ExecuteProgram(std::size_t program_index); + /// Instructs the window to exit the application. + void Exit(); + public slots: void OnEmulationStarting(EmuThread* emu_thread); void OnEmulationStopping(); @@ -191,6 +194,7 @@ signals: void Closed(); void FirstFrameDisplayed(); void ExecuteProgramSignal(std::size_t program_index); + void ExitSignal(); void MouseActivity(); private: diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 3c28243626..0bd0c5b044 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1384,6 +1384,9 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t system.RegisterExecuteProgramCallback( [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); + // Register an Exit callback such that Core can exit the currently running application. + system.RegisterExitCallback([this]() { render_window->Exit(); }); + connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity); // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views @@ -2469,6 +2472,10 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) { BootGame(last_filename_booted, 0, program_index); } +void GMainWindow::OnExit() { + OnStopGame(); +} + void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text, QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 36eed61030..60ce014718 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -153,6 +153,7 @@ signals: public slots: void OnLoadComplete(); void OnExecuteProgram(std::size_t program_index); + void OnExit(); void ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters); void SoftwareKeyboardInitialize( From 2f5808b7ffd168e1ab3ac7e453f8936098350e58 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 25 Sep 2021 23:21:08 -0400 Subject: [PATCH 3/3] service: am: Make use of Exit to exit the currently running application This also moves the call to the end to ensure services are properly destructed on exit. --- src/core/hle/service/am/am.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 8c2e2f9202..49e9787a45 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -332,10 +332,10 @@ ISelfController::~ISelfController() = default; void ISelfController::Exit(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); - system.Shutdown(); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); + + system.Exit(); } void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {