From b57d58c0dc94857d28a3ef197d9656f0fbad8e08 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 23 Sep 2017 13:59:07 -0500 Subject: [PATCH 1/2] HLE/APT: Prepare the APT Wakeup parameter when the game calls Initialize We need to know what is being run so we can set the APT parameter destination AppId correctly. Delaying the preparation of the parameter until we know which AppId is running lets us support booting both the Home Menu and normal game Applications. --- src/core/hle/service/apt/apt.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 8c0ba73f2a..ea964bab19 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -65,6 +65,7 @@ union AppletAttributes { u32 raw; BitField<0, 3, u32> applet_pos; + BitField<29, 1, u32> is_home_menu; AppletAttributes() : raw(0) {} AppletAttributes(u32 attributes) : raw(attributes) {} @@ -158,6 +159,11 @@ static AppletSlotData* GetAppletSlotData(AppletAttributes attributes) { if (slot == AppletSlot::Error) return nullptr; + // The Home Menu is a system applet, however, it has its own applet slot so that it can run + // concurrently with other system applets. + if (slot == AppletSlot::SystemApplet && attributes.is_home_menu) + return &applet_slots[static_cast(AppletSlot::HomeMenu)]; + return &applet_slots[static_cast(slot)]; } @@ -197,6 +203,19 @@ void Initialize(Service::Interface* self) { rb.Push(RESULT_SUCCESS); rb.PushCopyHandles(Kernel::g_handle_table.Create(slot_data->notification_event).Unwrap(), Kernel::g_handle_table.Create(slot_data->parameter_event).Unwrap()); + + if (slot_data->applet_id == AppletId::Application || + slot_data->applet_id == AppletId::HomeMenu) { + // Initialize the APT parameter to wake up the application. + next_parameter.emplace(); + next_parameter->signal = static_cast(SignalType::Wakeup); + next_parameter->sender_id = static_cast(AppletId::None); + next_parameter->destination_id = app_id; + // Not signaling the parameter event will cause the application (or Home Menu) to hang + // during startup. In the real console, it is usually the Kernel and Home Menu who cause NS + // to signal the HomeMenu and Application parameter events, respectively. + slot_data->parameter_event->Signal(); + } } static u32 DecompressLZ11(const u8* in, u8* out) { @@ -1041,12 +1060,6 @@ void Init() { slot_data.parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter"); } - - // Initialize the parameter to wake up the application. - next_parameter.emplace(); - next_parameter->signal = static_cast(SignalType::Wakeup); - next_parameter->destination_id = static_cast(AppletId::Application); - applet_slots[static_cast(AppletSlot::Application)].parameter_event->Signal(); } void Shutdown() { From 7096f01c14ff76aefd829ae449a8ab5d474eacf7 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 23 Sep 2017 14:01:04 -0500 Subject: [PATCH 2/2] HLE/APT: Always return an error from PrepareToStartNewestHomeMenu so that the Home Menu doesn't try to reboot the system. As per 3dbrew: "During Home Menu start-up it uses APT:PrepareToStartNewestHomeMenu. If that doesn't return an error(normally NS returns 0xC8A0CFFC for that), Home Menu starts a hardware reboot with APT:StartNewestHomeMenu etc. " --- src/core/hle/service/apt/apt.cpp | 14 ++++++++++++++ src/core/hle/service/apt/apt.h | 10 ++++++++++ src/core/hle/service/apt/apt_s.cpp | 4 ++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index ea964bab19..490c146059 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -776,6 +776,20 @@ void PrepareToStartLibraryApplet(Service::Interface* self) { LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); } +void PrepareToStartNewestHomeMenu(Service::Interface* self) { + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 0, 0); // 0x1A0000 + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + + // TODO(Subv): This command can only be called by a System Applet (return 0xC8A0CC04 otherwise). + + // This command must return an error when called, otherwise the Home Menu will try to reboot the + // system. + rb.Push(ResultCode(ErrorDescription::AlreadyExists, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status)); + + LOG_DEBUG(Service_APT, "called"); +} + void PreloadLibraryApplet(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x16, 1, 0); // 0x160040 AppletId applet_id = static_cast(rp.Pop()); diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 96b28b438a..7b79e1f3e4 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -419,6 +419,16 @@ void GetAppCpuTimeLimit(Service::Interface* self); */ void PrepareToStartLibraryApplet(Service::Interface* self); +/** + * APT::PrepareToStartNewestHomeMenu service function + * Inputs: + * 0 : Command header [0x001A0000] + * Outputs: + * 0 : Return header + * 1 : Result of function + */ +void PrepareToStartNewestHomeMenu(Service::Interface* self); + /** * APT::PreloadLibraryApplet service function * Inputs: diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index ec5668d05f..fe1d21fff6 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -17,7 +17,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00060040, GetAppletInfo, "GetAppletInfo"}, {0x00070000, nullptr, "GetLastSignaledAppletId"}, {0x00080000, nullptr, "CountRegisteredApplet"}, - {0x00090040, nullptr, "IsRegistered"}, + {0x00090040, IsRegistered, "IsRegistered"}, {0x000A0040, nullptr, "GetAttribute"}, {0x000B0040, InquireNotification, "InquireNotification"}, {0x000C0104, nullptr, "SendParameter"}, @@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, - {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, + {0x001A0000, PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"}, {0x001B00C4, nullptr, "StartApplication"}, {0x001C0000, nullptr, "WakeupApplication"}, {0x001D0000, nullptr, "CancelApplication"},