diff options
| -rw-r--r-- | src/core/hle/service/apt_u.cpp | 109 |
1 files changed, 90 insertions, 19 deletions
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 617b6add4..4f41ec5f4 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | namespace APT_U { | 16 | namespace APT_U { |
| 17 | 17 | ||
| 18 | static Handle lock_handle = 0; | ||
| 19 | |||
| 18 | /// Signals used by APT functions | 20 | /// Signals used by APT functions |
| 19 | enum class SignalType : u32 { | 21 | enum class SignalType : u32 { |
| 20 | None = 0x0, | 22 | None = 0x0, |
| @@ -32,15 +34,32 @@ void Initialize(Service::Interface* self) { | |||
| 32 | Kernel::SetEventLocked(cmd_buff[3], true); | 34 | Kernel::SetEventLocked(cmd_buff[3], true); |
| 33 | Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event | 35 | Kernel::SetEventLocked(cmd_buff[4], false); // Fire start event |
| 34 | 36 | ||
| 37 | _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock"); | ||
| 38 | Kernel::ReleaseMutex(lock_handle); | ||
| 39 | |||
| 35 | cmd_buff[1] = 0; // No error | 40 | cmd_buff[1] = 0; // No error |
| 41 | |||
| 36 | DEBUG_LOG(KERNEL, "called"); | 42 | DEBUG_LOG(KERNEL, "called"); |
| 37 | } | 43 | } |
| 38 | 44 | ||
| 39 | void GetLockHandle(Service::Interface* self) { | 45 | void GetLockHandle(Service::Interface* self) { |
| 40 | u32* cmd_buff = Service::GetCommandBuffer(); | 46 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 41 | u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field | 47 | u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field |
| 48 | |||
| 49 | if (0 == lock_handle) { | ||
| 50 | // TODO(bunnei): Verify if this is created here or at application boot? | ||
| 51 | lock_handle = Kernel::CreateMutex(false, "APT_U:Lock"); | ||
| 52 | Kernel::ReleaseMutex(lock_handle); | ||
| 53 | } | ||
| 42 | cmd_buff[1] = 0; // No error | 54 | cmd_buff[1] = 0; // No error |
| 43 | cmd_buff[5] = Kernel::CreateMutex(false, "APT_U:Lock"); | 55 | |
| 56 | // Not sure what these parameters are used for, but retail apps check that they are 0 after | ||
| 57 | // GetLockHandle has been called. | ||
| 58 | cmd_buff[2] = 0; | ||
| 59 | cmd_buff[3] = 0; | ||
| 60 | cmd_buff[4] = 0; | ||
| 61 | |||
| 62 | cmd_buff[5] = lock_handle; | ||
| 44 | DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); | 63 | DEBUG_LOG(KERNEL, "called handle=0x%08X", cmd_buff[5]); |
| 45 | } | 64 | } |
| 46 | 65 | ||
| @@ -59,6 +78,25 @@ void InquireNotification(Service::Interface* self) { | |||
| 59 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id); | 78 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X", app_id); |
| 60 | } | 79 | } |
| 61 | 80 | ||
| 81 | /** | ||
| 82 | * APT_U::ReceiveParameter service function. This returns the current parameter data from NS state, | ||
| 83 | * from the source process which set the parameters. Once finished, NS will clear a flag in the NS | ||
| 84 | * state so that this command will return an error if this command is used again if parameters were | ||
| 85 | * not set again. This is called when the second Initialize event is triggered. It returns a signal | ||
| 86 | * type indicating why it was triggered. | ||
| 87 | * Inputs: | ||
| 88 | * 1 : AppID | ||
| 89 | * 2 : Parameter buffer size, max size is 0x1000 | ||
| 90 | * Outputs: | ||
| 91 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 92 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | ||
| 93 | * 3 : Unknown, for now assume Signal type | ||
| 94 | * 4 : Actual parameter buffer size, this is <= to the the input size | ||
| 95 | * 5 : Value | ||
| 96 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | ||
| 97 | * 7 : Size | ||
| 98 | * 8 : Output parameter buffer ptr | ||
| 99 | */ | ||
| 62 | void ReceiveParameter(Service::Interface* self) { | 100 | void ReceiveParameter(Service::Interface* self) { |
| 63 | u32* cmd_buff = Service::GetCommandBuffer(); | 101 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 64 | u32 app_id = cmd_buff[1]; | 102 | u32 app_id = cmd_buff[1]; |
| @@ -66,7 +104,7 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 66 | cmd_buff[1] = 0; // No error | 104 | cmd_buff[1] = 0; // No error |
| 67 | cmd_buff[2] = 0; | 105 | cmd_buff[2] = 0; |
| 68 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type | 106 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type |
| 69 | cmd_buff[4] = 0x10; | 107 | cmd_buff[4] = 0x10; // Parameter buffer size (16) |
| 70 | cmd_buff[5] = 0; | 108 | cmd_buff[5] = 0; |
| 71 | cmd_buff[6] = 0; | 109 | cmd_buff[6] = 0; |
| 72 | cmd_buff[7] = 0; | 110 | cmd_buff[7] = 0; |
| @@ -74,35 +112,66 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 74 | } | 112 | } |
| 75 | 113 | ||
| 76 | /** | 114 | /** |
| 77 | * APT_U::GlanceParameter service function | 115 | * APT_U::GlanceParameter service function. This is exactly the same as APT_U::ReceiveParameter |
| 78 | * Inputs: | 116 | * (except for the word value prior to the output handle), except this will not clear the flag |
| 79 | * 1 : AppID | 117 | * (except when responseword[3]==8 || responseword[3]==9) in NS state. |
| 80 | * 2 : Parameter buffer size, max size is 0x1000 | 118 | * Inputs: |
| 81 | * Outputs: | 119 | * 1 : AppID |
| 82 | * 1 : Result of function, 0 on success, otherwise error code | 120 | * 2 : Parameter buffer size, max size is 0x1000 |
| 83 | * 2 : Unknown, for now assume AppID of the process which sent these parameters | 121 | * Outputs: |
| 84 | * 3 : Unknown, for now assume Signal type | 122 | * 1 : Result of function, 0 on success, otherwise error code |
| 85 | * 4 : Actual parameter buffer size, this is <= to the the input size | 123 | * 2 : Unknown, for now assume AppID of the process which sent these parameters |
| 86 | * 5 : Value | 124 | * 3 : Unknown, for now assume Signal type |
| 87 | * 6 : Handle from the source process which set the parameters, likely used for shared memory | 125 | * 4 : Actual parameter buffer size, this is <= to the the input size |
| 88 | * 7 : Size | 126 | * 5 : Value |
| 89 | * 8 : Output parameter buffer ptr | 127 | * 6 : Handle from the source process which set the parameters, likely used for shared memory |
| 90 | */ | 128 | * 7 : Size |
| 129 | * 8 : Output parameter buffer ptr | ||
| 130 | */ | ||
| 91 | void GlanceParameter(Service::Interface* self) { | 131 | void GlanceParameter(Service::Interface* self) { |
| 92 | u32* cmd_buff = Service::GetCommandBuffer(); | 132 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 93 | u32 app_id = cmd_buff[1]; | 133 | u32 app_id = cmd_buff[1]; |
| 94 | u32 buffer_size = cmd_buff[2]; | 134 | u32 buffer_size = cmd_buff[2]; |
| 135 | |||
| 95 | cmd_buff[1] = 0; // No error | 136 | cmd_buff[1] = 0; // No error |
| 96 | cmd_buff[2] = 0; | 137 | cmd_buff[2] = 0; |
| 97 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type | 138 | cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type |
| 98 | cmd_buff[4] = 0; | 139 | cmd_buff[4] = 0x10; // Parameter buffer size (16) |
| 99 | cmd_buff[5] = 0; | 140 | cmd_buff[5] = 0; |
| 100 | cmd_buff[6] = 0; | 141 | cmd_buff[6] = 0; |
| 101 | cmd_buff[7] = 0; | 142 | cmd_buff[7] = 0; |
| 102 | cmd_buff[8] = 0; | 143 | |
| 103 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 144 | WARN_LOG(KERNEL, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 104 | } | 145 | } |
| 105 | 146 | ||
| 147 | /** | ||
| 148 | * APT_U::AppletUtility service function | ||
| 149 | * Inputs: | ||
| 150 | * 1 : Unknown, but clearly used for something | ||
| 151 | * 2 : Buffer 1 size (purpose is unknown) | ||
| 152 | * 3 : Buffer 2 size (purpose is unknown) | ||
| 153 | * 5 : Buffer 1 address (purpose is unknown) | ||
| 154 | * 65 : Buffer 2 address (purpose is unknown) | ||
| 155 | * Outputs: | ||
| 156 | * 1 : Result of function, 0 on success, otherwise error code | ||
| 157 | */ | ||
| 158 | void AppletUtility(Service::Interface* self) { | ||
| 159 | u32* cmd_buff = Service::GetCommandBuffer(); | ||
| 160 | |||
| 161 | // These are from 3dbrew - I'm not really sure what they're used for. | ||
| 162 | u32 unk = cmd_buff[1]; | ||
| 163 | u32 buffer1_size = cmd_buff[2]; | ||
| 164 | u32 buffer2_size = cmd_buff[3]; | ||
| 165 | u32 buffer1_addr = cmd_buff[5]; | ||
| 166 | u32 buffer2_addr = cmd_buff[65]; | ||
| 167 | |||
| 168 | cmd_buff[1] = 0; // No error | ||
| 169 | |||
| 170 | WARN_LOG(KERNEL, "(STUBBED) called unk=0x%08X, buffer1_size=0x%08x, buffer2_size=0x%08x, " | ||
| 171 | "buffer1_addr=0x%08x, buffer2_addr=0x%08x", unk, buffer1_size, buffer2_size, | ||
| 172 | buffer1_addr, buffer2_addr); | ||
| 173 | } | ||
| 174 | |||
| 106 | const Interface::FunctionInfo FunctionTable[] = { | 175 | const Interface::FunctionInfo FunctionTable[] = { |
| 107 | {0x00010040, GetLockHandle, "GetLockHandle"}, | 176 | {0x00010040, GetLockHandle, "GetLockHandle"}, |
| 108 | {0x00020080, Initialize, "Initialize"}, | 177 | {0x00020080, Initialize, "Initialize"}, |
| @@ -178,7 +247,7 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 178 | {0x00480100, nullptr, "GetProgramInfo"}, | 247 | {0x00480100, nullptr, "GetProgramInfo"}, |
| 179 | {0x00490180, nullptr, "Reboot"}, | 248 | {0x00490180, nullptr, "Reboot"}, |
| 180 | {0x004A0040, nullptr, "GetCaptureInfo"}, | 249 | {0x004A0040, nullptr, "GetCaptureInfo"}, |
| 181 | {0x004B00C2, nullptr, "AppletUtility"}, | 250 | {0x004B00C2, AppletUtility, "AppletUtility"}, |
| 182 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, | 251 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, |
| 183 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, | 252 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, |
| 184 | {0x004E0000, nullptr, "HardwareResetAsync"}, | 253 | {0x004E0000, nullptr, "HardwareResetAsync"}, |
| @@ -191,6 +260,8 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 191 | 260 | ||
| 192 | Interface::Interface() { | 261 | Interface::Interface() { |
| 193 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); | 262 | Register(FunctionTable, ARRAY_SIZE(FunctionTable)); |
| 263 | |||
| 264 | lock_handle = 0; | ||
| 194 | } | 265 | } |
| 195 | 266 | ||
| 196 | Interface::~Interface() { | 267 | Interface::~Interface() { |