summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/core.cpp11
-rw-r--r--src/core/core.h4
-rw-r--r--src/core/hle/service/am/am.cpp31
-rw-r--r--src/core/hle/service/am/am.h5
-rw-r--r--src/core/hle/service/am/applet_ae.h2
-rw-r--r--src/core/hle/service/am/applet_oe.h2
-rw-r--r--src/yuzu/main.cpp43
-rw-r--r--src/yuzu/main.h2
8 files changed, 92 insertions, 8 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 76bb2bae9..92ba42fb9 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -163,6 +163,7 @@ struct System::Impl {
163 gpu_core = VideoCore::CreateGPU(system); 163 gpu_core = VideoCore::CreateGPU(system);
164 164
165 is_powered_on = true; 165 is_powered_on = true;
166 exit_lock = false;
166 167
167 LOG_DEBUG(Core, "Initialized OK"); 168 LOG_DEBUG(Core, "Initialized OK");
168 169
@@ -249,6 +250,7 @@ struct System::Impl {
249 perf_stats->GetMeanFrametime()); 250 perf_stats->GetMeanFrametime());
250 251
251 is_powered_on = false; 252 is_powered_on = false;
253 exit_lock = false;
252 254
253 // Shutdown emulation session 255 // Shutdown emulation session
254 renderer.reset(); 256 renderer.reset();
@@ -333,6 +335,7 @@ struct System::Impl {
333 std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager; 335 std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager;
334 CpuCoreManager cpu_core_manager; 336 CpuCoreManager cpu_core_manager;
335 bool is_powered_on = false; 337 bool is_powered_on = false;
338 bool exit_lock = false;
336 339
337 std::unique_ptr<Memory::CheatEngine> cheat_engine; 340 std::unique_ptr<Memory::CheatEngine> cheat_engine;
338 std::unique_ptr<Tools::Freezer> memory_freezer; 341 std::unique_ptr<Tools::Freezer> memory_freezer;
@@ -629,6 +632,14 @@ const Service::APM::Controller& System::GetAPMController() const {
629 return impl->apm_controller; 632 return impl->apm_controller;
630} 633}
631 634
635void System::SetExitLock(bool locked) {
636 impl->exit_lock = locked;
637}
638
639bool System::GetExitLock() const {
640 return impl->exit_lock;
641}
642
632System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { 643System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
633 return impl->Init(*this, emu_window); 644 return impl->Init(*this, emu_window);
634} 645}
diff --git a/src/core/core.h b/src/core/core.h
index d2a3c82d8..ff10ebe12 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -326,6 +326,10 @@ public:
326 326
327 const Service::APM::Controller& GetAPMController() const; 327 const Service::APM::Controller& GetAPMController() const;
328 328
329 void SetExitLock(bool locked);
330
331 bool GetExitLock() const;
332
329private: 333private:
330 System(); 334 System();
331 335
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3366fd8ce..797c9a06f 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -232,12 +232,12 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
232 232
233IDebugFunctions::~IDebugFunctions() = default; 233IDebugFunctions::~IDebugFunctions() = default;
234 234
235ISelfController::ISelfController(Core::System& system_, 235ISelfController::ISelfController(Core::System& system,
236 std::shared_ptr<NVFlinger::NVFlinger> nvflinger_) 236 std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
237 : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger_)) { 237 : ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) {
238 // clang-format off 238 // clang-format off
239 static const FunctionInfo functions[] = { 239 static const FunctionInfo functions[] = {
240 {0, nullptr, "Exit"}, 240 {0, &ISelfController::Exit, "Exit"},
241 {1, &ISelfController::LockExit, "LockExit"}, 241 {1, &ISelfController::LockExit, "LockExit"},
242 {2, &ISelfController::UnlockExit, "UnlockExit"}, 242 {2, &ISelfController::UnlockExit, "UnlockExit"},
243 {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, 243 {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
@@ -282,7 +282,7 @@ ISelfController::ISelfController(Core::System& system_,
282 282
283 RegisterHandlers(functions); 283 RegisterHandlers(functions);
284 284
285 auto& kernel = system_.Kernel(); 285 auto& kernel = system.Kernel();
286 launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, 286 launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
287 "ISelfController:LaunchableEvent"); 287 "ISelfController:LaunchableEvent");
288 288
@@ -298,15 +298,28 @@ ISelfController::ISelfController(Core::System& system_,
298 298
299ISelfController::~ISelfController() = default; 299ISelfController::~ISelfController() = default;
300 300
301void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
302 LOG_DEBUG(Service_AM, "called");
303
304 system.Shutdown();
305
306 IPC::ResponseBuilder rb{ctx, 2};
307 rb.Push(RESULT_SUCCESS);
308}
309
301void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { 310void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
302 LOG_WARNING(Service_AM, "(STUBBED) called"); 311 LOG_DEBUG(Service_AM, "called");
312
313 system.SetExitLock(true);
303 314
304 IPC::ResponseBuilder rb{ctx, 2}; 315 IPC::ResponseBuilder rb{ctx, 2};
305 rb.Push(RESULT_SUCCESS); 316 rb.Push(RESULT_SUCCESS);
306} 317}
307 318
308void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { 319void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
309 LOG_WARNING(Service_AM, "(STUBBED) called"); 320 LOG_DEBUG(Service_AM, "called");
321
322 system.SetExitLock(false);
310 323
311 IPC::ResponseBuilder rb{ctx, 2}; 324 IPC::ResponseBuilder rb{ctx, 2};
312 rb.Push(RESULT_SUCCESS); 325 rb.Push(RESULT_SUCCESS);
@@ -550,6 +563,10 @@ void AppletMessageQueue::OperationModeChanged() {
550 on_operation_mode_changed.writable->Signal(); 563 on_operation_mode_changed.writable->Signal();
551} 564}
552 565
566void AppletMessageQueue::RequestExit() {
567 PushMessage(AppletMessage::ExitRequested);
568}
569
553ICommonStateGetter::ICommonStateGetter(Core::System& system, 570ICommonStateGetter::ICommonStateGetter(Core::System& system,
554 std::shared_ptr<AppletMessageQueue> msg_queue) 571 std::shared_ptr<AppletMessageQueue> msg_queue)
555 : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) { 572 : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) {
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 28f870302..a3baeb673 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -45,6 +45,7 @@ class AppletMessageQueue {
45public: 45public:
46 enum class AppletMessage : u32 { 46 enum class AppletMessage : u32 {
47 NoMessage = 0, 47 NoMessage = 0,
48 ExitRequested = 4,
48 FocusStateChanged = 15, 49 FocusStateChanged = 15,
49 OperationModeChanged = 30, 50 OperationModeChanged = 30,
50 PerformanceModeChanged = 31, 51 PerformanceModeChanged = 31,
@@ -59,6 +60,7 @@ public:
59 AppletMessage PopMessage(); 60 AppletMessage PopMessage();
60 std::size_t GetMessageCount() const; 61 std::size_t GetMessageCount() const;
61 void OperationModeChanged(); 62 void OperationModeChanged();
63 void RequestExit();
62 64
63private: 65private:
64 std::queue<AppletMessage> messages; 66 std::queue<AppletMessage> messages;
@@ -123,6 +125,7 @@ public:
123 ~ISelfController() override; 125 ~ISelfController() override;
124 126
125private: 127private:
128 void Exit(Kernel::HLERequestContext& ctx);
126 void LockExit(Kernel::HLERequestContext& ctx); 129 void LockExit(Kernel::HLERequestContext& ctx);
127 void UnlockExit(Kernel::HLERequestContext& ctx); 130 void UnlockExit(Kernel::HLERequestContext& ctx);
128 void EnterFatalSection(Kernel::HLERequestContext& ctx); 131 void EnterFatalSection(Kernel::HLERequestContext& ctx);
@@ -151,6 +154,8 @@ private:
151 u32 idle_time_detection_extension = 0; 154 u32 idle_time_detection_extension = 0;
152 u64 num_fatal_sections_entered = 0; 155 u64 num_fatal_sections_entered = 0;
153 bool is_auto_sleep_disabled = false; 156 bool is_auto_sleep_disabled = false;
157
158 Core::System& system;
154}; 159};
155 160
156class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { 161class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h
index 0e0d10858..2e3e45915 100644
--- a/src/core/hle/service/am/applet_ae.h
+++ b/src/core/hle/service/am/applet_ae.h
@@ -19,6 +19,8 @@ class NVFlinger;
19 19
20namespace AM { 20namespace AM {
21 21
22class AppletMessageQueue;
23
22class AppletAE final : public ServiceFramework<AppletAE> { 24class AppletAE final : public ServiceFramework<AppletAE> {
23public: 25public:
24 explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, 26 explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
index 99a65e7b5..758da792d 100644
--- a/src/core/hle/service/am/applet_oe.h
+++ b/src/core/hle/service/am/applet_oe.h
@@ -19,6 +19,8 @@ class NVFlinger;
19 19
20namespace AM { 20namespace AM {
21 21
22class AppletMessageQueue;
23
22class AppletOE final : public ServiceFramework<AppletOE> { 24class AppletOE final : public ServiceFramework<AppletOE> {
23public: 25public:
24 explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, 26 explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f147044d9..2d82df739 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -22,6 +22,8 @@
22#include "core/frontend/applets/general_frontend.h" 22#include "core/frontend/applets/general_frontend.h"
23#include "core/frontend/scope_acquire_window_context.h" 23#include "core/frontend/scope_acquire_window_context.h"
24#include "core/hle/service/acc/profile_manager.h" 24#include "core/hle/service/acc/profile_manager.h"
25#include "core/hle/service/am/applet_ae.h"
26#include "core/hle/service/am/applet_oe.h"
25#include "core/hle/service/am/applets/applets.h" 27#include "core/hle/service/am/applets/applets.h"
26#include "core/hle/service/hid/controllers/npad.h" 28#include "core/hle/service/hid/controllers/npad.h"
27#include "core/hle/service/hid/hid.h" 29#include "core/hle/service/hid/hid.h"
@@ -83,6 +85,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
83#include "core/file_sys/submission_package.h" 85#include "core/file_sys/submission_package.h"
84#include "core/frontend/applets/software_keyboard.h" 86#include "core/frontend/applets/software_keyboard.h"
85#include "core/hle/kernel/process.h" 87#include "core/hle/kernel/process.h"
88#include "core/hle/service/am/am.h"
86#include "core/hle/service/filesystem/filesystem.h" 89#include "core/hle/service/filesystem/filesystem.h"
87#include "core/hle/service/nfp/nfp.h" 90#include "core/hle/service/nfp/nfp.h"
88#include "core/hle/service/sm/sm.h" 91#include "core/hle/service/sm/sm.h"
@@ -1674,6 +1677,11 @@ void GMainWindow::OnStartGame() {
1674} 1677}
1675 1678
1676void GMainWindow::OnPauseGame() { 1679void GMainWindow::OnPauseGame() {
1680 Core::System& system{Core::System::GetInstance()};
1681 if (system.GetExitLock() && !ConfirmForceLockedExit()) {
1682 return;
1683 }
1684
1677 emu_thread->SetRunning(false); 1685 emu_thread->SetRunning(false);
1678 1686
1679 ui.action_Start->setEnabled(true); 1687 ui.action_Start->setEnabled(true);
@@ -1685,6 +1693,11 @@ void GMainWindow::OnPauseGame() {
1685} 1693}
1686 1694
1687void GMainWindow::OnStopGame() { 1695void GMainWindow::OnStopGame() {
1696 Core::System& system{Core::System::GetInstance()};
1697 if (system.GetExitLock() && !ConfirmForceLockedExit()) {
1698 return;
1699 }
1700
1688 ShutdownGame(); 1701 ShutdownGame();
1689} 1702}
1690 1703
@@ -2182,13 +2195,41 @@ bool GMainWindow::ConfirmChangeGame() {
2182 if (emu_thread == nullptr) 2195 if (emu_thread == nullptr)
2183 return true; 2196 return true;
2184 2197
2185 auto answer = QMessageBox::question( 2198 const auto answer = QMessageBox::question(
2186 this, tr("yuzu"), 2199 this, tr("yuzu"),
2187 tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."), 2200 tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."),
2188 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 2201 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
2189 return answer != QMessageBox::No; 2202 return answer != QMessageBox::No;
2190} 2203}
2191 2204
2205bool GMainWindow::ConfirmForceLockedExit() {
2206 if (emu_thread == nullptr)
2207 return true;
2208
2209 const auto answer =
2210 QMessageBox::question(this, tr("yuzu"),
2211 tr("The currently running application has requested yuzu to not "
2212 "exit.\n\nWould you like to bypass this and exit anyway?"),
2213 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
2214 return answer != QMessageBox::No;
2215}
2216
2217void GMainWindow::RequestGameExit() {
2218 auto& sm{Core::System::GetInstance().ServiceManager()};
2219 auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
2220 auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
2221 bool has_signalled = false;
2222
2223 if (applet_oe != nullptr) {
2224 applet_oe->GetMessageQueue()->RequestExit();
2225 has_signalled = true;
2226 }
2227
2228 if (applet_ae != nullptr && !has_signalled) {
2229 applet_ae->GetMessageQueue()->RequestExit();
2230 }
2231}
2232
2192void GMainWindow::filterBarSetChecked(bool state) { 2233void GMainWindow::filterBarSetChecked(bool state) {
2193 ui.action_Show_Filter_Bar->setChecked(state); 2234 ui.action_Show_Filter_Bar->setChecked(state);
2194 emit(OnToggleFilterBar()); 2235 emit(OnToggleFilterBar());
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7d16188cb..e942d1248 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -172,6 +172,8 @@ private:
172 */ 172 */
173 bool ConfirmClose(); 173 bool ConfirmClose();
174 bool ConfirmChangeGame(); 174 bool ConfirmChangeGame();
175 bool ConfirmForceLockedExit();
176 void RequestGameExit();
175 void closeEvent(QCloseEvent* event) override; 177 void closeEvent(QCloseEvent* event) override;
176 178
177private slots: 179private slots: