summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/apt
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/apt')
-rw-r--r--src/core/hle/service/apt/apt.cpp160
-rw-r--r--src/core/hle/service/apt/apt.h49
-rw-r--r--src/core/hle/service/apt/apt_a.cpp31
-rw-r--r--src/core/hle/service/apt/apt_u.cpp4
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"},