service/apt: Implement soft reset & CloseApplication

This commit is contained in:
zhupengfei 2018-07-18 20:07:00 +08:00
parent ca701e2610
commit ad6b140cb0
No known key found for this signature in database
GPG key ID: 85B82A3E62174206
9 changed files with 160 additions and 12 deletions

View file

@ -35,6 +35,12 @@ void EmuThread::run() {
emit DebugModeLeft();
Core::System::ResultStatus result = Core::System::GetInstance().RunLoop();
if (result == Core::System::ResultStatus::ShutdownRequested) {
// Notify frontend we shutdown
emit ErrorThrown(result, "");
// End emulation execution
break;
}
if (result != Core::System::ResultStatus::Success) {
this->SetRunning(false);
emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails());

View file

@ -1400,7 +1400,6 @@ void GMainWindow::UpdateStatusBar() {
}
void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
QMessageBox::StandardButton answer;
QString status_message;
QString title, message;
@ -1435,9 +1434,11 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
message_box.setIcon(QMessageBox::Icon::Critical);
QPushButton* continue_button = message_box.addButton(tr("Continue"), QMessageBox::RejectRole);
QPushButton* abort_button = message_box.addButton(tr("Abort"), QMessageBox::AcceptRole);
message_box.exec();
if (result != Core::System::ResultStatus::ShutdownRequested)
message_box.exec();
if (message_box.clickedButton() == abort_button) {
if (result == Core::System::ResultStatus::ShutdownRequested ||
message_box.clickedButton() == abort_button) {
if (emu_thread) {
ShutdownGame();
}

View file

@ -76,6 +76,12 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
HW::Update();
Reschedule();
if (reset_requested.exchange(false)) {
Reset();
} else if (shutdown_requested.exchange(false)) {
return ResultStatus::ShutdownRequested;
}
return status;
}
@ -131,6 +137,8 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
}
Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
status = ResultStatus::Success;
m_emu_window = &emu_window;
m_filepath = filepath;
return status;
}
@ -238,4 +246,14 @@ void System::Shutdown() {
LOG_DEBUG(Core, "Shutdown OK");
}
void System::Reset() {
// This is NOT a proper reset, but a temporary workaround by shutting down the system and
// reloading.
// TODO: Properly implement the reset
Shutdown();
// Reload the system with the same setting
Load(*m_emu_window, m_filepath);
}
} // namespace Core

View file

@ -55,6 +55,7 @@ public:
/// generic drivers installed
ErrorVideoCore_ErrorBelowGL33, ///< Error in the video core due to the user not having
/// OpenGL 3.3 or higher
ShutdownRequested, ///< Emulated program requested a system shutdown
ErrorUnknown ///< Any other error
};
@ -79,6 +80,19 @@ public:
/// Shutdown the emulated system.
void Shutdown();
/// Shutdown and then load again
void Reset();
/// Request reset of the system
void RequestReset() {
reset_requested = true;
}
/// Request shutdown of the system
void RequestShutdown() {
shutdown_requested = true;
}
/**
* Load an executable application.
* @param emu_window Reference to the host-system window used for video output and keyboard
@ -209,6 +223,12 @@ private:
ResultStatus status = ResultStatus::Success;
std::string status_details = "";
/// Saved variables for reset
EmuWindow* m_emu_window;
std::string m_filepath;
std::atomic<bool> reset_requested;
std::atomic<bool> shutdown_requested;
};
inline ARM_Interface& CPU() {

View file

@ -543,6 +543,65 @@ void Module::Interface::StartLibraryApplet(Kernel::HLERequestContext& ctx) {
rb.Push(apt->applet_manager->StartLibraryApplet(applet_id, object, buffer));
}
void Module::Interface::CloseApplication(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x27, 1, 4);
u32 parameters_size = rp.Pop<u32>();
Kernel::SharedPtr<Kernel::Object> object = rp.PopGenericObject();
std::vector<u8> buffer = rp.PopStaticBuffer();
LOG_DEBUG(Service_APT, "called");
Core::System::GetInstance().RequestShutdown();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::PrepareToDoApplicationJump(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x31, 4, 0);
u32 flags = rp.Pop<u8>();
u32 program_id_low = rp.Pop<u32>();
u32 program_id_high = rp.Pop<u32>();
Service::FS::MediaType media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>());
LOG_WARNING(Service_APT,
"(STUBBED) called, flags={:08X}, program_id_low={:08X}, program_id_high={:08X}, "
"media_type={:08X}",
flags, program_id_low, program_id_high, static_cast<u8>(media_type));
if (flags == 0x2) {
// It seems that flags 0x2 means jumping to the same application,
// and ignore the parameters. This is used in Pokemon main series
// to soft reset.
application_reset_prepared = true;
}
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::DoApplicationJump(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x32, 2, 4);
u32 parameter_size = rp.Pop<u32>();
u32 hmac_size = rp.Pop<u32>();
std::vector<u8> parameter = rp.PopStaticBuffer();
std::vector<u8> hmac = rp.PopStaticBuffer();
LOG_WARNING(Service_APT, "(STUBBED) called");
if (application_reset_prepared) {
// Reset system
Core::System::GetInstance().RequestReset();
} else {
// After the jump, the application should shutdown
// TODO: Actually implement the jump
Core::System::GetInstance().RequestShutdown();
}
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::CancelLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x3B, 1, 0); // 0x003B0040
bool exiting = rp.Pop<bool>();

View file

@ -409,6 +409,49 @@ public:
*/
void StartLibraryApplet(Kernel::HLERequestContext& ctx);
/**
* APT::CloseApplication service function
* Inputs:
* 0 : Command header [0x00270044]
* 1 : Parameters Size
* 2 : 0x0
* 3 : Handle Parameter
* 4 : (Parameters Size << 14) | 2
* 5 : void*, Parameters
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void CloseApplication(Kernel::HLERequestContext& ctx);
/**
* APT::PrepareToDoApplicationJump service function
* Inputs:
* 0 : Command header [0x00310100]
* 1 : Flags
* 2 : Program ID low
* 3 : Program ID high
* 4 : Media type
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* @param ctx
*/
void PrepareToDoApplicationJump(Kernel::HLERequestContext& ctx);
/**
* APT::DoApplicationJump service function
* Inputs:
* 0 : Command header [0x00320084]
* 1 : Parameter Size (capped to 0x300)
* 2 : HMAC Size (capped to 0x20)
* 3 : (Parameter Size << 14) | 2
* 4 : void*, Parameter
* 5 : (HMAC Size << 14) | 0x802
* 6 : void*, HMAC
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void DoApplicationJump(Kernel::HLERequestContext& ctx);
/**
* APT::CancelLibraryApplet service function
* Inputs:
@ -533,6 +576,7 @@ public:
private:
std::shared_ptr<Module> apt;
bool application_reset_prepared{};
};
private:

View file

@ -48,7 +48,7 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
{0x00240044, nullptr, "JumpToApplication"},
{0x002500C0, &APT_A::PrepareToCloseLibraryApplet, "PrepareToCloseLibraryApplet"},
{0x00260000, nullptr, "PrepareToCloseSystemApplet"},
{0x00270044, nullptr, "CloseApplication"},
{0x00270044, &APT_A::CloseApplication, "CloseApplication"},
{0x00280044, &APT_A::CloseLibraryApplet, "CloseLibraryApplet"},
{0x00290044, nullptr, "CloseSystemApplet"},
{0x002A0000, nullptr, "OrderToCloseSystemApplet"},
@ -58,8 +58,8 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
{0x002E0044, nullptr, "LeaveHomeMenu"},
{0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
{0x00300044, nullptr, "LeaveResidentApplet"},
{0x00310100, nullptr, "PrepareToDoApplicationJump"},
{0x00320084, nullptr, "DoApplicationJump"},
{0x00310100, &APT_A::PrepareToDoApplicationJump, "PrepareToDoApplicationJump"},
{0x00320084, &APT_A::DoApplicationJump, "DoApplicationJump"},
{0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
{0x00340084, nullptr, "SendDeliverArg"},
{0x00350080, nullptr, "ReceiveDeliverArg"},

View file

@ -48,7 +48,7 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
{0x00240044, nullptr, "JumpToApplication"},
{0x002500C0, nullptr, "PrepareToCloseLibraryApplet"},
{0x00260000, nullptr, "PrepareToCloseSystemApplet"},
{0x00270044, nullptr, "CloseApplication"},
{0x00270044, &APT_S::CloseApplication, "CloseApplication"},
{0x00280044, nullptr, "CloseLibraryApplet"},
{0x00290044, nullptr, "CloseSystemApplet"},
{0x002A0000, nullptr, "OrderToCloseSystemApplet"},
@ -58,8 +58,8 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
{0x002E0044, nullptr, "LeaveHomeMenu"},
{0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
{0x00300044, nullptr, "LeaveResidentApplet"},
{0x00310100, nullptr, "PrepareToDoApplicationJump"},
{0x00320084, nullptr, "DoApplicationJump"},
{0x00310100, &APT_S::PrepareToDoApplicationJump, "PrepareToDoApplicationJump"},
{0x00320084, &APT_S::DoApplicationJump, "DoApplicationJump"},
{0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
{0x00340084, nullptr, "SendDeliverArg"},
{0x00350080, nullptr, "ReceiveDeliverArg"},

View file

@ -48,7 +48,7 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
{0x00240044, nullptr, "JumpToApplication"},
{0x002500C0, &APT_U::PrepareToCloseLibraryApplet, "PrepareToCloseLibraryApplet"},
{0x00260000, nullptr, "PrepareToCloseSystemApplet"},
{0x00270044, nullptr, "CloseApplication"},
{0x00270044, &APT_U::CloseApplication, "CloseApplication"},
{0x00280044, &APT_U::CloseLibraryApplet, "CloseLibraryApplet"},
{0x00290044, nullptr, "CloseSystemApplet"},
{0x002A0000, nullptr, "OrderToCloseSystemApplet"},
@ -58,8 +58,8 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
{0x002E0044, nullptr, "LeaveHomeMenu"},
{0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
{0x00300044, nullptr, "LeaveResidentApplet"},
{0x00310100, nullptr, "PrepareToDoApplicationJump"},
{0x00320084, nullptr, "DoApplicationJump"},
{0x00310100, &APT_U::PrepareToDoApplicationJump, "PrepareToDoApplicationJump"},
{0x00320084, &APT_U::DoApplicationJump, "DoApplicationJump"},
{0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
{0x00340084, nullptr, "SendDeliverArg"},
{0x00350080, nullptr, "ReceiveDeliverArg"},