From 0df9c344105a4aad4d6750d0db4e79e546500d77 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Mon, 10 Nov 2014 23:30:17 -0500
Subject: [PATCH 1/4] APT_U: Fixes for GetLockHandle to boot system titles.

- Also added comment to GetLockHandle function.
---
 src/core/hle/service/apt_u.cpp | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 617b6add4a..5d7f0bac98 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -15,6 +15,8 @@
 
 namespace APT_U {
 
+static Handle lock_handle = 0;
+
 /// Signals used by APT functions
 enum class SignalType : u32 {
     None            = 0x0,
@@ -39,8 +41,21 @@ void Initialize(Service::Interface* self) {
 void GetLockHandle(Service::Interface* self) {
     u32* cmd_buff = Service::GetCommandBuffer();
     u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
+
+    if (0 == lock_handle) {
+        // TODO(bunnei): Verify if this is created here or at application boot?
+        lock_handle = Kernel::CreateMutex(false, "APT_U:Lock");
+        Kernel::ReleaseMutex(lock_handle);
+    }
     cmd_buff[1] = 0; // No error
-    cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock");
+
+    // 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[3] = 0;
+    cmd_buff[4] = 0;
+
+    cmd_buff[5] = lock_handle;
     DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]);
 }
 
@@ -191,6 +206,8 @@ const Interface::FunctionInfo FunctionTable[] = {
 
 Interface::Interface() {
     Register(FunctionTable, ARRAY_SIZE(FunctionTable));
+
+    lock_handle = 0;
 }
 
 Interface::~Interface() {

From 8eced1b6976a0f074dc87cf486cd4c092d3bd35c Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 11 Nov 2014 00:12:10 -0500
Subject: [PATCH 2/4] APT_U: Release service lock on initialization.

---
 src/core/hle/service/apt_u.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 5d7f0bac98..4997a681ea 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -34,7 +34,11 @@ void Initialize(Service::Interface* self) {
     Kernel::SetEventLocked(cmd_buff[3], true);
     Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event
 
+    _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock");
+    Kernel::ReleaseMutex(lock_handle);
+
     cmd_buff[1] = 0; // No error
+
     DEBUG_LOG(KERNEL, "called");
 }
 

From 19cfcfe8c0e76659a1b991446cd888d9c2c58e82 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 11 Nov 2014 00:25:35 -0500
Subject: [PATCH 3/4] APT_U: Set a valid parameter buffer size in
 GlanceParameter.

- Also Clarified GlanceParameter/ReceiveParameter documentation.
---
 src/core/hle/service/apt_u.cpp | 56 +++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 17 deletions(-)

diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 4997a681ea..9cac9aef95 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -78,6 +78,25 @@ void InquireNotification(Service::Interface* self) {
     WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id);
 }
 
+/**
+ * APT_U::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.
+ * 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
+ * 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
+ */
 void ReceiveParameter(Service::Interface* self) {
     u32* cmd_buff = Service::GetCommandBuffer();
     u32 app_id = cmd_buff[1];
@@ -85,7 +104,7 @@ void ReceiveParameter(Service::Interface* self) {
     cmd_buff[1] = 0; // No error
     cmd_buff[2] = 0;
     cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type
-    cmd_buff[4] = 0x10;
+    cmd_buff[4] = 0x10; // Parameter buffer size (16)
     cmd_buff[5] = 0;
     cmd_buff[6] = 0;
     cmd_buff[7] = 0;
@@ -93,32 +112,35 @@ void ReceiveParameter(Service::Interface* self) {
 }
 
 /**
-* APT_U::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
-* 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
-*/
+ * APT_U::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.
+ * 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
+ * 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
+ */
 void GlanceParameter(Service::Interface* self) {
     u32* cmd_buff = Service::GetCommandBuffer();
     u32 app_id = cmd_buff[1];
     u32 buffer_size = cmd_buff[2];
+
     cmd_buff[1] = 0; // No error
     cmd_buff[2] = 0;
     cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type
-    cmd_buff[4] = 0;
+    cmd_buff[4] = 0x10; // Parameter buffer size (16)
     cmd_buff[5] = 0;
     cmd_buff[6] = 0;
     cmd_buff[7] = 0;
-    cmd_buff[8] = 0;
+
     WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
 }
 

From 9fb549cb845e275b8f2a3a69368ee363dca9dc20 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 11 Nov 2014 00:32:18 -0500
Subject: [PATCH 4/4] APT_U: Added stub for function AppletUtility.

---
 src/core/hle/service/apt_u.cpp | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 9cac9aef95..4f41ec5f4c 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -144,6 +144,34 @@ void GlanceParameter(Service::Interface* self) {
     WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
 }
 
+/**
+ * APT_U::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)
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void AppletUtility(Service::Interface* self) {
+    u32* cmd_buff = Service::GetCommandBuffer();
+
+    // These are from 3dbrew - I'm not really sure what they're used for.
+    u32 unk = 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];
+
+    cmd_buff[1] = 0; // No error
+
+    WARN_LOG(KERNEL, "(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, 
+             buffer1_addr, buffer2_addr);
+}
+
 const Interface::FunctionInfo FunctionTable[] = {
     {0x00010040, GetLockHandle,         "GetLockHandle"},
     {0x00020080, Initialize,            "Initialize"},
@@ -219,7 +247,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00480100, nullptr,               "GetProgramInfo"},
     {0x00490180, nullptr,               "Reboot"},
     {0x004A0040, nullptr,               "GetCaptureInfo"},
-    {0x004B00C2, nullptr,               "AppletUtility"},
+    {0x004B00C2, AppletUtility,         "AppletUtility"},
     {0x004C0000, nullptr,               "SetFatalErrDispMode"},
     {0x004D0080, nullptr,               "GetAppletProgramInfo"},
     {0x004E0000, nullptr,               "HardwareResetAsync"},