aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/hle/service
diff options
context:
space:
mode:
authorGravatar Subv <subv2112@gmail.com>2015-05-25 23:30:20 -0500
committerGravatar Subv <subv2112@gmail.com>2015-07-11 21:47:22 -0500
commit2a6ebadf66051362cdcf07d722f7e2d3cee14c82 (patch)
treef016b2ee81df95aabccc426762c42073d645803c /src/core/hle/service
parentb0d72e3de1ec2350716300c86bc02930893e9e23 (diff)
HLE/APT: Initial HLE support for applets.
Currently only the SWKBD is emulated, and there's currently no way to ask the user for input, so it always returns "Subv" as the text.
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/apt/apt.cpp139
-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, 173 insertions, 50 deletions
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index b454a270..0c3889e8 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(MessageParameter const& 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_WARNING(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags);
}
void GetSharedFont(Service::Interface* self) {
@@ -85,9 +95,7 @@ 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);
}
@@ -112,6 +120,7 @@ void Enable(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
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 unk=0x%08X", unk);
}
@@ -121,8 +130,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 +140,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 +160,81 @@ 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);
+ 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;
- LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
+ 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 CancelParameter(Service::Interface* self) {
@@ -281,6 +327,28 @@ void GetAppCpuTimeLimit(Service::Interface* self) {
LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value);
}
+void PrepareToStartLibraryApplet(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = HLE::Applets::Applet::Create(static_cast<AppletId>(cmd_buff[1])).raw;
+}
+
+void StartLibraryApplet(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ std::shared_ptr<HLE::Applets::Applet> applet = HLE::Applets::Applet::Get(static_cast<AppletId>(cmd_buff[1]));
+
+ if (applet == nullptr) {
+ 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);
@@ -318,7 +386,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 +397,7 @@ void Shutdown() {
shared_font_mem = nullptr;
lock = nullptr;
notification_event = nullptr;
- start_event = nullptr;
+ parameter_event = nullptr;
}
} // namespace APT
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index a03e1712..510193cc 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(MessageParameter const& 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 86493424..88de339f 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 d006b593..b724cd72 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"},