Merge pull request #3959 from zhaowenlan1779/semi-reset

service/apt: Implement soft reset & CloseApplication
This commit is contained in:
James Rowe 2018-09-19 21:02:59 -06:00 committed by GitHub
commit 687e3e74ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 160 additions and 12 deletions

View file

@ -35,6 +35,12 @@ void EmuThread::run() {
emit DebugModeLeft(); emit DebugModeLeft();
Core::System::ResultStatus result = Core::System::GetInstance().RunLoop(); 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) { if (result != Core::System::ResultStatus::Success) {
this->SetRunning(false); this->SetRunning(false);
emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails()); 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) { void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
QMessageBox::StandardButton answer;
QString status_message; QString status_message;
QString title, message; QString title, message;
@ -1435,9 +1434,11 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
message_box.setIcon(QMessageBox::Icon::Critical); message_box.setIcon(QMessageBox::Icon::Critical);
QPushButton* continue_button = message_box.addButton(tr("Continue"), QMessageBox::RejectRole); QPushButton* continue_button = message_box.addButton(tr("Continue"), QMessageBox::RejectRole);
QPushButton* abort_button = message_box.addButton(tr("Abort"), QMessageBox::AcceptRole); 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) { if (emu_thread) {
ShutdownGame(); ShutdownGame();
} }

View file

@ -77,6 +77,12 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
HW::Update(); HW::Update();
Reschedule(); Reschedule();
if (reset_requested.exchange(false)) {
Reset();
} else if (shutdown_requested.exchange(false)) {
return ResultStatus::ShutdownRequested;
}
return status; return status;
} }
@ -132,6 +138,8 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
} }
Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
status = ResultStatus::Success; status = ResultStatus::Success;
m_emu_window = &emu_window;
m_filepath = filepath;
return status; return status;
} }
@ -241,4 +249,14 @@ void System::Shutdown() {
LOG_DEBUG(Core, "Shutdown OK"); 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 } // namespace Core

View file

@ -59,6 +59,7 @@ public:
/// generic drivers installed /// generic drivers installed
ErrorVideoCore_ErrorBelowGL33, ///< Error in the video core due to the user not having ErrorVideoCore_ErrorBelowGL33, ///< Error in the video core due to the user not having
/// OpenGL 3.3 or higher /// OpenGL 3.3 or higher
ShutdownRequested, ///< Emulated program requested a system shutdown
ErrorUnknown ///< Any other error ErrorUnknown ///< Any other error
}; };
@ -83,6 +84,19 @@ public:
/// Shutdown the emulated system. /// Shutdown the emulated system.
void Shutdown(); 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. * Load an executable application.
* @param emu_window Reference to the host-system window used for video output and keyboard * @param emu_window Reference to the host-system window used for video output and keyboard
@ -216,6 +230,12 @@ private:
ResultStatus status = ResultStatus::Success; ResultStatus status = ResultStatus::Success;
std::string status_details = ""; 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() { 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)); 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) { void Module::Interface::CancelLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x3B, 1, 0); // 0x003B0040 IPC::RequestParser rp(ctx, 0x3B, 1, 0); // 0x003B0040
bool exiting = rp.Pop<bool>(); bool exiting = rp.Pop<bool>();

View file

@ -409,6 +409,49 @@ public:
*/ */
void StartLibraryApplet(Kernel::HLERequestContext& ctx); 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 * APT::CancelLibraryApplet service function
* Inputs: * Inputs:
@ -533,6 +576,7 @@ public:
private: private:
std::shared_ptr<Module> apt; std::shared_ptr<Module> apt;
bool application_reset_prepared{};
}; };
private: private:

View file

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

View file

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

View file

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