diff options
Diffstat (limited to 'src/core/hle/service/apt')
-rw-r--r-- | src/core/hle/service/apt/apt.cpp | 160 | ||||
-rw-r--r-- | src/core/hle/service/apt/apt.h | 49 | ||||
-rw-r--r-- | src/core/hle/service/apt/apt_a.cpp | 31 | ||||
-rw-r--r-- | src/core/hle/service/apt/apt_u.cpp | 4 |
4 files changed, 188 insertions, 56 deletions
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index b454a2709..b364beed9 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -6,6 +6,7 @@ #include "common/file_util.h" #include "common/logging/log.h" +#include "core/hle/applets/applet.h" #include "core/hle/service/service.h" #include "core/hle/service/apt/apt.h" #include "core/hle/service/apt/apt_a.h" @@ -34,12 +35,21 @@ static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem; static Kernel::SharedPtr<Kernel::Mutex> lock; static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event -static Kernel::SharedPtr<Kernel::Event> start_event; ///< APT start event +static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event static std::vector<u8> shared_font; static u32 cpu_percent; ///< CPU time available to the running application +/// Parameter data to be returned in the next call to Glance/ReceiveParameter +static MessageParameter next_parameter; + +void SendParameter(const MessageParameter& parameter) { + next_parameter = parameter; + // 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]; @@ -47,18 +57,18 @@ void Initialize(Service::Interface* self) { cmd_buff[2] = IPC::MoveHandleDesc(2); cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); - cmd_buff[4] = Kernel::g_handle_table.Create(start_event).MoveFrom(); + cmd_buff[4] = Kernel::g_handle_table.Create(parameter_event).MoveFrom(); // TODO(bunnei): Check if these events are cleared every time Initialize is called. notification_event->Clear(); - start_event->Clear(); + parameter_event->Clear(); ASSERT_MSG((nullptr != lock), "Cannot initialize without lock"); lock->Release(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_TRACE(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags); + LOG_DEBUG(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags); } void GetSharedFont(Service::Interface* self) { @@ -85,9 +95,6 @@ void GetSharedFont(Service::Interface* self) { void NotifyToWait(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; - // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further. - start_event->Signal(); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); } @@ -100,7 +107,7 @@ void GetLockHandle(Service::Interface* self) { // Not sure what these parameters are used for, but retail apps check that they are 0 after // GetLockHandle has been called. - cmd_buff[2] = 0; + cmd_buff[2] = 0; // Applet Attributes, this value is passed to Enable. cmd_buff[3] = 0; cmd_buff[4] = 0; @@ -110,9 +117,10 @@ void GetLockHandle(Service::Interface* self) { void Enable(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for? + u32 attributes = cmd_buff[1]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); + parameter_event->Signal(); // Let the application know that it has been started + LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); } void GetAppletManInfo(Service::Interface* self) { @@ -121,8 +129,8 @@ void GetAppletManInfo(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = 0; cmd_buff[3] = 0; - cmd_buff[4] = static_cast<u32>(AppID::HomeMenu); // Home menu AppID - cmd_buff[5] = static_cast<u32>(AppID::Application); // TODO(purpasmart96): Do this correctly + cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID + cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); } @@ -131,7 +139,13 @@ void IsRegistered(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] = 1; // Set to registered + /// TODO(Subv): It is currently unknown what this value (0x400) means, + /// but i believe it is used as a global "LibraryApplet" id, to verify if there's + /// any LibApplet currently running. This is not verified. + if (app_id != 0x400) + cmd_buff[2] = 1; // Set to registered + else + cmd_buff[2] = 0; // Set to not registered LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); } @@ -145,50 +159,82 @@ void InquireNotification(Service::Interface* self) { void SendParameter(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 src_app_id = cmd_buff[1]; - u32 dst_app_id = cmd_buff[2]; - u32 signal_type = cmd_buff[3]; - u32 buffer_size = cmd_buff[4]; - u32 value = cmd_buff[5]; - u32 handle = cmd_buff[6]; - u32 size = cmd_buff[7]; - u32 in_param_buffer_ptr = cmd_buff[8]; + u32 src_app_id = cmd_buff[1]; + u32 dst_app_id = cmd_buff[2]; + u32 signal_type = cmd_buff[3]; + u32 buffer_size = cmd_buff[4]; + u32 value = cmd_buff[5]; + u32 handle = cmd_buff[6]; + u32 size = cmd_buff[7]; + u32 buffer = cmd_buff[8]; + + std::shared_ptr<HLE::Applets::Applet> dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); + + if (dest_applet == nullptr) { + LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); + cmd_buff[1] = -1; // TODO(Subv): Find the right error code + return; + } - cmd_buff[1] = RESULT_SUCCESS.raw; // No error + MessageParameter param; + param.buffer_size = buffer_size; + param.destination_id = dst_app_id; + param.sender_id = src_app_id; + param.object = Kernel::g_handle_table.GetGeneric(handle); + param.signal = signal_type; + param.data = Memory::GetPointer(buffer); + + cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", - src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, in_param_buffer_ptr); + src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); } 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]; + cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; - cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type - cmd_buff[4] = 0x10; // Parameter buffer size (16) - cmd_buff[5] = 0; + cmd_buff[2] = next_parameter.sender_id; + cmd_buff[3] = next_parameter.signal; // Signal type + cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size + cmd_buff[5] = 0x10; cmd_buff[6] = 0; - cmd_buff[7] = 0; - LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); + if (next_parameter.object != nullptr) + cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); + cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; + cmd_buff[8] = buffer; + + if (next_parameter.data) + memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); + + LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); } 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]; cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; - cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type - cmd_buff[4] = 0x10; // Parameter buffer size (16) - cmd_buff[5] = 0; + cmd_buff[2] = next_parameter.sender_id; + cmd_buff[3] = next_parameter.signal; // Signal type + cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size + cmd_buff[5] = 0x10; cmd_buff[6] = 0; - cmd_buff[7] = 0; + if (next_parameter.object != nullptr) + cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); + cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; + cmd_buff[8] = buffer; + + if (next_parameter.data) + memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); - LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); + LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); } void CancelParameter(Service::Interface* self) { @@ -240,7 +286,7 @@ 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 unk = cmd_buff[1]; + u32 command = cmd_buff[1]; u32 buffer1_size = cmd_buff[2]; u32 buffer2_size = cmd_buff[3]; u32 buffer1_addr = cmd_buff[5]; @@ -248,8 +294,8 @@ void AppletUtility(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " - "buffer1_addr=0x%08X, buffer2_addr=0x%08X", unk, buffer1_size, buffer2_size, + 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); } @@ -281,11 +327,41 @@ void GetAppCpuTimeLimit(Service::Interface* self) { LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value); } +void PrepareToStartLibraryApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); + cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; + LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); +} + +void StartLibraryApplet(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); + std::shared_ptr<HLE::Applets::Applet> applet = HLE::Applets::Applet::Get(applet_id); + + LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); + + if (applet == nullptr) { + LOG_ERROR(Service_APT, "unknown applet id=%08X", applet_id); + cmd_buff[1] = -1; // TODO(Subv): Find the right error code + return; + } + + AppletStartupParameter parameter; + parameter.buffer_size = cmd_buff[2]; + parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); + parameter.data = Memory::GetPointer(cmd_buff[6]); + + cmd_buff[1] = applet->Start(parameter).raw; +} + void Init() { AddService(new APT_A_Interface); AddService(new APT_S_Interface); AddService(new APT_U_Interface); + HLE::Applets::Init(); + // Load the shared system font (if available). // The expected format is a decrypted, uncompressed BCFNT file with the 0x80 byte header // generated by the APT:U service. The best way to get is by dumping it from RAM. We've provided @@ -318,7 +394,10 @@ void Init() { // TODO(bunnei): Check if these are created in Initialize or on APT process startup. notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification"); - start_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Start"); + parameter_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Start"); + + next_parameter.signal = static_cast<u32>(SignalType::AppJustStarted); + next_parameter.destination_id = 0x300; } void Shutdown() { @@ -326,7 +405,8 @@ void Shutdown() { shared_font_mem = nullptr; lock = nullptr; notification_event = nullptr; - start_event = nullptr; + parameter_event = nullptr; + HLE::Applets::Shutdown(); } } // namespace APT diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index a03e1712a..9f0802508 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -11,6 +11,23 @@ namespace Service { namespace APT { +/// Holds information about the parameters used in Send/Glance/ReceiveParameter +struct MessageParameter { + u32 sender_id = 0; + u32 destination_id = 0; + u32 signal = 0; + u32 buffer_size = 0; + Kernel::SharedPtr<Kernel::Object> object = nullptr; + u8* data = nullptr; +}; + +/// Holds information about the parameters used in StartLibraryApplet +struct AppletStartupParameter { + u32 buffer_size = 0; + Kernel::SharedPtr<Kernel::Object> object = nullptr; + u8* data = nullptr; +}; + /// Signals used by APT functions enum class SignalType : u32 { None = 0x0, @@ -23,7 +40,7 @@ enum class SignalType : u32 { }; /// App Id's used by APT functions -enum class AppID : u32 { +enum class AppletId : u32 { HomeMenu = 0x101, AlternateMenu = 0x103, Camera = 0x110, @@ -45,6 +62,9 @@ enum class AppID : u32 { SoftwareKeyboard2 = 0x401, }; +/// Send a parameter to the currently-running application, which will read it via ReceiveParameter +void SendParameter(const MessageParameter& parameter); + /** * APT::Initialize service function * Service function that initializes the APT process for the running application @@ -249,6 +269,33 @@ void SetAppCpuTimeLimit(Service::Interface* self); */ void GetAppCpuTimeLimit(Service::Interface* self); +/** + * APT::PrepareToStartLibraryApplet service function + * Inputs: + * 0 : Command header [0x00180040] + * 1 : Id of the applet to start + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +void PrepareToStartLibraryApplet(Service::Interface* self); + +/** + * APT::StartLibraryApplet service function + * Inputs: + * 0 : Command header [0x001E0084] + * 1 : Id of the applet to start + * 2 : Buffer size + * 3 : Always 0? + * 4 : Handle passed to the applet + * 5 : (Size << 14) | 2 + * 6 : Input buffer virtual address + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +void StartLibraryApplet(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 864934245..88de339f9 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -10,19 +10,24 @@ namespace Service { namespace APT { const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, GetLockHandle, "GetLockHandle?"}, - {0x00020080, Initialize, "Initialize?"}, - {0x00030040, Enable, "Enable?"}, - {0x00040040, nullptr, "Finalize?"}, - {0x00050040, nullptr, "GetAppletManInfo?"}, - {0x00060040, nullptr, "GetAppletInfo?"}, - {0x000D0080, ReceiveParameter, "ReceiveParameter?"}, - {0x000E0080, GlanceParameter, "GlanceParameter?"}, - {0x003B0040, nullptr, "CancelLibraryApplet?"}, - {0x00430040, NotifyToWait, "NotifyToWait?"}, - {0x00440000, GetSharedFont, "GetSharedFont?"}, - {0x004B00C2, AppletUtility, "AppletUtility?"}, - {0x00550040, nullptr, "WriteInputToNsState?"}, + {0x00010040, GetLockHandle, "GetLockHandle?"}, + {0x00020080, Initialize, "Initialize?"}, + {0x00030040, Enable, "Enable?"}, + {0x00040040, nullptr, "Finalize?"}, + {0x00050040, nullptr, "GetAppletManInfo?"}, + {0x00060040, nullptr, "GetAppletInfo?"}, + {0x00090040, IsRegistered, "IsRegistered"}, + {0x000C0104, SendParameter, "SendParameter"}, + {0x000D0080, ReceiveParameter, "ReceiveParameter"}, + {0x000E0080, GlanceParameter, "GlanceParameter"}, + {0x000F0100, CancelParameter, "CancelParameter"}, + {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, + {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, + {0x003B0040, nullptr, "CancelLibraryApplet?"}, + {0x00430040, NotifyToWait, "NotifyToWait?"}, + {0x00440000, GetSharedFont, "GetSharedFont?"}, + {0x004B00C2, AppletUtility, "AppletUtility?"}, + {0x00550040, nullptr, "WriteInputToNsState?"}, }; 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 d006b5930..b724cd72b 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -35,13 +35,13 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00150140, nullptr, "PrepareToStartApplication"}, {0x00160040, nullptr, "PreloadLibraryApplet"}, {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, - {0x00180040, nullptr, "PrepareToStartLibraryApplet"}, + {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x00190040, nullptr, "PrepareToStartSystemApplet"}, {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, {0x001B00C4, nullptr, "StartApplication"}, {0x001C0000, nullptr, "WakeupApplication"}, {0x001D0000, nullptr, "CancelApplication"}, - {0x001E0084, nullptr, "StartLibraryApplet"}, + {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, {0x001F0084, nullptr, "StartSystemApplet"}, {0x00200044, nullptr, "StartNewestHomeMenu"}, {0x00210000, nullptr, "OrderToCloseApplication"}, |