From 5cfd37225aac0bd34e24ca1110ec4363dc3cde22 Mon Sep 17 00:00:00 2001 From: JamePeng Date: Wed, 17 Aug 2016 22:29:15 +0800 Subject: [PATCH] Update the code of APT service(part2) --- src/core/hle/result.h | 1 + src/core/hle/service/apt/apt.cpp | 517 ++++++++++++++++++++++++++--- src/core/hle/service/apt/apt.h | 412 +++++++++++++++++++---- src/core/hle/service/apt/apt_a.cpp | 25 +- src/core/hle/service/apt/apt_u.cpp | 42 +-- src/core/hle/service/gsp_gpu.cpp | 8 +- 6 files changed, 884 insertions(+), 121 deletions(-) diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 268a8dad2..7bf422abc 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -17,6 +17,7 @@ /// Detailed description of the error. This listing is likely incomplete. enum class ErrorDescription : u32 { Success = 0, + InvalidMemoryPermissions = 2, WrongPermission = 46, OS_InvalidBufferDescriptor = 48, WrongAddress = 53, diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index c009e6c98..1a61bb5db 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -7,6 +7,7 @@ #include "common/logging/log.h" #include "core/hle/applets/applet.h" +#include "core/hle/config_mem.h" #include "core/hle/service/service.h" #include "core/hle/service/apt/apt.h" #include "core/hle/service/apt/apt_a.h" @@ -14,6 +15,7 @@ #include "core/hle/service/apt/apt_u.h" #include "core/hle/service/apt/bcfnt/bcfnt.h" #include "core/hle/service/fs/archive.h" +#include "core/hle/service/gsp_gpu.h" #include "core/hle/service/ptm/ptm.h" #include "core/hle/kernel/event.h" @@ -21,6 +23,9 @@ #include "core/hle/kernel/process.h" #include "core/hle/kernel/shared_memory.h" +#include "core/hw/gpu.h" +#include "core/settings.h" + namespace Service { namespace APT { @@ -33,6 +38,13 @@ static Kernel::SharedPtr notification_event; ///< APT notificatio static Kernel::SharedPtr parameter_event; ///< APT parameter event static u32 cpu_percent; ///< CPU time available to the running application +static u32 homemenu_input_buffer; +static bool is_capture_buffer_info_set = false; +static bool is_homemenu_input_buffer_set = false; + +static AppletPreparationState applet_preparation_state = AppletPreparationState::NoPreparation; +static CaptureBufferInfo capture_buffer_info; +static WirelessRebootInfo wireless_reboot_info; // APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode static u8 unknown_ns_state_field; @@ -41,6 +53,46 @@ static ScreencapPostPermission screen_capture_post_permission; /// Parameter data to be returned in the next call to Glance/ReceiveParameter static MessageParameter next_parameter; +static std::array MessageParameters; + +/** + * GetMessageParametersIndex(sub_10F564) + * Index 0 : + * 0x300 : Application + * Index 1 : + * 0x11X : System Applet + * Index 2 : + * 0x10X : Home Menu + * Index 3 : + * 0x2XX : Library Applet + * 0x4XX : Library Applet + */ +static u32 GetMessageParametersIndex(const u32& app_id) { + u32 result = 0; + if (!(app_id & 0xFF)) { + return 0xFFFFFFFF; + } else { + if (app_id == 0x101 || app_id == 0x103) { + if (app_id & 0x100) { + return 0x2; + } + return 0xFFFFFFFF; + } + if ((app_id & 0x300) != app_id) { + if ((app_id & 0x110) != app_id) { + if ((app_id & 0x100) != app_id) { + if ((app_id & 0x200) != app_id && (app_id & 0x400) != app_id) { + return 0xFFFFFFFF; + } + return 3; + } + return 2; + } + return 1; + } + return 0; + } +} void SendParameter(const MessageParameter& parameter) { next_parameter = parameter; @@ -48,6 +100,16 @@ void SendParameter(const MessageParameter& parameter) { parameter_event->Signal(); } + +void SendParameter(const u32& dst_app_id, const MessageParameter& parameter) { + u32 index = GetMessageParametersIndex(dst_app_id); + if(index != 0xFFFFFFFF){ + memcpy(&MessageParameters[index], ¶meter, sizeof(MessageParameter)); + } + // Signal the event to let the application know that a new parameter is ready to be read + parameter_event->Signal(); +} + void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; @@ -100,11 +162,213 @@ void GetSharedFont(Service::Interface* self) { cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom(); } +void GetWirelessRebootInfo(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 buffer_size = cmd_buff[1]; + VAddr buffer_addr = cmd_buff[0x41]; + + if (buffer_size > sizeof(WirelessRebootInfo)) { + buffer_size = sizeof(WirelessRebootInfo); + } + + memcpy(&wireless_reboot_info, Memory::GetPointer(buffer_addr), sizeof(buffer_size)); + + cmd_buff[0] = IPC::MakeHeader(0x45, 0x1, 0x2); + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = (buffer_size << 14) | 2; + cmd_buff[3] = buffer_size; + LOG_WARNING(Service_APT, "(STUBBED) called"); +} + +void PrepareToLeaveResidentApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 caller_exiting = cmd_buff[1] & 0xFF; + + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) caller_exiting=0x%08X", caller_exiting); +} + +void LeaveResidentApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 parameters_size = cmd_buff[1]; + u32 parameter_handle = cmd_buff[3]; + u32 parameters_addr = cmd_buff[5]; + + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, parameter_handle=0x%08X, parameter_addr=0x%08X", + parameters_size, parameter_handle, parameters_addr); +} + +void PreloadResidentApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 app_id = cmd_buff[1]; + + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id); +} + +void PrepareToStartResidentApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 app_id = cmd_buff[1]; + + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id); +} + +void StartResidentApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 parameters_size = cmd_buff[1]; + u32 parameter_handle = cmd_buff[3]; + u32 parameters_addr = cmd_buff[5]; + + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, parameter_handle=0x%08X, parameter_addr=0x%08X", + parameters_size, parameter_handle, parameters_addr); +} + +void CancelLibraryApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 application_exiting = cmd_buff[1] & 0xf; + + cmd_buff[0] = IPC::MakeHeader(0x3B, 0x1, 0); + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) application_exiting=%u", application_exiting); +} + +void ReplySleepQuery(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 app_id = cmd_buff[1]; + QueryReply query_reply = static_cast(cmd_buff[2] & 0xFF); + + cmd_buff[1] = RESULT_SUCCESS.raw; + if (query_reply == QueryReply::Reject) { + LOG_ERROR(Service_APT, "(STUBBED) app_id=0x%08X, query_reply=REJECT", app_id); + } else { + LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X, query_reply=%u", app_id, query_reply); + } +} + +void ReplySleepNotificationComplete(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 app_id = cmd_buff[1]; + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id); +} + +static void InitCaptureBufferInfo() { + u32 thread_id = 0; + u32 top_screen_color_per_pixel; + u32 bottom_screen_color_per_pixel; + + GSP_GPU::FrameBufferUpdate* top_screen = GSP_GPU::GetFrameBufferInfo(thread_id, 0); + GSP_GPU::FrameBufferUpdate* bottom_screen = GSP_GPU::GetFrameBufferInfo(thread_id, 1); + // not 3D + capture_buffer_info.is_3d = 0; + // main screen config + capture_buffer_info.top_screen_left_offset = top_screen->framebuffer_info[top_screen->index].address_left; + capture_buffer_info.top_screen_right_offset = top_screen->framebuffer_info[top_screen->index].address_right; + capture_buffer_info.top_screen_format = top_screen->framebuffer_info[top_screen->index].format & 0x7; + // sub screen config + capture_buffer_info.bottom_screen_left_offset = bottom_screen->framebuffer_info[bottom_screen->index].address_left; + capture_buffer_info.bottom_screen_right_offset = bottom_screen->framebuffer_info[bottom_screen->index].address_right; + capture_buffer_info.bottom_screen_format = bottom_screen->framebuffer_info[bottom_screen->index].format & 0x7; + + top_screen_color_per_pixel = GPU::Regs::BytesPerPixel(static_cast(capture_buffer_info.top_screen_format)); + bottom_screen_color_per_pixel = GPU::Regs::BytesPerPixel(static_cast(capture_buffer_info.bottom_screen_format)); + capture_buffer_info.size = 240 * (top_screen_color_per_pixel * 400 + bottom_screen_color_per_pixel * 320); + + is_capture_buffer_info_set = true; +} + +ResultCode SendCaptureBufferInfo(u32& buffer_addr, u32& buffer_size) { + if (buffer_addr) { + if (buffer_size > sizeof(CaptureBufferInfo)) { + buffer_size = sizeof(CaptureBufferInfo); + } + is_capture_buffer_info_set = true; + } else { + buffer_size = 0; + } + + memcpy(&capture_buffer_info, Memory::GetPointer(buffer_addr), buffer_size); + return RESULT_SUCCESS; +} + +void SendCaptureBufferInfo(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 buffer_size = cmd_buff[1]; + u32 buffer_transition = cmd_buff[2]; + u32 buffer_addr = cmd_buff[3]; + + if ((buffer_transition & 0x3C0F) != 0x2) { + cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); + cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; //0xD9001830 + return; + } + + cmd_buff[0] = IPC::MakeHeader(0x40, 0x1, 0); //0x00400040 + cmd_buff[1] = SendCaptureBufferInfo(buffer_addr, buffer_size).raw; + LOG_WARNING(Service_APT, "buffer_addr=0x%08X, buffer_size=0x%08X", buffer_addr, buffer_size); +} + +ResultCode ReceiveCaptureBufferInfo(u32& buffer_addr, u32 buffer_size) { + if (buffer_addr) { + if (buffer_size > sizeof(CaptureBufferInfo)) { + buffer_size = sizeof(CaptureBufferInfo); + } + } else { + buffer_size = 0; + } + + if (is_capture_buffer_info_set) { + memcpy(Memory::GetPointer(buffer_addr), &capture_buffer_info, buffer_size); + } else { + InitCaptureBufferInfo(); + memcpy(Memory::GetPointer(buffer_addr), &capture_buffer_info, buffer_size); + } + + return RESULT_SUCCESS; +} + +void ReceiveCaptureBufferInfo(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 buffer_size = cmd_buff[1]; + VAddr buffer_addr = cmd_buff[0x41]; + + if (buffer_size > 0x1000) { + buffer_size = 0x1000; + } + + cmd_buff[0] = IPC::MakeHeader(0x41, 0x2, 0x2); //0x00410082 + cmd_buff[1] = ReceiveCaptureBufferInfo(buffer_addr, buffer_size).raw; + cmd_buff[2] = buffer_size; + cmd_buff[3] = (buffer_size << 14) | 2; + LOG_WARNING(Service_APT, "buffer_size=0x%08X", buffer_size); +} + +void GetCaptureInfo(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 buffer_size = cmd_buff[1]; + VAddr buffer_addr = cmd_buff[0x41]; + + if (buffer_size > 0x1000) { + buffer_size = 0x1000; + } + + cmd_buff[0] = IPC::MakeHeader(0x4A, 0x1, 0x2); + cmd_buff[1] = ReceiveCaptureBufferInfo(buffer_addr, buffer_size).raw; + cmd_buff[2] = (buffer_size << 14) | 2; + LOG_WARNING(Service_APT, "buffer_size=0x%08X", buffer_size); +} + void NotifyToWait(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; + cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); + LOG_WARNING(Service_APT, "(STUBBED) app_id=0x%08X", app_id); } void GetLockHandle(Service::Interface* self) { @@ -127,6 +391,7 @@ void GetLockHandle(Service::Interface* self) { void Enable(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 attributes = cmd_buff[1]; + cmd_buff[1] = RESULT_SUCCESS.raw; // No error parameter_event->Signal(); // Let the application know that it has been started LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); @@ -134,14 +399,22 @@ void Enable(Service::Interface* self) { void GetAppletManInfo(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 unk = cmd_buff[1]; + AppletPos applet_pos = static_cast(cmd_buff[1]); + cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; + cmd_buff[2] = static_cast(applet_pos); cmd_buff[3] = 0; cmd_buff[4] = static_cast(AppletId::HomeMenu); // Home menu AppID cmd_buff[5] = static_cast(AppletId::Application); // TODO(purpasmart96): Do this correctly + LOG_WARNING(Service_APT, "(STUBBED) called applet_pos=0x%08X", applet_pos); +} - LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); +void CountRegisteredApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[2] = HLE::Applets::GetRegisteredAppletCount(); + LOG_WARNING(Service_APT, "registered_applet_count=0x%08X", cmd_buff[2]); } void IsRegistered(Service::Interface* self) { @@ -164,6 +437,7 @@ void IsRegistered(Service::Interface* self) { void InquireNotification(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; + cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = static_cast(SignalType::None); // Signal type LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); @@ -207,7 +481,7 @@ void ReceiveParameter(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; u32 buffer_size = cmd_buff[2]; - VAddr buffer = cmd_buff[0x104 >> 2]; + VAddr buffer = cmd_buff[0x41]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = next_parameter.sender_id; @@ -229,7 +503,7 @@ void GlanceParameter(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; u32 buffer_size = cmd_buff[2]; - VAddr buffer = cmd_buff[0x104 >> 2]; + VAddr buffer = cmd_buff[0x41]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = next_parameter.sender_id; @@ -249,16 +523,32 @@ void GlanceParameter(Service::Interface* self) { void CancelParameter(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 flag1 = cmd_buff[1]; - u32 unk = cmd_buff[2]; - u32 flag2 = cmd_buff[3]; - u32 app_id = cmd_buff[4]; + u32 check_sender = cmd_buff[1] & 0xFF; + u32 sender_id = cmd_buff[2]; + u32 check_receiver = cmd_buff[3] & 0xFF; + u32 receiver_id = cmd_buff[4]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = 1; // Set to Success - LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", - flag1, unk, flag2, app_id); + LOG_WARNING(Service_APT, "(STUBBED) check_sender=0x%08X, sender_id=0x%08X, check_receiver=0x%08X, receiver_id=0x%08X", + check_sender, sender_id, check_receiver, receiver_id); +} + +void GetPreparationState(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[2] = static_cast(applet_preparation_state); + LOG_WARNING(Service_APT, "(STUBBED) called"); +} + +void SetPreparationState(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + applet_preparation_state = static_cast(cmd_buff[1]); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_APT, "(STUBBED) applet_preparation_state=0x%08X", applet_preparation_state); } void PrepareToStartApplication(Service::Interface* self) { @@ -281,36 +571,119 @@ void PrepareToStartApplication(Service::Interface* self) { void StartApplication(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 buffer1_size = cmd_buff[1]; - u32 buffer2_size = cmd_buff[2]; - u32 flag = cmd_buff[3]; - u32 size1 = cmd_buff[4]; - u32 buffer1_ptr = cmd_buff[5]; - u32 size2 = cmd_buff[6]; - u32 buffer2_ptr = cmd_buff[7]; + u32 parameter_size = cmd_buff[1]; + u32 hmac_size = cmd_buff[2]; + u32 is_paused = cmd_buff[3] & 0xFF; + u32 parameter_transition = cmd_buff[4]; + u32 parameter_buffer = cmd_buff[5]; + u32 hmac_transtion = cmd_buff[6]; + u32 hmac_buffer = cmd_buff[7]; + if ((parameter_transition & 0x3C0F) != 2 || (hmac_transtion & 0x3C0F) != 0x802) { + cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); // 0x40 + cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; //0xD9001830 + return; + } + + cmd_buff[0] = IPC::MakeHeader(0x1B, 0x1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, hmac_size=0x%08X, is_paused=0x%08X, parameter_buffer=0x%08X, hmac_buffer=0x%08X", + parameter_size, hmac_size, is_paused, parameter_buffer, hmac_buffer); +} - LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," - "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", - buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); +ResultCode AppletUtility(u32& utility_id, u32& input_buffer, u32& input_size, u32& output_buffer,u32& output_size, bool applet_result) { + u32 sender_id = 0; + u32 transition = 0; + bool shell_open = true; + + switch (static_cast(utility_id)) { + case UtilityID::ClearPowerButtonState: // not useful + case UtilityID::ClearExclusiveControl: + break; + + case UtilityID::SleepIfShellClosed: + shell_open = PTM::GetShellState(); + if (!shell_open) { + LOG_WARNING(Service_APT, "(STUBBED) SleepIfShellClosed, The 3DS system should sleep now."); + } + else { + LOG_WARNING(Service_APT, "(STUBBED) SleepIfShellClosed shell_open=%u", shell_open); + } + break; + + case UtilityID::LockTransition: + transition = Memory::Read32(input_buffer); + LOG_WARNING(Service_APT, "(STUBBED) LockTransition, transition=0x%08X", transition); + break; + + case UtilityID::TryLockTransition: + applet_result = false; + if (output_buffer) { + if (output_size != 0) { + transition = Memory::Read32(input_buffer); + Memory::Write32(output_buffer, 0); + applet_result = true; + LOG_WARNING(Service_APT, "(STUBBED) TryLockTransition, transition=0x%08X", transition); + } + } + LOG_ERROR(Service_APT, "(STUBBED) Utility TryLockTransition Operation Failed"); + break; + + case UtilityID::UnlockTransition: + transition = Memory::Read32(input_buffer); + LOG_WARNING(Service_APT, "(STUBBED) UnlockTransition, transition=0x%08X", transition); + break; + + case UtilityID::StartExitTask: // not useful + break; + + case UtilityID::SetInitialSenderId: + sender_id = Memory::Read32(input_buffer); + LOG_WARNING(Service_APT, "(STUBBED) SetInitialSenderId, sender_id=0x%08X", sender_id); + break; + + case UtilityID::SetPowerButtonClick: // not useful + break; + + case UtilityID::SetHomeMenuBuffer: + // This input_buffer content(may be a src_appid or a dst_appid) + // will be used by homemenu operation(like APT::LeaveHomeMenu) which try to do SendParameter() + is_homemenu_input_buffer_set = true; + homemenu_input_buffer = Memory::Read32(input_buffer); + LOG_WARNING(Service_APT, "(STUBBED) SetLeaveHomeMenuBuffer, input_buffer=0x%08X", input_buffer); + break; + + default: + LOG_ERROR(Service_APT, "(STUBBED) unknown utility_id=0x%08X", utility_id); + UNIMPLEMENTED(); + } + return RESULT_SUCCESS; } void AppletUtility(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - // These are from 3dbrew - I'm not really sure what they're used for. - u32 command = cmd_buff[1]; - u32 buffer1_size = cmd_buff[2]; - u32 buffer2_size = cmd_buff[3]; - u32 buffer1_addr = cmd_buff[5]; - u32 buffer2_addr = cmd_buff[65]; + u32 utility_id = cmd_buff[1]; + u32 input_size = cmd_buff[2]; + u32 output_size = (cmd_buff[3] > 0x1000) ? 0x1000 : cmd_buff[3]; + u32 input_traslation = cmd_buff[4]; + u32 input_buffer = cmd_buff[5]; + u32 output_traslation = cmd_buff[0x40]; + u32 output_buffer = cmd_buff[0x41]; - cmd_buff[1] = RESULT_SUCCESS.raw; // No error + bool applet_result = false; // Only use for utility_id = 6 (bool TryLockTransition) - LOG_WARNING(Service_APT, "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " - "buffer1_addr=0x%08X, buffer2_addr=0x%08X", command, buffer1_size, buffer2_size, - buffer1_addr, buffer2_addr); + if (input_size > 0x1000) { + cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); // 0x40 + cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;;// 0xD9001830 + return; + } + + cmd_buff[0] = IPC::MakeHeader(0x4B, 0x2, 0x2);// 0x004B0082 + cmd_buff[1] = AppletUtility(utility_id, input_buffer, input_size, output_buffer, output_size, applet_result).raw; + cmd_buff[2] = static_cast(applet_result); } void SetAppCpuTimeLimit(Service::Interface* self) { @@ -410,6 +783,45 @@ void GetScreenCapPostPermission(Service::Interface* self) { LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); } +void PrepareToCloseApplication(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 cancel_preload = cmd_buff[1] & 0xFF; + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_APT, "(STUBBED) cancel_preload=%u", cancel_preload); +} + +void CloseApplication(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 parameter_size = cmd_buff[1]; + u32 handle_parameter = cmd_buff[3]; + u32 parameter_buffer = cmd_buff[5]; + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, handle_parameter=0x%08X, parameter_buffer=0x%08X", + parameter_size, handle_parameter, parameter_buffer); +} + +void LeaveHomeMenu(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 parameter_size = cmd_buff[1]; + u32 handle_parameter = cmd_buff[3]; + u32 parameter_buffer_transition = cmd_buff[4]; + u32 parameter_buffer = cmd_buff[5]; + + if (cmd_buff[2] != 0 || (parameter_buffer_transition & 0x3C0F) != 2) { + cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0);// 0x40 + cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; //0xD9001830 + return; + } + + cmd_buff[0] = IPC::MakeHeader(0x2E, 0x1, 0); //0x2E0040 + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) parameter_size=0x%08X, handle_parameter=0x%08X, parameter_buffer=0x%08X", + parameter_size, handle_parameter, parameter_buffer); +} + void GetAppletInfo(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); auto app_id = static_cast(cmd_buff[1]); @@ -431,18 +843,20 @@ void GetAppletInfo(Service::Interface* self) { void GetStartupArgument(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 parameter_size = cmd_buff[1]; + u32 parameter_buffer = cmd_buff[0x41]; + StartupArgumentType startup_argument_type = static_cast(cmd_buff[2]); - if (parameter_size >= 0x300) { - LOG_ERROR(Service_APT, "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", parameter_size); - return; + if (parameter_size > 0x1000) { + parameter_size = 0x1000; } - LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x", - startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41])); + LOG_WARNING(Service_APT,"(STUBBED) called startup_argument_type=%u , parameter_size=0x%08x , parameter_buffer=0x%08x", + startup_argument_type, parameter_size, parameter_buffer); cmd_buff[1] = RESULT_SUCCESS.raw; cmd_buff[2] = (parameter_size > 0) ? 1 : 0; + cmd_buff[3] = (parameter_size << 14) | 2; } void CheckNew3DSApp(Service::Interface* self) { @@ -468,6 +882,31 @@ void CheckNew3DS(Service::Interface* self) { LOG_WARNING(Service_APT, "(STUBBED) called"); } +void IsStandardMemoryLayout(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + const bool is_new_3ds = Settings::values.is_new_3ds; + + u32 is_standard_memory_layout = 0; + + using ConfigMem::config_mem; + + if (is_new_3ds) { + if (config_mem.app_mem_type != 7) { // 7 for 178MB mode. + is_standard_memory_layout = 1; + } + } else { + if (config_mem.app_mem_type == 0) { // 0 for 64MB mode + is_standard_memory_layout = 1; + } + } + + cmd_buff[0] = IPC::MakeHeader(0x104, 0x2, 0); + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = is_standard_memory_layout; + LOG_WARNING(Service_APT, "(STUBBED) is_standard_memory_layout=%u", is_standard_memory_layout); +} + void Init() { AddService(new APT_A_Interface); AddService(new APT_S_Interface); @@ -501,7 +940,7 @@ void Init() { lock = Kernel::Mutex::Create(false, "APT_U:Lock"); cpu_percent = 0; - unknown_ns_state_field = 0; + homemenu_input_buffer = 0; screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value // TODO(bunnei): Check if these are created in Initialize or on APT process startup. @@ -513,6 +952,8 @@ void Init() { } void Shutdown() { + is_capture_buffer_info_set = false; + is_homemenu_input_buffer_set = false; shared_font_mem = nullptr; shared_font_relocated = false; lock = nullptr; diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 077a6a316..4b1da8611 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "common/common_types.h" #include "common/swap.h" @@ -44,6 +46,13 @@ struct CaptureBufferInfo { }; static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has incorrect size"); +struct WirelessRebootInfo { + std::array mac_address{}; + std::array wireless_reboot_passphrase{}; + INSERT_PADDING_BYTES(1); +}; +static_assert(sizeof(WirelessRebootInfo) == 0x10, "WirelessRebootInfo struct has incorrect size"); + /// Signals used by APT functions enum class SignalType : u32 { None = 0x0, @@ -70,12 +79,12 @@ enum class AppletId : u32 { AmiiboSettings = 0x119, SoftwareKeyboard1 = 0x201, Ed1 = 0x202, - PnoteApp = 0x204, - SnoteApp = 0x205, + PnoteApp1 = 0x204, + SnoteApp1 = 0x205, Error = 0x206, - Mint = 0x207, - Extrapad = 0x208, - Memolib = 0x209, + Mint1 = 0x207, + Extrapad1 = 0x208, + Memolib1 = 0x209, Application = 0x300, AnyLibraryApplet = 0x400, SoftwareKeyboard2 = 0x401, @@ -88,6 +97,15 @@ enum class AppletId : u32 { Memolib2 = 0x409, }; +enum class AppletPos { + None = -1, + App = 0, + AppLib = 1, + Sys = 2, + SysLib = 3, + Resident = 4 +}; + enum class StartupArgumentType : u32 { OtherApp = 0, Restart = 1, @@ -101,6 +119,49 @@ enum class ScreencapPostPermission : u32 { DisableScreenshotPostingToMiiverse = 3 }; +enum class QueryReply : u32 { + Reject = 0, + Accept = 1, + Later = 2 +}; + +enum class AppletPreparationState : u32 { + NoPreparation = 0, + PreparedToLaunchApp = 1, + PreparedToCloseApp = 2, + PreparedToForceToCloseApp = 3, + PreparedToPreloadApplib = 4, + PreparedToLaunchApplib = 5, + PreparedToCloseApplib = 6, + PreparedToLaunchSys = 7, + PreparedToCloseSys = 8, + PreparedToPreloadSyslib = 9, + PreparedToLaunchSyslib = 10, + PreparedToCloseSyslib = 11, + PreparedToLaunchResident = 12, + PreparedToLeaveResident = 13, + PreparedToDoHomemenu = 14, + PreparedToLeaveHomemenu = 15, + PreparedToStartResident = 16, + PreparedToDoAppJump = 17, + PreparedToForceToCloseSys = 18, + PreparedToLaunchOtherSys = 19, + PreparedToJumpToApp = 20, +}; + +enum class UtilityID : u32 { + ClearPowerButtonState = 0, + ClearExclusiveControl = 3, + SleepIfShellClosed = 4, + LockTransition = 5, + TryLockTransition = 6, + UnlockTransition = 7, + StartExitTask = 10, + SetInitialSenderId = 11, + SetPowerButtonClick = 12, + SetHomeMenuBuffer = 17 +}; + /// Send a parameter to the currently-running application, which will read it via ReceiveParameter void SendParameter(const MessageParameter& parameter); @@ -123,6 +184,149 @@ void Initialize(Service::Interface* self); */ void GetSharedFont(Service::Interface* self); +/** + * APT::GetWirelessRebootInfo service function + * Inputs: + * 1 : buffer_size + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Note: + * Same as NSS:SetWirelessRebootInfo except this loads the data instead. + * The state flag set by NSS:SetWirelessRebootInfo must have bit0 set, + * Otherwise the output buffer is just cleared without copying any data. + * This is used by DLP-child titles. + */ +void GetWirelessRebootInfo(Service::Interface* self); + +/** + * APT::PrepareToLeaveResidentApplet service function + * Inputs: + * 1 : u8, Caller Exiting (0 = not exiting, 1 = exiting) + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void PrepareToLeaveResidentApplet(Service::Interface* self); + +/** + * APT::LeaveResidentApplet service function + * Inputs: + * 1 : Parameters Size + * 2 : 0x0 + * 3 : Handle Parameter + * 5 : void*, Parameters + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void LeaveResidentApplet(Service::Interface* self); + +/** + * APT::PreloadResidentApplet service function + * Inputs: + * 1 : AppID + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void PreloadResidentApplet(Service::Interface* self); + +/** + * APT::PrepareToStartResidentApplet service function + * Inputs: + * 1 : AppID + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void PrepareToStartResidentApplet(Service::Interface* self); + +/** + * APT::StartResidentApplet service function + * Inputs: + * 1 : Parameters Size + * 2 : 0x0 + * 3 : Handle Parameter + * 5 : void*, Parameters + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void StartResidentApplet(Service::Interface* self); + +/** + * APT::CancelLibraryApplet service function + * Inputs: + * 0 : Header code [0x003B0040] + * 1 : u8, Application Exiting (0 = not exiting, 1 = exiting) + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void CancelLibraryApplet(Service::Interface* self); + +/** + * APT::ReplySleepQuery service function + * Inputs: + * 1 : AppID + * 2: QueryReply + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Note: If the specific unimplemented function or applet was called by application, + * It would return a value QueryReply::Reject to cmd_buff[2] + * For example, "Could not create applet XXXX" will cause the command QueryReply::Reject to this function + */ +void ReplySleepQuery(Service::Interface* self); + +/** + * APT::ReplySleepNotificationComplete service function + * Inputs: + * 1 : AppId + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void ReplySleepNotificationComplete(Service::Interface* self); + +/** + * APT::SendCaptureBufferInfo service function + * Inputs: + * 1 : Size + * 2 : (Size << 14) | 2 + * 3: void* CaptureBufferInfo + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Note: + * The input size is clamped to 0x20-bytes by NS. + * The input buffer with the clamped size is then copied to a NS state buffer. + * The size field for this state buffer is also set to this clamped size. + */ +void SendCaptureBufferInfo(Service::Interface* self); + +/** + * APT::ReceiveCaptureBufferInfo service function + * Inputs: + * 1 : Size + * 0x40 : (Size << 14) | 2 + * 0x41 : void*, CaptureBufferInfo + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Actual Size + * Note: + * This command loads the data set by APT:SendCaptureBufferInfo. + * The input size is clamped to 0x20-bytes by NS, then this size is clamped to the size for the NS state buffer. + * The NS state buffer data is copied to the output buffer, (when the clamped size is not zero) then the size field for the state buffer is set 0. + */ +void ReceiveCaptureBufferInfo(Service::Interface* self); + +/** + * APT::GetCaptureInfo service function + * Inputs: + * 1 : Size + * 0x40 : (Size << 14) | 2 + * 0x41 : void*, CaptureBufferInfo + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Notes: + * This command loads the data set by APT:SendCaptureBufferInfo, this command is similar to APT:ReceiveCaptureBufferInfo. + * The input size is clamped to 0x20-bytes by NS. + * The NS state buffer data is then copied to the output buffer. + */ +void GetCaptureInfo(Service::Interface* self); + /** * APT::NotifyToWait service function * Inputs: @@ -157,11 +361,11 @@ void Enable(Service::Interface* self); /** * APT::GetAppletManInfo service function. * Inputs: - * 1 : Unknown + * 1 : AppletPos * Outputs: * 1 : Result of function, 0 on success, otherwise error code - * 2 : Unknown u32 value - * 3 : Unknown u8 value + * 2 : AppletPos + * 3 : Requested AppId * 4 : Home Menu AppId * 5 : AppID of currently active app */ @@ -182,19 +386,37 @@ void GetAppletManInfo(Service::Interface* self); void GetAppletInfo(Service::Interface* self); /** - * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. - * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this - * command to determine when the launched process is running and to determine when to stop using GSP etc, - * while displaying the "Nintendo 3DS" loading screen. + * APT::CountRegisteredApplet service function. + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Registered Applet Count + */ +void CountRegisteredApplet(Service::Interface* self); + +/** + * APT::IsRegistered service function * Inputs: * 1 : AppID * Outputs: * 0 : Return header * 1 : Result of function, 0 on success, otherwise error code * 2 : Output, 0 = not registered, 1 = registered. + * Note: + * This returns whether the specified AppID is registered with NS yet. + * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this + * command to determine when the launched process is running and to determine when to stop using GSP etc, + * while displaying the "Nintendo 3DS" loading screen. */ void IsRegistered(Service::Interface* self); +/** + * APT::InquireNotification service function. + * Inputs: + * 1 : AppId + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Notification + */ void InquireNotification(Service::Interface* self); /** @@ -215,11 +437,7 @@ void InquireNotification(Service::Interface* self); void SendParameter(Service::Interface* self); /** - * APT::ReceiveParameter service function. This returns the current parameter data from NS state, - * from the source process which set the parameters. Once finished, NS will clear a flag in the NS - * state so that this command will return an error if this command is used again if parameters were - * not set again. This is called when the second Initialize event is triggered. It returns a signal - * type indicating why it was triggered. + * APT::ReceiveParameter service function * Inputs: * 1 : AppID * 2 : Parameter buffer size, max size is 0x1000 @@ -232,90 +450,123 @@ void SendParameter(Service::Interface* self); * 6 : Handle from the source process which set the parameters, likely used for shared memory * 7 : Size * 8 : Output parameter buffer ptr + * Note: + * This returns the current parameter data from NS state, + * from the source process which set the parameters. Once finished, NS will clear a flag in the NS + * state so that this command will return an error if this command is used again if parameters were + * not set again. This is called when the second Initialize event is triggered. It returns a signal + * type indicating why it was triggered. */ void ReceiveParameter(Service::Interface* self); /** - * APT::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter - * (except for the word value prior to the output handle), except this will not clear the flag - * (except when responseword[3]==8 || responseword[3]==9) in NS state. + * APT::GlanceParameter service function * Inputs: * 1 : AppID * 2 : Parameter buffer size, max size is 0x1000 * Outputs: * 1 : Result of function, 0 on success, otherwise error code - * 2 : Unknown, for now assume AppID of the process which sent these parameters - * 3 : Unknown, for now assume Signal type + * 2 : Sender AppID, for now assume AppID of the process which sent these parameters + * 3 : Command, for now assume Signal type * 4 : Actual parameter buffer size, this is <= to the the input size * 5 : Value * 6 : Handle from the source process which set the parameters, likely used for shared memory * 7 : Size * 8 : Output parameter buffer ptr + * Note: + * This is exactly the same as APT_U::ReceiveParameter + * (except for the word value prior to the output handle), except this will not clear the flag + * (except when responseword[3]==8 || responseword[3]==9) in NS state. */ void GlanceParameter(Service::Interface* self); /** - * APT::CancelParameter service function. When the parameter data is available, and when the above - * specified fields match the ones in NS state(for the ones where the checks are enabled), this - * clears the flag which indicates that parameter data is available - * (same flag cleared by APT:ReceiveParameter). + * APT::CancelParameter service function. * Inputs: - * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. - * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. - * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. - * 4 : AppID + * 1 : u8, Check Sender (0 = don't check, 1 = check) + * 2 : Sender AppID + * 3 : u8, Check Receiver (0 = don't check, 1 = check) + * 4 : Receiver AppID * Outputs: - * 0 : Return header * 1 : Result of function, 0 on success, otherwise error code * 2 : Status flag, 0 = failure due to no parameter data being available, or the above enabled * fields don't match the fields in NS state. 1 = success. + * Note: + * When the parameter data is available, and when the above specified fields match the ones in NS state(for the ones where the checks are enabled), + * This clears the flag which indicates that parameter data is available(same flag cleared by APT:ReceiveParameter). */ void CancelParameter(Service::Interface* self); /** - * APT::PrepareToStartApplication service function. When the input title-info programID is zero, - * NS will load the actual program ID via AMNet:GetTitleIDList. After doing some checks with the - * programID, NS will then set a NS state flag to value 1, then set the programID for AppID - * 0x300(application) to the input program ID(or the one from GetTitleIDList). A media-type field - * in the NS state is also set to the input media-type value - * (other state fields are set at this point as well). With 8.0.0-18, NS will set an u8 NS state - * field to value 1 when input flags bit8 is set + * APT::GetPreparationState service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2: AppletPreparationState + */ +void GetPreparationState(Service::Interface* self); + +/** + * APT::SetPreparationState service function * Inputs: - * 1-4 : 0x10-byte title-info struct - * 4 : Flags + * 1 : AppletPreparationState + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void SetPreparationState(Service::Interface* self); + +/** + * APT::PrepareToStartApplication service function + * Inputs: + * 1-4 : ProgramInfo + * 5 : Flags (usually zero, when zero, NS writes a title-info struct with Program ID = ~0 + * and MediaType = NAND to the FIRM parameters structure) * Outputs: * 0 : Return header * 1 : Result of function, 0 on success, otherwise error code + * Note: + * When the input title-info programID is zero, + * NS will load the actual program ID via AMNet:GetTitleIDList. After doing some checks with the + * programID, NS will then set a NS state flag to value 1, then set the programID for AppID + * 0x300(application) to the input program ID(or the one from GetTitleIDList). A media-type field + * in the NS state is also set to the input media-type value + * (other state fields are set at this point as well). With 8.0.0-18, NS will set an u8 NS state + * field to value 1 when input flags bit8 is set */ void PrepareToStartApplication(Service::Interface* self); /** - * APT::StartApplication service function. Buf0 is copied to NS FIRMparams+0x0, then Buf1 is copied - * to the NS FIRMparams+0x480. Then the application is launched. + * APT::StartApplication service function. * Inputs: - * 1 : Buffer 0 size, max size is 0x300 - * 2 : Buffer 1 size, max size is 0x20 (this can be zero) - * 3 : u8 flag - * 4 : (Size0<<14) | 2 - * 5 : Buffer 0 pointer - * 6 : (Size1<<14) | 0x802 - * 7 : Buffer 1 pointer + * 1 : Parameter Size (capped to 0x300) + * 2 : HMAC Size (capped to 0x20) + * 3 : u8 Paused (0 = not paused, 1 = paused) + * 4 : (Parameter Size << 14) | 2 + * 5 : void*, Parameter + * 6 : (HMAC Size << 14) | 0x802 + * 7 : void*, HMAC * Outputs: * 0 : Return Header * 1 : Result of function, 0 on success, otherwise error code -*/ + * Note: + * The parameter buffer is copied to NS FIRMparams+0x0, then the HMAC buffer is copied to NS FIRMparams+0x480. + * Then the application is launched. + */ void StartApplication(Service::Interface* self); /** * APT::AppletUtility service function * Inputs: - * 1 : Unknown, but clearly used for something - * 2 : Buffer 1 size (purpose is unknown) - * 3 : Buffer 2 size (purpose is unknown) - * 5 : Buffer 1 address (purpose is unknown) - * 65 : Buffer 2 address (purpose is unknown) + * 1 : UtilityID + * 2 : Input Size + * 3 : Output Size + * 4 : (Input Size << 14) | 0x402 + * 5 : void*, Input + * 0x41 : void*, Output * Outputs: * 1 : Result of function, 0 on success, otherwise error code + * 2 : Applet Result + * Note: + * This function may affect specific srv:Notifications operation by using Utility */ void AppletUtility(Service::Interface* self); @@ -378,14 +629,50 @@ void PreloadLibraryApplet(Service::Interface* self); */ void StartLibraryApplet(Service::Interface* self); +/** + * APT::PrepareToCloseApplication service function + * Inputs: + * 1 : u8, Cancel Preload (0 = don't cancel, 1 = cancel) + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void PrepareToCloseApplication(Service::Interface* self); + +/** + * APT::CloseApplication service function + * Inputs: + * 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(Service::Interface* self); + +/** + * APT::LeaveHomeMenu service function + * Inputs: + * 0 : Header code [0x002E0044] + * 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 LeaveHomeMenu(Service::Interface* self); + /** * APT::GetStartupArgument service function * Inputs: * 1 : Parameter Size (capped to 0x300) * 2 : StartupArgumentType * Outputs: - * 0 : Return header - * 1 : u8, Exists (0 = does not exist, 1 = exists) + * 1 : Result of function, 0 on success, otherwise error code + * 2 : u8, Exists (0 = does not exist, 1 = exists) */ void GetStartupArgument(Service::Interface* self); @@ -432,6 +719,17 @@ void CheckNew3DSApp(Service::Interface* self); */ void CheckNew3DS(Service::Interface* self); +/** + * APT::IsStandardMemoryLayout service function + * Inputs: + * 0 : Header code [0x01040000] + * Outputs: + * 0 : Header code + * 1 : Result code + * 2 : u8, Standard Memory Layout (0 = non-standard, 1 = standard) + */ +void IsStandardMemoryLayout(Service::Interface* self); + /// Initialize the APT service void Init(); diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index 6c44c491c..e51ecd4d0 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -15,20 +15,37 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00040040, nullptr, "Finalize?"}, {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, {0x00060040, GetAppletInfo, "GetAppletInfo"}, + {0x00080000, CountRegisteredApplet, "CountRegisteredApplet"}, {0x00090040, IsRegistered, "IsRegistered"}, {0x000B0040, InquireNotification, "InquireNotification"}, {0x000C0104, SendParameter, "SendParameter"}, {0x000D0080, ReceiveParameter, "ReceiveParameter"}, {0x000E0080, GlanceParameter, "GlanceParameter"}, {0x000F0100, CancelParameter, "CancelParameter"}, + {0x00130000, GetPreparationState, "GetPreparationState"}, + {0x00140040, SetPreparationState, "SetPreparationState"}, {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, + {0x001B00C4, StartApplication, "StartApplication"}, {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, - {0x003B0040, nullptr, "CancelLibraryApplet?"}, - {0x003E0080, nullptr, "ReplySleepQuery"}, + {0x00220040, PrepareToCloseApplication, "PrepareToCloseApplication"}, + {0x00270044, CloseApplication, "CloseApplication"}, + {0x002E0044, LeaveHomeMenu, "LeaveHomeMenu"}, + {0x002F0040, PrepareToLeaveResidentApplet, "PrepareToLeaveResidentApplet"}, + {0x00300044, LeaveResidentApplet, "LeaveResidentApplet"}, + {0x00380040, PreloadResidentApplet, "PreloadResidentApplet"}, + {0x00390040, PrepareToStartResidentApplet, "PrepareToStartResidentApplet"}, + {0x003A0044, StartResidentApplet, "StartResidentApplet"}, + {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet?"}, + {0x003E0080, ReplySleepQuery, "ReplySleepQuery"}, + {0x003F0040, ReplySleepNotificationComplete,"ReplySleepNotificationComplete"}, + {0x00400042, SendCaptureBufferInfo, "SendCaptureBufferInfo"}, + {0x00410040, ReceiveCaptureBufferInfo, "ReceiveCaptureBufferInfo"}, {0x00430040, NotifyToWait, "NotifyToWait?"}, {0x00440000, GetSharedFont, "GetSharedFont?"}, + {0x00450040, GetWirelessRebootInfo, "GetWirelessRebootInfo"}, + {0x004A0040, GetCaptureInfo, "GetCaptureInfo"}, {0x004B00C2, AppletUtility, "AppletUtility?"}, {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, @@ -36,7 +53,9 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, - {0x01020000, CheckNew3DS, "CheckNew3DS"} + {0x01020000, CheckNew3DS, "CheckNew3DS"}, + {0x01040000, IsStandardMemoryLayout, "IsStandardMemoryLayout" }, + {0x01050100, nullptr, "IsTitleAllowed" } }; APT_A_Interface::APT_A_Interface() { diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index 7bb804ffa..d27f4baa2 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -16,7 +16,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, {0x00060040, GetAppletInfo, "GetAppletInfo"}, {0x00070000, nullptr, "GetLastSignaledAppletId"}, - {0x00080000, nullptr, "CountRegisteredApplet"}, + {0x00080000, CountRegisteredApplet, "CountRegisteredApplet"}, {0x00090040, IsRegistered, "IsRegistered"}, {0x000A0040, nullptr, "GetAttribute"}, {0x000B0040, InquireNotification, "InquireNotification"}, @@ -27,36 +27,36 @@ const Interface::FunctionInfo FunctionTable[] = { {0x001000C2, nullptr, "DebugFunc"}, {0x001100C0, nullptr, "MapProgramIdForDebug"}, {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, - {0x00130000, nullptr, "GetPreparationState"}, - {0x00140040, nullptr, "SetPreparationState"}, + {0x00130000, GetPreparationState, "GetPreparationState"}, + {0x00140040, SetPreparationState, "SetPreparationState"}, {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, - {0x001B00C4, nullptr, "StartApplication"}, + {0x001B00C4, StartApplication, "StartApplication"}, {0x001C0000, nullptr, "WakeupApplication"}, {0x001D0000, nullptr, "CancelApplication"}, {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, {0x001F0084, nullptr, "StartSystemApplet"}, {0x00200044, nullptr, "StartNewestHomeMenu"}, {0x00210000, nullptr, "OrderToCloseApplication"}, - {0x00220040, nullptr, "PrepareToCloseApplication"}, + {0x00220040, PrepareToCloseApplication, "PrepareToCloseApplication"}, {0x00230040, nullptr, "PrepareToJumpToApplication"}, {0x00240044, nullptr, "JumpToApplication"}, {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, - {0x00270044, nullptr, "CloseApplication"}, + {0x00270044, CloseApplication, "CloseApplication"}, {0x00280044, nullptr, "CloseLibraryApplet"}, {0x00290044, nullptr, "CloseSystemApplet"}, {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, {0x002C0044, nullptr, "JumpToHomeMenu"}, {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, - {0x002E0044, nullptr, "LeaveHomeMenu"}, - {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, - {0x00300044, nullptr, "LeaveResidentApplet"}, + {0x002E0044, LeaveHomeMenu, "LeaveHomeMenu"}, + {0x002F0040, PrepareToLeaveResidentApplet, "PrepareToLeaveResidentApplet"}, + {0x00300044, LeaveResidentApplet, "LeaveResidentApplet"}, {0x00310100, nullptr, "PrepareToDoApplicationJump"}, {0x00320084, nullptr, "DoApplicationJump"}, {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, @@ -64,25 +64,25 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00350080, nullptr, "ReceiveDeliverArg"}, {0x00360040, nullptr, "LoadSysMenuArg"}, {0x00370042, nullptr, "StoreSysMenuArg"}, - {0x00380040, nullptr, "PreloadResidentApplet"}, - {0x00390040, nullptr, "PrepareToStartResidentApplet"}, - {0x003A0044, nullptr, "StartResidentApplet"}, - {0x003B0040, nullptr, "CancelLibraryApplet"}, + {0x00380040, PreloadResidentApplet, "PreloadResidentApplet"}, + {0x00390040, PrepareToStartResidentApplet, "PrepareToStartResidentApplet"}, + {0x003A0044, StartResidentApplet, "StartResidentApplet"}, + {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"}, {0x003C0042, nullptr, "SendDspSleep"}, {0x003D0042, nullptr, "SendDspWakeUp"}, - {0x003E0080, nullptr, "ReplySleepQuery"}, - {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, - {0x00400042, nullptr, "SendCaptureBufferInfo"}, - {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, + {0x003E0080, ReplySleepQuery, "ReplySleepQuery"}, + {0x003F0040, ReplySleepNotificationComplete, "ReplySleepNotificationComplete"}, + {0x00400042, SendCaptureBufferInfo, "SendCaptureBufferInfo"}, + {0x00410040, ReceiveCaptureBufferInfo, "ReceiveCaptureBufferInfo"}, {0x00420080, nullptr, "SleepSystem"}, {0x00430040, NotifyToWait, "NotifyToWait"}, {0x00440000, GetSharedFont, "GetSharedFont"}, - {0x00450040, nullptr, "GetWirelessRebootInfo"}, + {0x00450040, GetWirelessRebootInfo, "GetWirelessRebootInfo"}, {0x00460104, nullptr, "Wrap"}, {0x00470104, nullptr, "Unwrap"}, {0x00480100, nullptr, "GetProgramInfo"}, {0x00490180, nullptr, "Reboot"}, - {0x004A0040, nullptr, "GetCaptureInfo"}, + {0x004A0040, GetCaptureInfo, "GetCaptureInfo"}, {0x004B00C2, AppletUtility, "AppletUtility"}, {0x004C0000, nullptr, "SetFatalErrDispMode"}, {0x004D0080, nullptr, "GetAppletProgramInfo"}, @@ -96,7 +96,9 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, {0x00580002, nullptr, "GetProgramID"}, {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, - {0x01020000, CheckNew3DS, "CheckNew3DS"} + {0x01020000, CheckNew3DS, "CheckNew3DS"}, + {0x01040000, IsStandardMemoryLayout, "IsStandardMemoryLayout"}, + {0x01050100, nullptr, "IsTitleAllowed"} }; APT_U_Interface::APT_U_Interface() { diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index ec565f46d..9eef3d7fa 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -611,6 +611,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) { * Inputs: * 0: Header 0x00180000 * Outputs: + * 0: Header Code[0x00180240] * 1: Result code * 2: Left framebuffer virtual address for the main screen * 3: Right framebuffer virtual address for the main screen @@ -633,18 +634,19 @@ static void ImportDisplayCaptureInfo(Service::Interface* self) { FrameBufferUpdate* top_screen = GetFrameBufferInfo(thread_id, 0); FrameBufferUpdate* bottom_screen = GetFrameBufferInfo(thread_id, 1); + cmd_buff[0] = IPC::MakeHeader(0x18, 0x9, 0); + cmd_buff[1] = RESULT_SUCCESS.raw; + //Top Screen cmd_buff[2] = top_screen->framebuffer_info[top_screen->index].address_left; cmd_buff[3] = top_screen->framebuffer_info[top_screen->index].address_right; cmd_buff[4] = top_screen->framebuffer_info[top_screen->index].format; cmd_buff[5] = top_screen->framebuffer_info[top_screen->index].stride; - + //Bottom Screen cmd_buff[6] = bottom_screen->framebuffer_info[bottom_screen->index].address_left; cmd_buff[7] = bottom_screen->framebuffer_info[bottom_screen->index].address_right; cmd_buff[8] = bottom_screen->framebuffer_info[bottom_screen->index].format; cmd_buff[9] = bottom_screen->framebuffer_info[bottom_screen->index].stride; - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_GSP, "called"); }