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); | ||||
| 
 | ||||
|         is_powered_on = true; | ||||
|         exit_lock = false; | ||||
| 
 | ||||
|         LOG_DEBUG(Core, "Initialized OK"); | ||||
| 
 | ||||
| @ -249,6 +250,7 @@ struct System::Impl { | ||||
|                                     perf_stats->GetMeanFrametime()); | ||||
| 
 | ||||
|         is_powered_on = false; | ||||
|         exit_lock = false; | ||||
| 
 | ||||
|         // Shutdown emulation session
 | ||||
|         renderer.reset(); | ||||
| @ -333,6 +335,7 @@ struct System::Impl { | ||||
|     std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager; | ||||
|     CpuCoreManager cpu_core_manager; | ||||
|     bool is_powered_on = false; | ||||
|     bool exit_lock = false; | ||||
| 
 | ||||
|     std::unique_ptr<Memory::CheatEngine> cheat_engine; | ||||
|     std::unique_ptr<Tools::Freezer> memory_freezer; | ||||
| @ -629,6 +632,14 @@ const Service::APM::Controller& System::GetAPMController() const { | ||||
|     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) { | ||||
|     return impl->Init(*this, emu_window); | ||||
| } | ||||
|  | ||||
| @ -326,6 +326,10 @@ public: | ||||
| 
 | ||||
|     const Service::APM::Controller& GetAPMController() const; | ||||
| 
 | ||||
|     void SetExitLock(bool locked); | ||||
| 
 | ||||
|     bool GetExitLock() const; | ||||
| 
 | ||||
| private: | ||||
|     System(); | ||||
| 
 | ||||
|  | ||||
| @ -232,12 +232,12 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { | ||||
| 
 | ||||
| IDebugFunctions::~IDebugFunctions() = default; | ||||
| 
 | ||||
| ISelfController::ISelfController(Core::System& system_, | ||||
|                                  std::shared_ptr<NVFlinger::NVFlinger> nvflinger_) | ||||
|     : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger_)) { | ||||
| ISelfController::ISelfController(Core::System& system, | ||||
|                                  std::shared_ptr<NVFlinger::NVFlinger> nvflinger) | ||||
|     : ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) { | ||||
|     // clang-format off
 | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, nullptr, "Exit"}, | ||||
|         {0, &ISelfController::Exit, "Exit"}, | ||||
|         {1, &ISelfController::LockExit, "LockExit"}, | ||||
|         {2, &ISelfController::UnlockExit, "UnlockExit"}, | ||||
|         {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, | ||||
| @ -282,7 +282,7 @@ ISelfController::ISelfController(Core::System& system_, | ||||
| 
 | ||||
|     RegisterHandlers(functions); | ||||
| 
 | ||||
|     auto& kernel = system_.Kernel(); | ||||
|     auto& kernel = system.Kernel(); | ||||
|     launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, | ||||
|                                                               "ISelfController:LaunchableEvent"); | ||||
| 
 | ||||
| @ -298,15 +298,28 @@ ISelfController::ISelfController(Core::System& system_, | ||||
| 
 | ||||
| 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) { | ||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); | ||||
|     LOG_DEBUG(Service_AM, "called"); | ||||
| 
 | ||||
|     system.SetExitLock(true); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| 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}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| @ -550,6 +563,10 @@ void AppletMessageQueue::OperationModeChanged() { | ||||
|     on_operation_mode_changed.writable->Signal(); | ||||
| } | ||||
| 
 | ||||
| void AppletMessageQueue::RequestExit() { | ||||
|     PushMessage(AppletMessage::ExitRequested); | ||||
| } | ||||
| 
 | ||||
| ICommonStateGetter::ICommonStateGetter(Core::System& system, | ||||
|                                        std::shared_ptr<AppletMessageQueue> msg_queue) | ||||
|     : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) { | ||||
|  | ||||
| @ -45,6 +45,7 @@ class AppletMessageQueue { | ||||
| public: | ||||
|     enum class AppletMessage : u32 { | ||||
|         NoMessage = 0, | ||||
|         ExitRequested = 4, | ||||
|         FocusStateChanged = 15, | ||||
|         OperationModeChanged = 30, | ||||
|         PerformanceModeChanged = 31, | ||||
| @ -59,6 +60,7 @@ public: | ||||
|     AppletMessage PopMessage(); | ||||
|     std::size_t GetMessageCount() const; | ||||
|     void OperationModeChanged(); | ||||
|     void RequestExit(); | ||||
| 
 | ||||
| private: | ||||
|     std::queue<AppletMessage> messages; | ||||
| @ -123,6 +125,7 @@ public: | ||||
|     ~ISelfController() override; | ||||
| 
 | ||||
| private: | ||||
|     void Exit(Kernel::HLERequestContext& ctx); | ||||
|     void LockExit(Kernel::HLERequestContext& ctx); | ||||
|     void UnlockExit(Kernel::HLERequestContext& ctx); | ||||
|     void EnterFatalSection(Kernel::HLERequestContext& ctx); | ||||
| @ -151,6 +154,8 @@ private: | ||||
|     u32 idle_time_detection_extension = 0; | ||||
|     u64 num_fatal_sections_entered = 0; | ||||
|     bool is_auto_sleep_disabled = false; | ||||
| 
 | ||||
|     Core::System& system; | ||||
| }; | ||||
| 
 | ||||
| class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | ||||
|  | ||||
| @ -19,6 +19,8 @@ class NVFlinger; | ||||
| 
 | ||||
| namespace AM { | ||||
| 
 | ||||
| class AppletMessageQueue; | ||||
| 
 | ||||
| class AppletAE final : public ServiceFramework<AppletAE> { | ||||
| public: | ||||
|     explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | ||||
|  | ||||
| @ -19,6 +19,8 @@ class NVFlinger; | ||||
| 
 | ||||
| namespace AM { | ||||
| 
 | ||||
| class AppletMessageQueue; | ||||
| 
 | ||||
| class AppletOE final : public ServiceFramework<AppletOE> { | ||||
| public: | ||||
|     explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | ||||
|  | ||||
| @ -22,6 +22,8 @@ | ||||
| #include "core/frontend/applets/general_frontend.h" | ||||
| #include "core/frontend/scope_acquire_window_context.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/hid/controllers/npad.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/frontend/applets/software_keyboard.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/nfp/nfp.h" | ||||
| #include "core/hle/service/sm/sm.h" | ||||
| @ -1674,6 +1677,11 @@ void GMainWindow::OnStartGame() { | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnPauseGame() { | ||||
|     Core::System& system{Core::System::GetInstance()}; | ||||
|     if (system.GetExitLock() && !ConfirmForceLockedExit()) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     emu_thread->SetRunning(false); | ||||
| 
 | ||||
|     ui.action_Start->setEnabled(true); | ||||
| @ -1685,6 +1693,11 @@ void GMainWindow::OnPauseGame() { | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnStopGame() { | ||||
|     Core::System& system{Core::System::GetInstance()}; | ||||
|     if (system.GetExitLock() && !ConfirmForceLockedExit()) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     ShutdownGame(); | ||||
| } | ||||
| 
 | ||||
| @ -2182,13 +2195,41 @@ bool GMainWindow::ConfirmChangeGame() { | ||||
|     if (emu_thread == nullptr) | ||||
|         return true; | ||||
| 
 | ||||
|     auto answer = QMessageBox::question( | ||||
|     const auto answer = QMessageBox::question( | ||||
|         this, tr("yuzu"), | ||||
|         tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."), | ||||
|         QMessageBox::Yes | QMessageBox::No, 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) { | ||||
|     ui.action_Show_Filter_Bar->setChecked(state); | ||||
|     emit(OnToggleFilterBar()); | ||||
|  | ||||
| @ -172,6 +172,8 @@ private: | ||||
|      */ | ||||
|     bool ConfirmClose(); | ||||
|     bool ConfirmChangeGame(); | ||||
|     bool ConfirmForceLockedExit(); | ||||
|     void RequestGameExit(); | ||||
|     void closeEvent(QCloseEvent* event) override; | ||||
| 
 | ||||
| private slots: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 David
						David