diff options
| author | 2017-09-30 10:47:42 -0500 | |
|---|---|---|
| committer | 2017-09-30 10:47:42 -0500 | |
| commit | 7056b9c46ac0265c4daff1d4908e6f6f78553ceb (patch) | |
| tree | 964b177eb54edda4ac0065f9444c427ebef2eaff | |
| parent | Merge pull request #2967 from Subv/thread_wakeup_callbacks (diff) | |
| parent | HLE/APT: Always return an error from PrepareToStartNewestHomeMenu so that the... (diff) | |
| download | yuzu-7056b9c46ac0265c4daff1d4908e6f6f78553ceb.tar.gz yuzu-7056b9c46ac0265c4daff1d4908e6f6f78553ceb.tar.xz yuzu-7056b9c46ac0265c4daff1d4908e6f6f78553ceb.zip | |
Merge pull request #2946 from Subv/home_menu_apt
Implement PrepareToStartNewestHomeMenu and fixed an APT regression.
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 39 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.h | 10 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt_s.cpp | 4 |
3 files changed, 45 insertions, 8 deletions
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 4c6156345..2f7362748 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp | |||
| @@ -65,6 +65,7 @@ union AppletAttributes { | |||
| 65 | u32 raw; | 65 | u32 raw; |
| 66 | 66 | ||
| 67 | BitField<0, 3, u32> applet_pos; | 67 | BitField<0, 3, u32> applet_pos; |
| 68 | BitField<29, 1, u32> is_home_menu; | ||
| 68 | 69 | ||
| 69 | AppletAttributes() : raw(0) {} | 70 | AppletAttributes() : raw(0) {} |
| 70 | AppletAttributes(u32 attributes) : raw(attributes) {} | 71 | AppletAttributes(u32 attributes) : raw(attributes) {} |
| @@ -158,6 +159,11 @@ static AppletSlotData* GetAppletSlotData(AppletAttributes attributes) { | |||
| 158 | if (slot == AppletSlot::Error) | 159 | if (slot == AppletSlot::Error) |
| 159 | return nullptr; | 160 | return nullptr; |
| 160 | 161 | ||
| 162 | // The Home Menu is a system applet, however, it has its own applet slot so that it can run | ||
| 163 | // concurrently with other system applets. | ||
| 164 | if (slot == AppletSlot::SystemApplet && attributes.is_home_menu) | ||
| 165 | return &applet_slots[static_cast<size_t>(AppletSlot::HomeMenu)]; | ||
| 166 | |||
| 161 | return &applet_slots[static_cast<size_t>(slot)]; | 167 | return &applet_slots[static_cast<size_t>(slot)]; |
| 162 | } | 168 | } |
| 163 | 169 | ||
| @@ -197,6 +203,19 @@ void Initialize(Service::Interface* self) { | |||
| 197 | rb.Push(RESULT_SUCCESS); | 203 | rb.Push(RESULT_SUCCESS); |
| 198 | rb.PushCopyHandles(Kernel::g_handle_table.Create(slot_data->notification_event).Unwrap(), | 204 | rb.PushCopyHandles(Kernel::g_handle_table.Create(slot_data->notification_event).Unwrap(), |
| 199 | Kernel::g_handle_table.Create(slot_data->parameter_event).Unwrap()); | 205 | Kernel::g_handle_table.Create(slot_data->parameter_event).Unwrap()); |
| 206 | |||
| 207 | if (slot_data->applet_id == AppletId::Application || | ||
| 208 | slot_data->applet_id == AppletId::HomeMenu) { | ||
| 209 | // Initialize the APT parameter to wake up the application. | ||
| 210 | next_parameter.emplace(); | ||
| 211 | next_parameter->signal = static_cast<u32>(SignalType::Wakeup); | ||
| 212 | next_parameter->sender_id = static_cast<u32>(AppletId::None); | ||
| 213 | next_parameter->destination_id = app_id; | ||
| 214 | // Not signaling the parameter event will cause the application (or Home Menu) to hang | ||
| 215 | // during startup. In the real console, it is usually the Kernel and Home Menu who cause NS | ||
| 216 | // to signal the HomeMenu and Application parameter events, respectively. | ||
| 217 | slot_data->parameter_event->Signal(); | ||
| 218 | } | ||
| 200 | } | 219 | } |
| 201 | 220 | ||
| 202 | static u32 DecompressLZ11(const u8* in, u8* out) { | 221 | static u32 DecompressLZ11(const u8* in, u8* out) { |
| @@ -757,6 +776,20 @@ void PrepareToStartLibraryApplet(Service::Interface* self) { | |||
| 757 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); | 776 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); |
| 758 | } | 777 | } |
| 759 | 778 | ||
| 779 | void PrepareToStartNewestHomeMenu(Service::Interface* self) { | ||
| 780 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1A, 0, 0); // 0x1A0000 | ||
| 781 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||
| 782 | |||
| 783 | // TODO(Subv): This command can only be called by a System Applet (return 0xC8A0CC04 otherwise). | ||
| 784 | |||
| 785 | // This command must return an error when called, otherwise the Home Menu will try to reboot the | ||
| 786 | // system. | ||
| 787 | rb.Push(ResultCode(ErrorDescription::AlreadyExists, ErrorModule::Applet, | ||
| 788 | ErrorSummary::InvalidState, ErrorLevel::Status)); | ||
| 789 | |||
| 790 | LOG_DEBUG(Service_APT, "called"); | ||
| 791 | } | ||
| 792 | |||
| 760 | void PreloadLibraryApplet(Service::Interface* self) { | 793 | void PreloadLibraryApplet(Service::Interface* self) { |
| 761 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x16, 1, 0); // 0x160040 | 794 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x16, 1, 0); // 0x160040 |
| 762 | AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); | 795 | AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); |
| @@ -1041,12 +1074,6 @@ void Init() { | |||
| 1041 | slot_data.parameter_event = | 1074 | slot_data.parameter_event = |
| 1042 | Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter"); | 1075 | Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter"); |
| 1043 | } | 1076 | } |
| 1044 | |||
| 1045 | // Initialize the parameter to wake up the application. | ||
| 1046 | next_parameter.emplace(); | ||
| 1047 | next_parameter->signal = static_cast<u32>(SignalType::Wakeup); | ||
| 1048 | next_parameter->destination_id = static_cast<u32>(AppletId::Application); | ||
| 1049 | applet_slots[static_cast<size_t>(AppletSlot::Application)].parameter_event->Signal(); | ||
| 1050 | } | 1077 | } |
| 1051 | 1078 | ||
| 1052 | void Shutdown() { | 1079 | void Shutdown() { |
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 96b28b438..7b79e1f3e 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h | |||
| @@ -420,6 +420,16 @@ void GetAppCpuTimeLimit(Service::Interface* self); | |||
| 420 | void PrepareToStartLibraryApplet(Service::Interface* self); | 420 | void PrepareToStartLibraryApplet(Service::Interface* self); |
| 421 | 421 | ||
| 422 | /** | 422 | /** |
| 423 | * APT::PrepareToStartNewestHomeMenu service function | ||
| 424 | * Inputs: | ||
| 425 | * 0 : Command header [0x001A0000] | ||
| 426 | * Outputs: | ||
| 427 | * 0 : Return header | ||
| 428 | * 1 : Result of function | ||
| 429 | */ | ||
| 430 | void PrepareToStartNewestHomeMenu(Service::Interface* self); | ||
| 431 | |||
| 432 | /** | ||
| 423 | * APT::PreloadLibraryApplet service function | 433 | * APT::PreloadLibraryApplet service function |
| 424 | * Inputs: | 434 | * Inputs: |
| 425 | * 0 : Command header [0x00160040] | 435 | * 0 : Command header [0x00160040] |
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index ec5668d05..fe1d21fff 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[] = { | |||
| 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, | 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, |
| 18 | {0x00070000, nullptr, "GetLastSignaledAppletId"}, | 18 | {0x00070000, nullptr, "GetLastSignaledAppletId"}, |
| 19 | {0x00080000, nullptr, "CountRegisteredApplet"}, | 19 | {0x00080000, nullptr, "CountRegisteredApplet"}, |
| 20 | {0x00090040, nullptr, "IsRegistered"}, | 20 | {0x00090040, IsRegistered, "IsRegistered"}, |
| 21 | {0x000A0040, nullptr, "GetAttribute"}, | 21 | {0x000A0040, nullptr, "GetAttribute"}, |
| 22 | {0x000B0040, InquireNotification, "InquireNotification"}, | 22 | {0x000B0040, InquireNotification, "InquireNotification"}, |
| 23 | {0x000C0104, nullptr, "SendParameter"}, | 23 | {0x000C0104, nullptr, "SendParameter"}, |
| @@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 34 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, | 34 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, |
| 35 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, | 35 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, |
| 36 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, | 36 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, |
| 37 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, | 37 | {0x001A0000, PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"}, |
| 38 | {0x001B00C4, nullptr, "StartApplication"}, | 38 | {0x001B00C4, nullptr, "StartApplication"}, |
| 39 | {0x001C0000, nullptr, "WakeupApplication"}, | 39 | {0x001C0000, nullptr, "WakeupApplication"}, |
| 40 | {0x001D0000, nullptr, "CancelApplication"}, | 40 | {0x001D0000, nullptr, "CancelApplication"}, |