From 674bd550a4e2e9003a9e9b0d7b169da9af1b8cef Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 10 Dec 2017 20:01:11 -0500 Subject: [PATCH 1/2] HLE/APT: Stubbed FinishPreloadingLibraryApplet. An applet is considered "loaded" when the parent application calls this function. --- src/core/hle/service/apt/apt.cpp | 21 ++++++++++++++++++++- src/core/hle/service/apt/apt.h | 11 +++++++++++ src/core/hle/service/apt/apt_s.cpp | 2 +- src/core/hle/service/apt/apt_u.cpp | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index b5a0f7d03..4a4276e70 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -76,6 +76,7 @@ struct AppletSlotData { AppletId applet_id; AppletSlot slot; bool registered; + bool loaded; AppletAttributes attributes; Kernel::SharedPtr notification_event; Kernel::SharedPtr parameter_event; @@ -507,7 +508,7 @@ void IsRegistered(Service::Interface* self) { IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); rb.Push(RESULT_SUCCESS); // No error - auto* const slot_data = GetAppletSlotData(app_id); + const auto* slot_data = GetAppletSlotData(app_id); // Check if an LLE applet was registered first, then fallback to HLE applets bool is_registered = slot_data && slot_data->registered; @@ -887,6 +888,20 @@ void PreloadLibraryApplet(Service::Interface* self) { } } +void FinishPreloadingLibraryApplet(Service::Interface* self) { + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x17, 1, 0); // 0x00170040 + AppletId applet_id = static_cast(rp.Pop()); + + // TODO(Subv): This function should fail depending on the applet preparation state. + auto& slot = applet_slots[static_cast(AppletSlot::LibraryApplet)]; + slot.loaded = true; + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_APT, "(STUBBED) called applet_id=%03X", static_cast(applet_id)); +} + void StartLibraryApplet(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1E, 2, 4); // 0x1E0084 AppletId applet_id = static_cast(rp.Pop()); @@ -1158,6 +1173,7 @@ void Init() { slot_data.applet_id = AppletId::None; slot_data.attributes.raw = 0; slot_data.registered = false; + slot_data.loaded = false; slot_data.notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Notification"); slot_data.parameter_event = @@ -1175,6 +1191,9 @@ void Shutdown() { slot.registered = false; slot.notification_event = nullptr; slot.parameter_event = nullptr; + slot.loaded = false; + slot.attributes.raw = 0; + slot.applet_id = AppletId::None; } next_parameter = boost::none; diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 7b79e1f3e..ef3911ace 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -440,6 +440,17 @@ void PrepareToStartNewestHomeMenu(Service::Interface* self); */ void PreloadLibraryApplet(Service::Interface* self); +/** + * APT::FinishPreloadingLibraryApplet service function + * Inputs: + * 0 : Command header [0x00170040] + * 1 : Id of the applet + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +void FinishPreloadingLibraryApplet(Service::Interface* self); + /** * APT::StartLibraryApplet service function * Inputs: diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index bb78ee7d7..eb15f82f4 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -31,7 +31,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00140040, nullptr, "SetPreparationState"}, {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, - {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, + {0x00170040, FinishPreloadingLibraryApplet, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, {0x001A0000, PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"}, diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index 9dd002590..12eb206ca 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -31,7 +31,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00140040, nullptr, "SetPreparationState"}, {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, - {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, + {0x00170040, FinishPreloadingLibraryApplet, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, From 9a22e8d9ed52119e11a652e6c6eca1970d1d928f Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 10 Dec 2017 20:09:03 -0500 Subject: [PATCH 2/2] HLE/APT: Implement GetAppletInfo for LLE applets. Calling this function for AppletId::Application is not yet implemented because we don't support launching applications from APT. --- src/core/hle/service/apt/apt.cpp | 34 +++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 4a4276e70..3e6d6b200 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -971,7 +971,20 @@ void GetAppletInfo(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x6, 1, 0); // 0x60040 auto app_id = static_cast(rp.Pop()); - if (auto applet = HLE::Applets::Applet::Get(app_id)) { + LOG_DEBUG(Service_APT, "called appid=%u", static_cast(app_id)); + + const auto* slot = GetAppletSlotData(app_id); + + if (slot == nullptr || !slot->registered) { + // See if there's an HLE applet and try to use it before erroring out. + auto hle_applet = HLE::Applets::Applet::Get(app_id); + if (hle_applet == nullptr) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, + ErrorSummary::NotFound, ErrorLevel::Status)); + return; + } + // TODO(Subv): Get the title id for the current applet and write it in the response[2-3] IPC::RequestBuilder rb = rp.MakeBuilder(7, 0); rb.Push(RESULT_SUCCESS); @@ -981,12 +994,27 @@ void GetAppletInfo(Service::Interface* self) { rb.Push(true); // Registered rb.Push(true); // Loaded rb.Push(0); // Applet Attributes - } else { + LOG_WARNING(Service_APT, "Using HLE applet info for applet %03X", static_cast(app_id)); + return; + } + + if (app_id == AppletId::Application) { + // TODO(Subv): Implement this once Application launching is implemented + LOG_ERROR(Service_APT, "Unimplemented GetAppletInfo(Application)"); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, ErrorLevel::Status)); + return; } - LOG_WARNING(Service_APT, "(stubbed) called appid=%u", static_cast(app_id)); + + IPC::RequestBuilder rb = rp.MakeBuilder(7, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(GetTitleIdForApplet(app_id)); + // Note: The NS service hardcodes this to NAND for all applets except the Application applet. + rb.Push(static_cast(Service::FS::MediaType::NAND)); + rb.Push(slot->registered); + rb.Push(slot->loaded); + rb.Push(slot->attributes.raw); } void GetStartupArgument(Service::Interface* self) {