diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/core.cpp | 11 | ||||
| -rw-r--r-- | src/core/core.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 31 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.h | 5 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_ae.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_oe.h | 2 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 43 | ||||
| -rw-r--r-- | src/yuzu/main.h | 2 |
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 | ||
| 635 | void System::SetExitLock(bool locked) { | ||
| 636 | impl->exit_lock = locked; | ||
| 637 | } | ||
| 638 | |||
| 639 | bool System::GetExitLock() const { | ||
| 640 | return impl->exit_lock; | ||
| 641 | } | ||
| 642 | |||
| 632 | System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | 643 | System::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 | |||
| 329 | private: | 333 | private: |
| 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 | ||
| 233 | IDebugFunctions::~IDebugFunctions() = default; | 233 | IDebugFunctions::~IDebugFunctions() = default; |
| 234 | 234 | ||
| 235 | ISelfController::ISelfController(Core::System& system_, | 235 | ISelfController::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 | ||
| 299 | ISelfController::~ISelfController() = default; | 299 | ISelfController::~ISelfController() = default; |
| 300 | 300 | ||
| 301 | void 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 | |||
| 301 | void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { | 310 | void 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 | ||
| 308 | void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { | 319 | void 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 | ||
| 566 | void AppletMessageQueue::RequestExit() { | ||
| 567 | PushMessage(AppletMessage::ExitRequested); | ||
| 568 | } | ||
| 569 | |||
| 553 | ICommonStateGetter::ICommonStateGetter(Core::System& system, | 570 | ICommonStateGetter::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 { | |||
| 45 | public: | 45 | public: |
| 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 | ||
| 63 | private: | 65 | private: |
| 64 | std::queue<AppletMessage> messages; | 66 | std::queue<AppletMessage> messages; |
| @@ -123,6 +125,7 @@ public: | |||
| 123 | ~ISelfController() override; | 125 | ~ISelfController() override; |
| 124 | 126 | ||
| 125 | private: | 127 | private: |
| 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 | ||
| 156 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 161 | class 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 | ||
| 20 | namespace AM { | 20 | namespace AM { |
| 21 | 21 | ||
| 22 | class AppletMessageQueue; | ||
| 23 | |||
| 22 | class AppletAE final : public ServiceFramework<AppletAE> { | 24 | class AppletAE final : public ServiceFramework<AppletAE> { |
| 23 | public: | 25 | public: |
| 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 | ||
| 20 | namespace AM { | 20 | namespace AM { |
| 21 | 21 | ||
| 22 | class AppletMessageQueue; | ||
| 23 | |||
| 22 | class AppletOE final : public ServiceFramework<AppletOE> { | 24 | class AppletOE final : public ServiceFramework<AppletOE> { |
| 23 | public: | 25 | public: |
| 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 | ||
| 1676 | void GMainWindow::OnPauseGame() { | 1679 | void 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 | ||
| 1687 | void GMainWindow::OnStopGame() { | 1695 | void 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 | ||
| 2205 | bool 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 | |||
| 2217 | void 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 | |||
| 2192 | void GMainWindow::filterBarSetChecked(bool state) { | 2233 | void 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 | ||
| 177 | private slots: | 179 | private slots: |