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.
This commit is contained in:
Subv 2017-09-23 13:59:07 -05:00
parent a7758b0b36
commit b57d58c0dc

View file

@ -65,6 +65,7 @@ union AppletAttributes {
u32 raw; u32 raw;
BitField<0, 3, u32> applet_pos; BitField<0, 3, u32> applet_pos;
BitField<29, 1, u32> is_home_menu;
AppletAttributes() : raw(0) {} AppletAttributes() : raw(0) {}
AppletAttributes(u32 attributes) : raw(attributes) {} AppletAttributes(u32 attributes) : raw(attributes) {}
@ -158,6 +159,11 @@ static AppletSlotData* GetAppletSlotData(AppletAttributes attributes) {
if (slot == AppletSlot::Error) if (slot == AppletSlot::Error)
return nullptr; 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<size_t>(AppletSlot::HomeMenu)];
return &applet_slots[static_cast<size_t>(slot)]; return &applet_slots[static_cast<size_t>(slot)];
} }
@ -197,6 +203,19 @@ void Initialize(Service::Interface* self) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushCopyHandles(Kernel::g_handle_table.Create(slot_data->notification_event).Unwrap(), rb.PushCopyHandles(Kernel::g_handle_table.Create(slot_data->notification_event).Unwrap(),
Kernel::g_handle_table.Create(slot_data->parameter_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<u32>(SignalType::Wakeup);
next_parameter->sender_id = static_cast<u32>(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) { static u32 DecompressLZ11(const u8* in, u8* out) {
@ -1041,12 +1060,6 @@ void Init() {
slot_data.parameter_event = slot_data.parameter_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter"); Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter");
} }
// Initialize the parameter to wake up the application.
next_parameter.emplace();
next_parameter->signal = static_cast<u32>(SignalType::Wakeup);
next_parameter->destination_id = static_cast<u32>(AppletId::Application);
applet_slots[static_cast<size_t>(AppletSlot::Application)].parameter_event->Signal();
} }
void Shutdown() { void Shutdown() {