mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #2683 from DarkLordZach/lock-exit
am: Implement exit locking and self exit commands
This commit is contained in:
		
						commit
						aaec1562f8
					
				| @ -163,6 +163,7 @@ struct System::Impl { | |||||||
|         gpu_core = VideoCore::CreateGPU(system); |         gpu_core = VideoCore::CreateGPU(system); | ||||||
| 
 | 
 | ||||||
|         is_powered_on = true; |         is_powered_on = true; | ||||||
|  |         exit_lock = false; | ||||||
| 
 | 
 | ||||||
|         LOG_DEBUG(Core, "Initialized OK"); |         LOG_DEBUG(Core, "Initialized OK"); | ||||||
| 
 | 
 | ||||||
| @ -249,6 +250,7 @@ struct System::Impl { | |||||||
|                                     perf_stats->GetMeanFrametime()); |                                     perf_stats->GetMeanFrametime()); | ||||||
| 
 | 
 | ||||||
|         is_powered_on = false; |         is_powered_on = false; | ||||||
|  |         exit_lock = false; | ||||||
| 
 | 
 | ||||||
|         // Shutdown emulation session
 |         // Shutdown emulation session
 | ||||||
|         renderer.reset(); |         renderer.reset(); | ||||||
| @ -333,6 +335,7 @@ struct System::Impl { | |||||||
|     std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager; |     std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager; | ||||||
|     CpuCoreManager cpu_core_manager; |     CpuCoreManager cpu_core_manager; | ||||||
|     bool is_powered_on = false; |     bool is_powered_on = false; | ||||||
|  |     bool exit_lock = false; | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<Memory::CheatEngine> cheat_engine; |     std::unique_ptr<Memory::CheatEngine> cheat_engine; | ||||||
|     std::unique_ptr<Tools::Freezer> memory_freezer; |     std::unique_ptr<Tools::Freezer> memory_freezer; | ||||||
| @ -629,6 +632,14 @@ const Service::APM::Controller& System::GetAPMController() const { | |||||||
|     return impl->apm_controller; |     return impl->apm_controller; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void System::SetExitLock(bool locked) { | ||||||
|  |     impl->exit_lock = locked; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool System::GetExitLock() const { | ||||||
|  |     return impl->exit_lock; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | ||||||
|     return impl->Init(*this, emu_window); |     return impl->Init(*this, emu_window); | ||||||
| } | } | ||||||
|  | |||||||
| @ -326,6 +326,10 @@ public: | |||||||
| 
 | 
 | ||||||
|     const Service::APM::Controller& GetAPMController() const; |     const Service::APM::Controller& GetAPMController() const; | ||||||
| 
 | 
 | ||||||
|  |     void SetExitLock(bool locked); | ||||||
|  | 
 | ||||||
|  |     bool GetExitLock() const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     System(); |     System(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -232,12 +232,12 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { | |||||||
| 
 | 
 | ||||||
| IDebugFunctions::~IDebugFunctions() = default; | IDebugFunctions::~IDebugFunctions() = default; | ||||||
| 
 | 
 | ||||||
| ISelfController::ISelfController(Core::System& system_, | ISelfController::ISelfController(Core::System& system, | ||||||
|                                  std::shared_ptr<NVFlinger::NVFlinger> nvflinger_) |                                  std::shared_ptr<NVFlinger::NVFlinger> nvflinger) | ||||||
|     : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger_)) { |     : ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) { | ||||||
|     // clang-format off
 |     // clang-format off
 | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, nullptr, "Exit"}, |         {0, &ISelfController::Exit, "Exit"}, | ||||||
|         {1, &ISelfController::LockExit, "LockExit"}, |         {1, &ISelfController::LockExit, "LockExit"}, | ||||||
|         {2, &ISelfController::UnlockExit, "UnlockExit"}, |         {2, &ISelfController::UnlockExit, "UnlockExit"}, | ||||||
|         {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, |         {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, | ||||||
| @ -282,7 +282,7 @@ ISelfController::ISelfController(Core::System& system_, | |||||||
| 
 | 
 | ||||||
|     RegisterHandlers(functions); |     RegisterHandlers(functions); | ||||||
| 
 | 
 | ||||||
|     auto& kernel = system_.Kernel(); |     auto& kernel = system.Kernel(); | ||||||
|     launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, |     launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, | ||||||
|                                                               "ISelfController:LaunchableEvent"); |                                                               "ISelfController:LaunchableEvent"); | ||||||
| 
 | 
 | ||||||
| @ -298,15 +298,28 @@ ISelfController::ISelfController(Core::System& system_, | |||||||
| 
 | 
 | ||||||
| ISelfController::~ISelfController() = default; | ISelfController::~ISelfController() = default; | ||||||
| 
 | 
 | ||||||
|  | void ISelfController::Exit(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  | 
 | ||||||
|  |     system.Shutdown(); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { | void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  | 
 | ||||||
|  |     system.SetExitLock(true); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 2}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { | void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  | 
 | ||||||
|  |     system.SetExitLock(false); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 2}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
| @ -550,6 +563,10 @@ void AppletMessageQueue::OperationModeChanged() { | |||||||
|     on_operation_mode_changed.writable->Signal(); |     on_operation_mode_changed.writable->Signal(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void AppletMessageQueue::RequestExit() { | ||||||
|  |     PushMessage(AppletMessage::ExitRequested); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ICommonStateGetter::ICommonStateGetter(Core::System& system, | ICommonStateGetter::ICommonStateGetter(Core::System& system, | ||||||
|                                        std::shared_ptr<AppletMessageQueue> msg_queue) |                                        std::shared_ptr<AppletMessageQueue> msg_queue) | ||||||
|     : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) { |     : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) { | ||||||
|  | |||||||
| @ -45,6 +45,7 @@ class AppletMessageQueue { | |||||||
| public: | public: | ||||||
|     enum class AppletMessage : u32 { |     enum class AppletMessage : u32 { | ||||||
|         NoMessage = 0, |         NoMessage = 0, | ||||||
|  |         ExitRequested = 4, | ||||||
|         FocusStateChanged = 15, |         FocusStateChanged = 15, | ||||||
|         OperationModeChanged = 30, |         OperationModeChanged = 30, | ||||||
|         PerformanceModeChanged = 31, |         PerformanceModeChanged = 31, | ||||||
| @ -59,6 +60,7 @@ public: | |||||||
|     AppletMessage PopMessage(); |     AppletMessage PopMessage(); | ||||||
|     std::size_t GetMessageCount() const; |     std::size_t GetMessageCount() const; | ||||||
|     void OperationModeChanged(); |     void OperationModeChanged(); | ||||||
|  |     void RequestExit(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     std::queue<AppletMessage> messages; |     std::queue<AppletMessage> messages; | ||||||
| @ -123,6 +125,7 @@ public: | |||||||
|     ~ISelfController() override; |     ~ISelfController() override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     void Exit(Kernel::HLERequestContext& ctx); | ||||||
|     void LockExit(Kernel::HLERequestContext& ctx); |     void LockExit(Kernel::HLERequestContext& ctx); | ||||||
|     void UnlockExit(Kernel::HLERequestContext& ctx); |     void UnlockExit(Kernel::HLERequestContext& ctx); | ||||||
|     void EnterFatalSection(Kernel::HLERequestContext& ctx); |     void EnterFatalSection(Kernel::HLERequestContext& ctx); | ||||||
| @ -151,6 +154,8 @@ private: | |||||||
|     u32 idle_time_detection_extension = 0; |     u32 idle_time_detection_extension = 0; | ||||||
|     u64 num_fatal_sections_entered = 0; |     u64 num_fatal_sections_entered = 0; | ||||||
|     bool is_auto_sleep_disabled = false; |     bool is_auto_sleep_disabled = false; | ||||||
|  | 
 | ||||||
|  |     Core::System& system; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | ||||||
|  | |||||||
| @ -19,6 +19,8 @@ class NVFlinger; | |||||||
| 
 | 
 | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
|  | class AppletMessageQueue; | ||||||
|  | 
 | ||||||
| class AppletAE final : public ServiceFramework<AppletAE> { | class AppletAE final : public ServiceFramework<AppletAE> { | ||||||
| public: | public: | ||||||
|     explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |     explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | ||||||
|  | |||||||
| @ -19,6 +19,8 @@ class NVFlinger; | |||||||
| 
 | 
 | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
|  | class AppletMessageQueue; | ||||||
|  | 
 | ||||||
| class AppletOE final : public ServiceFramework<AppletOE> { | class AppletOE final : public ServiceFramework<AppletOE> { | ||||||
| public: | public: | ||||||
|     explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, |     explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | ||||||
|  | |||||||
| @ -22,6 +22,8 @@ | |||||||
| #include "core/frontend/applets/general_frontend.h" | #include "core/frontend/applets/general_frontend.h" | ||||||
| #include "core/frontend/scope_acquire_window_context.h" | #include "core/frontend/scope_acquire_window_context.h" | ||||||
| #include "core/hle/service/acc/profile_manager.h" | #include "core/hle/service/acc/profile_manager.h" | ||||||
|  | #include "core/hle/service/am/applet_ae.h" | ||||||
|  | #include "core/hle/service/am/applet_oe.h" | ||||||
| #include "core/hle/service/am/applets/applets.h" | #include "core/hle/service/am/applets/applets.h" | ||||||
| #include "core/hle/service/hid/controllers/npad.h" | #include "core/hle/service/hid/controllers/npad.h" | ||||||
| #include "core/hle/service/hid/hid.h" | #include "core/hle/service/hid/hid.h" | ||||||
| @ -83,6 +85,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||||||
| #include "core/file_sys/submission_package.h" | #include "core/file_sys/submission_package.h" | ||||||
| #include "core/frontend/applets/software_keyboard.h" | #include "core/frontend/applets/software_keyboard.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/service/am/am.h" | ||||||
| #include "core/hle/service/filesystem/filesystem.h" | #include "core/hle/service/filesystem/filesystem.h" | ||||||
| #include "core/hle/service/nfp/nfp.h" | #include "core/hle/service/nfp/nfp.h" | ||||||
| #include "core/hle/service/sm/sm.h" | #include "core/hle/service/sm/sm.h" | ||||||
| @ -1674,6 +1677,11 @@ void GMainWindow::OnStartGame() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnPauseGame() { | void GMainWindow::OnPauseGame() { | ||||||
|  |     Core::System& system{Core::System::GetInstance()}; | ||||||
|  |     if (system.GetExitLock() && !ConfirmForceLockedExit()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     emu_thread->SetRunning(false); |     emu_thread->SetRunning(false); | ||||||
| 
 | 
 | ||||||
|     ui.action_Start->setEnabled(true); |     ui.action_Start->setEnabled(true); | ||||||
| @ -1685,6 +1693,11 @@ void GMainWindow::OnPauseGame() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GMainWindow::OnStopGame() { | void GMainWindow::OnStopGame() { | ||||||
|  |     Core::System& system{Core::System::GetInstance()}; | ||||||
|  |     if (system.GetExitLock() && !ConfirmForceLockedExit()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ShutdownGame(); |     ShutdownGame(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -2182,13 +2195,41 @@ bool GMainWindow::ConfirmChangeGame() { | |||||||
|     if (emu_thread == nullptr) |     if (emu_thread == nullptr) | ||||||
|         return true; |         return true; | ||||||
| 
 | 
 | ||||||
|     auto answer = QMessageBox::question( |     const auto answer = QMessageBox::question( | ||||||
|         this, tr("yuzu"), |         this, tr("yuzu"), | ||||||
|         tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."), |         tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."), | ||||||
|         QMessageBox::Yes | QMessageBox::No, QMessageBox::No); |         QMessageBox::Yes | QMessageBox::No, QMessageBox::No); | ||||||
|     return answer != QMessageBox::No; |     return answer != QMessageBox::No; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool GMainWindow::ConfirmForceLockedExit() { | ||||||
|  |     if (emu_thread == nullptr) | ||||||
|  |         return true; | ||||||
|  | 
 | ||||||
|  |     const auto answer = | ||||||
|  |         QMessageBox::question(this, tr("yuzu"), | ||||||
|  |                               tr("The currently running application has requested yuzu to not " | ||||||
|  |                                  "exit.\n\nWould you like to bypass this and exit anyway?"), | ||||||
|  |                               QMessageBox::Yes | QMessageBox::No, QMessageBox::No); | ||||||
|  |     return answer != QMessageBox::No; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GMainWindow::RequestGameExit() { | ||||||
|  |     auto& sm{Core::System::GetInstance().ServiceManager()}; | ||||||
|  |     auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); | ||||||
|  |     auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); | ||||||
|  |     bool has_signalled = false; | ||||||
|  | 
 | ||||||
|  |     if (applet_oe != nullptr) { | ||||||
|  |         applet_oe->GetMessageQueue()->RequestExit(); | ||||||
|  |         has_signalled = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (applet_ae != nullptr && !has_signalled) { | ||||||
|  |         applet_ae->GetMessageQueue()->RequestExit(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GMainWindow::filterBarSetChecked(bool state) { | void GMainWindow::filterBarSetChecked(bool state) { | ||||||
|     ui.action_Show_Filter_Bar->setChecked(state); |     ui.action_Show_Filter_Bar->setChecked(state); | ||||||
|     emit(OnToggleFilterBar()); |     emit(OnToggleFilterBar()); | ||||||
|  | |||||||
| @ -172,6 +172,8 @@ private: | |||||||
|      */ |      */ | ||||||
|     bool ConfirmClose(); |     bool ConfirmClose(); | ||||||
|     bool ConfirmChangeGame(); |     bool ConfirmChangeGame(); | ||||||
|  |     bool ConfirmForceLockedExit(); | ||||||
|  |     void RequestGameExit(); | ||||||
|     void closeEvent(QCloseEvent* event) override; |     void closeEvent(QCloseEvent* event) override; | ||||||
| 
 | 
 | ||||||
| private slots: | private slots: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 David
						David