Merge pull request #2683 from DarkLordZach/lock-exit

am: Implement exit locking and self exit commands
This commit is contained in:
David 2019-09-23 00:37:12 +10:00 committed by GitHub
commit aaec1562f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 8 deletions

View File

@ -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);
} }

View File

@ -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();

View File

@ -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)) {

View File

@ -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> {

View File

@ -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,

View File

@ -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,

View File

@ -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());

View File

@ -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: