service/apt: Implement soft reset & CloseApplication
This commit is contained in:
parent
ca701e2610
commit
ad6b140cb0
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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"},
|
||||
|
|
Reference in New Issue