diff options
| -rw-r--r-- | src/core/hle/ipc_helpers.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 427 | ||||
| -rw-r--r-- | src/core/hle/service/ptm/ptm.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/service/ptm/ptm.h | 2 |
4 files changed, 258 insertions, 195 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 323158bb5..11a33c8bd 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -27,6 +27,18 @@ public: | |||
| 27 | DEBUG_ASSERT_MSG(index == TotalSize(), "Operations do not match the header (cmd 0x%x)", | 27 | DEBUG_ASSERT_MSG(index == TotalSize(), "Operations do not match the header (cmd 0x%x)", |
| 28 | header.raw); | 28 | header.raw); |
| 29 | } | 29 | } |
| 30 | |||
| 31 | /** | ||
| 32 | * @brief Retrieves the address of a static buffer, used when a buffer is needed for output | ||
| 33 | * @param buffer_id The index of the static buffer | ||
| 34 | * @param data_size If non-null, will store the size of the buffer | ||
| 35 | */ | ||
| 36 | VAddr PeekStaticBuffer(u8 buffer_id, size_t* data_size = nullptr) const { | ||
| 37 | u32* static_buffer = cmdbuf + Kernel::kStaticBuffersOffset / 4 + buffer_id * 2; | ||
| 38 | if (data_size) | ||
| 39 | *data_size = StaticBufferDescInfo{static_buffer[0]}.size; | ||
| 40 | return static_buffer[1]; | ||
| 41 | } | ||
| 30 | }; | 42 | }; |
| 31 | 43 | ||
| 32 | class RequestBuilder : public RequestHelperBase { | 44 | class RequestBuilder : public RequestHelperBase { |
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index e57b19c2d..c2098d2e8 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp | |||
| @@ -49,13 +49,13 @@ void SendParameter(const MessageParameter& parameter) { | |||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | void Initialize(Service::Interface* self) { | 51 | void Initialize(Service::Interface* self) { |
| 52 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 52 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x2, 2, 0); // 0x20080 |
| 53 | u32 app_id = cmd_buff[1]; | 53 | u32 app_id = rp.Pop<u32>(); |
| 54 | u32 flags = cmd_buff[2]; | 54 | u32 flags = rp.Pop<u32>(); |
| 55 | 55 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); | |
| 56 | cmd_buff[2] = IPC::CopyHandleDesc(2); | 56 | rb.Push(RESULT_SUCCESS); |
| 57 | cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); | 57 | rb.PushCopyHandles(Kernel::g_handle_table.Create(notification_event).MoveFrom(), |
| 58 | cmd_buff[4] = Kernel::g_handle_table.Create(parameter_event).MoveFrom(); | 58 | Kernel::g_handle_table.Create(parameter_event).MoveFrom()); |
| 59 | 59 | ||
| 60 | // TODO(bunnei): Check if these events are cleared every time Initialize is called. | 60 | // TODO(bunnei): Check if these events are cleared every time Initialize is called. |
| 61 | notification_event->Clear(); | 61 | notification_event->Clear(); |
| @@ -64,18 +64,15 @@ void Initialize(Service::Interface* self) { | |||
| 64 | ASSERT_MSG((nullptr != lock), "Cannot initialize without lock"); | 64 | ASSERT_MSG((nullptr != lock), "Cannot initialize without lock"); |
| 65 | lock->Release(); | 65 | lock->Release(); |
| 66 | 66 | ||
| 67 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | ||
| 68 | |||
| 69 | LOG_DEBUG(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags); | 67 | LOG_DEBUG(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags); |
| 70 | } | 68 | } |
| 71 | 69 | ||
| 72 | void GetSharedFont(Service::Interface* self) { | 70 | void GetSharedFont(Service::Interface* self) { |
| 73 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 71 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x44, 0, 0); // 0x00440000 |
| 74 | |||
| 75 | if (!shared_font_mem) { | 72 | if (!shared_font_mem) { |
| 76 | LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); | 73 | LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); |
| 77 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); | 74 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 78 | cmd_buff[1] = -1; // TODO: Find the right error code | 75 | rb.Push(u32(-1)); // Failure |
| 79 | return; | 76 | return; |
| 80 | } | 77 | } |
| 81 | 78 | ||
| @@ -87,103 +84,112 @@ void GetSharedFont(Service::Interface* self) { | |||
| 87 | BCFNT::RelocateSharedFont(shared_font_mem, target_address); | 84 | BCFNT::RelocateSharedFont(shared_font_mem, target_address); |
| 88 | shared_font_relocated = true; | 85 | shared_font_relocated = true; |
| 89 | } | 86 | } |
| 90 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); | 87 | |
| 91 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 88 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); |
| 89 | rb.Push(RESULT_SUCCESS); // No error | ||
| 92 | // Since the SharedMemory interface doesn't provide the address at which the memory was | 90 | // Since the SharedMemory interface doesn't provide the address at which the memory was |
| 93 | // allocated, the real APT service calculates this address by scanning the entire address space | 91 | // allocated, the real APT service calculates this address by scanning the entire address space |
| 94 | // (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font. | 92 | // (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font. |
| 95 | cmd_buff[2] = target_address; | 93 | rb.Push(target_address); |
| 96 | cmd_buff[3] = IPC::CopyHandleDesc(); | 94 | rb.PushCopyHandles(Kernel::g_handle_table.Create(shared_font_mem).MoveFrom()); |
| 97 | cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom(); | ||
| 98 | } | 95 | } |
| 99 | 96 | ||
| 100 | void NotifyToWait(Service::Interface* self) { | 97 | void NotifyToWait(Service::Interface* self) { |
| 101 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 98 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x43, 1, 0); // 0x430040 |
| 102 | u32 app_id = cmd_buff[1]; | 99 | u32 app_id = rp.Pop<u32>(); |
| 103 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 100 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 101 | rb.Push(RESULT_SUCCESS); // No error | ||
| 104 | LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); | 102 | LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); |
| 105 | } | 103 | } |
| 106 | 104 | ||
| 107 | void GetLockHandle(Service::Interface* self) { | 105 | void GetLockHandle(Service::Interface* self) { |
| 108 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 106 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1, 1, 0); // 0x10040 |
| 107 | |||
| 109 | // Bits [0:2] are the applet type (System, Library, etc) | 108 | // Bits [0:2] are the applet type (System, Library, etc) |
| 110 | // Bit 5 tells the application that there's a pending APT parameter, | 109 | // Bit 5 tells the application that there's a pending APT parameter, |
| 111 | // this will cause the app to wait until parameter_event is signaled. | 110 | // this will cause the app to wait until parameter_event is signaled. |
| 112 | u32 applet_attributes = cmd_buff[1]; | 111 | u32 applet_attributes = rp.Pop<u32>(); |
| 113 | 112 | IPC::RequestBuilder rb = rp.MakeBuilder(3, 2); | |
| 114 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 113 | rb.Push(RESULT_SUCCESS); // No error |
| 115 | 114 | rb.Push(applet_attributes); // Applet Attributes, this value is passed to Enable. | |
| 116 | cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. | 115 | rb.Push(u32(0)); // Least significant bit = power button state |
| 117 | cmd_buff[3] = 0; // Least significant bit = power button state | 116 | Kernel::Handle handleCopy = Kernel::g_handle_table.Create(lock).MoveFrom(); |
| 118 | cmd_buff[4] = IPC::CopyHandleDesc(); | 117 | rb.PushCopyHandles(handleCopy); |
| 119 | cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); | 118 | |
| 120 | 119 | LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handleCopy, | |
| 121 | LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], | ||
| 122 | applet_attributes); | 120 | applet_attributes); |
| 123 | } | 121 | } |
| 124 | 122 | ||
| 125 | void Enable(Service::Interface* self) { | 123 | void Enable(Service::Interface* self) { |
| 126 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 124 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x3, 1, 0); // 0x30040 |
| 127 | u32 attributes = cmd_buff[1]; | 125 | u32 attributes = rp.Pop<u32>(); |
| 128 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 126 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 129 | parameter_event->Signal(); // Let the application know that it has been started | 127 | rb.Push(RESULT_SUCCESS); // No error |
| 128 | parameter_event->Signal(); // Let the application know that it has been started | ||
| 130 | LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); | 129 | LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); |
| 131 | } | 130 | } |
| 132 | 131 | ||
| 133 | void GetAppletManInfo(Service::Interface* self) { | 132 | void GetAppletManInfo(Service::Interface* self) { |
| 134 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 133 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x5, 1, 0); // 0x50040 |
| 135 | u32 unk = cmd_buff[1]; | 134 | u32 unk = rp.Pop<u32>(); |
| 136 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 135 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 137 | cmd_buff[2] = 0; | 136 | rb.Push(RESULT_SUCCESS); // No error |
| 138 | cmd_buff[3] = 0; | 137 | rb.Push(u32(0)); |
| 139 | cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID | 138 | rb.Push(u32(0)); |
| 140 | cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly | 139 | rb.Push(static_cast<u32>(AppletId::HomeMenu)); // Home menu AppID |
| 140 | rb.Push(static_cast<u32>(AppletId::Application)); // TODO(purpasmart96): Do this correctly | ||
| 141 | 141 | ||
| 142 | LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); | 142 | LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | void IsRegistered(Service::Interface* self) { | 145 | void IsRegistered(Service::Interface* self) { |
| 146 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 146 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x9, 1, 0); // 0x90040 |
| 147 | u32 app_id = cmd_buff[1]; | 147 | u32 app_id = rp.Pop<u32>(); |
| 148 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 148 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |
| 149 | rb.Push(RESULT_SUCCESS); // No error | ||
| 149 | 150 | ||
| 150 | // TODO(Subv): An application is considered "registered" if it has already called APT::Enable | 151 | // TODO(Subv): An application is considered "registered" if it has already called APT::Enable |
| 151 | // handle this properly once we implement multiprocess support. | 152 | // handle this properly once we implement multiprocess support. |
| 152 | cmd_buff[2] = 0; // Set to not registered by default | 153 | u32 isRegistered = 0; // Set to not registered by default |
| 153 | 154 | ||
| 154 | if (app_id == static_cast<u32>(AppletId::AnyLibraryApplet)) { | 155 | if (app_id == static_cast<u32>(AppletId::AnyLibraryApplet)) { |
| 155 | cmd_buff[2] = HLE::Applets::IsLibraryAppletRunning() ? 1 : 0; | 156 | isRegistered = HLE::Applets::IsLibraryAppletRunning() ? 1 : 0; |
| 156 | } else if (auto applet = HLE::Applets::Applet::Get(static_cast<AppletId>(app_id))) { | 157 | } else if (auto applet = HLE::Applets::Applet::Get(static_cast<AppletId>(app_id))) { |
| 157 | cmd_buff[2] = 1; // Set to registered | 158 | isRegistered = 1; // Set to registered |
| 158 | } | 159 | } |
| 160 | rb.Push(isRegistered); | ||
| 161 | |||
| 159 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); | 162 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); |
| 160 | } | 163 | } |
| 161 | 164 | ||
| 162 | void InquireNotification(Service::Interface* self) { | 165 | void InquireNotification(Service::Interface* self) { |
| 163 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 166 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xB, 1, 0); // 0xB0040 |
| 164 | u32 app_id = cmd_buff[1]; | 167 | u32 app_id = rp.Pop<u32>(); |
| 165 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 168 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |
| 166 | cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type | 169 | rb.Push(RESULT_SUCCESS); // No error |
| 170 | rb.Push(static_cast<u32>(SignalType::None)); // Signal type | ||
| 167 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); | 171 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); |
| 168 | } | 172 | } |
| 169 | 173 | ||
| 170 | void SendParameter(Service::Interface* self) { | 174 | void SendParameter(Service::Interface* self) { |
| 171 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 175 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xC, 4, 4); // 0xC0104 |
| 172 | u32 src_app_id = cmd_buff[1]; | 176 | u32 src_app_id = rp.Pop<u32>(); |
| 173 | u32 dst_app_id = cmd_buff[2]; | 177 | u32 dst_app_id = rp.Pop<u32>(); |
| 174 | u32 signal_type = cmd_buff[3]; | 178 | u32 signal_type = rp.Pop<u32>(); |
| 175 | u32 buffer_size = cmd_buff[4]; | 179 | u32 buffer_size = rp.Pop<u32>(); |
| 176 | u32 value = cmd_buff[5]; | 180 | u32 value = rp.Pop<u32>(); |
| 177 | u32 handle = cmd_buff[6]; | 181 | u32 handle = rp.Pop<u32>(); |
| 178 | u32 size = cmd_buff[7]; | 182 | u32 size = rp.Pop<u32>(); |
| 179 | u32 buffer = cmd_buff[8]; | 183 | u32 buffer = rp.Pop<u32>(); |
| 180 | 184 | ||
| 181 | std::shared_ptr<HLE::Applets::Applet> dest_applet = | 185 | std::shared_ptr<HLE::Applets::Applet> dest_applet = |
| 182 | HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); | 186 | HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); |
| 183 | 187 | ||
| 188 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||
| 189 | |||
| 184 | if (dest_applet == nullptr) { | 190 | if (dest_applet == nullptr) { |
| 185 | LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); | 191 | LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); |
| 186 | cmd_buff[1] = -1; // TODO(Subv): Find the right error code | 192 | rb.Push(u32(-1)); // TODO(Subv): Find the right error code |
| 187 | return; | 193 | return; |
| 188 | } | 194 | } |
| 189 | 195 | ||
| @@ -195,7 +201,7 @@ void SendParameter(Service::Interface* self) { | |||
| 195 | param.buffer.resize(buffer_size); | 201 | param.buffer.resize(buffer_size); |
| 196 | Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); | 202 | Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); |
| 197 | 203 | ||
| 198 | cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; | 204 | rb.Push(dest_applet->ReceiveParameter(param)); |
| 199 | 205 | ||
| 200 | LOG_WARNING( | 206 | LOG_WARNING( |
| 201 | Service_APT, | 207 | Service_APT, |
| @@ -205,21 +211,28 @@ void SendParameter(Service::Interface* self) { | |||
| 205 | } | 211 | } |
| 206 | 212 | ||
| 207 | void ReceiveParameter(Service::Interface* self) { | 213 | void ReceiveParameter(Service::Interface* self) { |
| 208 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 214 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xD, 2, 0); // 0xD0080 |
| 209 | u32 app_id = cmd_buff[1]; | 215 | u32 app_id = rp.Pop<u32>(); |
| 210 | u32 buffer_size = cmd_buff[2]; | 216 | u32 buffer_size = rp.Pop<u32>(); |
| 211 | VAddr buffer = cmd_buff[0x104 >> 2]; | 217 | |
| 212 | 218 | size_t static_buff_size; | |
| 213 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 219 | VAddr buffer = rp.PeekStaticBuffer(0, &static_buff_size); |
| 214 | cmd_buff[2] = next_parameter.sender_id; | 220 | if (buffer_size > static_buff_size) |
| 215 | cmd_buff[3] = next_parameter.signal; // Signal type | 221 | LOG_WARNING(Service_APT, "ReceiveParameter: buffer_size is bigger than the size in the " |
| 216 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size | 222 | "buffer descriptor (0x%08X > 0x%08X)", |
| 217 | cmd_buff[5] = 0x10; | 223 | buffer_size, static_buff_size); |
| 218 | cmd_buff[6] = 0; | 224 | |
| 219 | if (next_parameter.object != nullptr) | 225 | IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); |
| 220 | cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); | 226 | rb.Push(RESULT_SUCCESS); // No error |
| 221 | cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; | 227 | rb.Push(next_parameter.sender_id); |
| 222 | cmd_buff[8] = buffer; | 228 | rb.Push(next_parameter.signal); // Signal type |
| 229 | ASSERT_MSG(next_parameter.buffer.size() <= buffer_size, "Input static buffer is too small !"); | ||
| 230 | rb.Push(u32(next_parameter.buffer.size())); // Parameter buffer size | ||
| 231 | |||
| 232 | rb.PushMoveHandles((next_parameter.object != nullptr) | ||
| 233 | ? Kernel::g_handle_table.Create(next_parameter.object).MoveFrom() | ||
| 234 | : 0); | ||
| 235 | rb.PushStaticBuffer(buffer, next_parameter.buffer.size(), 0); | ||
| 223 | 236 | ||
| 224 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); | 237 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); |
| 225 | 238 | ||
| @@ -227,56 +240,64 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 227 | } | 240 | } |
| 228 | 241 | ||
| 229 | void GlanceParameter(Service::Interface* self) { | 242 | void GlanceParameter(Service::Interface* self) { |
| 230 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 243 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xE, 2, 0); // 0xE0080 |
| 231 | u32 app_id = cmd_buff[1]; | 244 | u32 app_id = rp.Pop<u32>(); |
| 232 | u32 buffer_size = cmd_buff[2]; | 245 | u32 buffer_size = rp.Pop<u32>(); |
| 233 | VAddr buffer = cmd_buff[0x104 >> 2]; | 246 | |
| 234 | 247 | size_t static_buff_size; | |
| 235 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 248 | VAddr buffer = rp.PeekStaticBuffer(0, &static_buff_size); |
| 236 | cmd_buff[2] = next_parameter.sender_id; | 249 | if (buffer_size > static_buff_size) |
| 237 | cmd_buff[3] = next_parameter.signal; // Signal type | 250 | LOG_WARNING(Service_APT, "ReceiveParameter: buffer_size is bigger than the size in the " |
| 238 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size | 251 | "buffer descriptor (0x%08X > 0x%08X)", |
| 239 | cmd_buff[5] = 0x10; | 252 | buffer_size, static_buff_size); |
| 240 | cmd_buff[6] = 0; | 253 | |
| 241 | if (next_parameter.object != nullptr) | 254 | IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); |
| 242 | cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); | 255 | rb.Push(RESULT_SUCCESS); // No error |
| 243 | cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; | 256 | rb.Push(next_parameter.sender_id); |
| 244 | cmd_buff[8] = buffer; | 257 | rb.Push(next_parameter.signal); // Signal type |
| 245 | 258 | ASSERT_MSG(next_parameter.buffer.size() <= buffer_size, "Input static buffer is too small !"); | |
| 246 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), | 259 | rb.Push(u32(next_parameter.buffer.size())); // Parameter buffer size |
| 247 | std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); | 260 | |
| 261 | rb.PushCopyHandles((next_parameter.object != nullptr) | ||
| 262 | ? Kernel::g_handle_table.Create(next_parameter.object).MoveFrom() | ||
| 263 | : 0); | ||
| 264 | rb.PushStaticBuffer(buffer, next_parameter.buffer.size(), 0); | ||
| 265 | |||
| 266 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); | ||
| 248 | 267 | ||
| 249 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 268 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 250 | } | 269 | } |
| 251 | 270 | ||
| 252 | void CancelParameter(Service::Interface* self) { | 271 | void CancelParameter(Service::Interface* self) { |
| 253 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 272 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xF, 4, 0); // 0xF0100 |
| 254 | u32 flag1 = cmd_buff[1]; | ||
| 255 | u32 unk = cmd_buff[2]; | ||
| 256 | u32 flag2 = cmd_buff[3]; | ||
| 257 | u32 app_id = cmd_buff[4]; | ||
| 258 | 273 | ||
| 259 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 274 | u32 check_sender = rp.Pop<u32>(); |
| 260 | cmd_buff[2] = 1; // Set to Success | 275 | u32 sender_appid = rp.Pop<u32>(); |
| 276 | u32 check_receiver = rp.Pop<u32>(); | ||
| 277 | u32 receiver_appid = rp.Pop<u32>(); | ||
| 278 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||
| 279 | rb.Push(RESULT_SUCCESS); // No error | ||
| 280 | rb.Push(u32(1)); // Set to Success | ||
| 261 | 281 | ||
| 262 | LOG_WARNING(Service_APT, | 282 | LOG_WARNING(Service_APT, "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, " |
| 263 | "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", flag1, | 283 | "check_receiver=0x%08X, receiver_appid=0x%08X", |
| 264 | unk, flag2, app_id); | 284 | check_sender, sender_appid, check_receiver, receiver_appid); |
| 265 | } | 285 | } |
| 266 | 286 | ||
| 267 | void PrepareToStartApplication(Service::Interface* self) { | 287 | void PrepareToStartApplication(Service::Interface* self) { |
| 268 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 288 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x00150140); |
| 269 | u32 title_info1 = cmd_buff[1]; | 289 | u32 title_info1 = rp.Pop<u32>(); |
| 270 | u32 title_info2 = cmd_buff[2]; | 290 | u32 title_info2 = rp.Pop<u32>(); |
| 271 | u32 title_info3 = cmd_buff[3]; | 291 | u32 title_info3 = rp.Pop<u32>(); |
| 272 | u32 title_info4 = cmd_buff[4]; | 292 | u32 title_info4 = rp.Pop<u32>(); |
| 273 | u32 flags = cmd_buff[5]; | 293 | u32 flags = rp.Pop<u32>(); |
| 274 | 294 | ||
| 275 | if (flags & 0x00000100) { | 295 | if (flags & 0x00000100) { |
| 276 | unknown_ns_state_field = 1; | 296 | unknown_ns_state_field = 1; |
| 277 | } | 297 | } |
| 278 | 298 | ||
| 279 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 299 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 300 | rb.Push(RESULT_SUCCESS); // No error | ||
| 280 | 301 | ||
| 281 | LOG_WARNING(Service_APT, | 302 | LOG_WARNING(Service_APT, |
| 282 | "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," | 303 | "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," |
| @@ -285,16 +306,17 @@ void PrepareToStartApplication(Service::Interface* self) { | |||
| 285 | } | 306 | } |
| 286 | 307 | ||
| 287 | void StartApplication(Service::Interface* self) { | 308 | void StartApplication(Service::Interface* self) { |
| 288 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 309 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x001B00C4); |
| 289 | u32 buffer1_size = cmd_buff[1]; | 310 | u32 buffer1_size = rp.Pop<u32>(); |
| 290 | u32 buffer2_size = cmd_buff[2]; | 311 | u32 buffer2_size = rp.Pop<u32>(); |
| 291 | u32 flag = cmd_buff[3]; | 312 | u32 flag = rp.Pop<u32>(); |
| 292 | u32 size1 = cmd_buff[4]; | 313 | u32 size1 = rp.Pop<u32>(); |
| 293 | u32 buffer1_ptr = cmd_buff[5]; | 314 | u32 buffer1_ptr = rp.Pop<u32>(); |
| 294 | u32 size2 = cmd_buff[6]; | 315 | u32 size2 = rp.Pop<u32>(); |
| 295 | u32 buffer2_ptr = cmd_buff[7]; | 316 | u32 buffer2_ptr = rp.Pop<u32>(); |
| 296 | 317 | ||
| 297 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 318 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 319 | rb.Push(RESULT_SUCCESS); // No error | ||
| 298 | 320 | ||
| 299 | LOG_WARNING(Service_APT, | 321 | LOG_WARNING(Service_APT, |
| 300 | "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," | 322 | "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," |
| @@ -303,154 +325,170 @@ void StartApplication(Service::Interface* self) { | |||
| 303 | } | 325 | } |
| 304 | 326 | ||
| 305 | void AppletUtility(Service::Interface* self) { | 327 | void AppletUtility(Service::Interface* self) { |
| 306 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 328 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x004B00C2); |
| 307 | 329 | ||
| 308 | // These are from 3dbrew - I'm not really sure what they're used for. | 330 | // These are from 3dbrew - I'm not really sure what they're used for. |
| 309 | u32 command = cmd_buff[1]; | 331 | u32 utility_command = rp.Pop<u32>(); |
| 310 | u32 buffer1_size = cmd_buff[2]; | 332 | u32 input_size = rp.Pop<u32>(); |
| 311 | u32 buffer2_size = cmd_buff[3]; | 333 | u32 output_size = rp.Pop<u32>(); |
| 312 | u32 buffer1_addr = cmd_buff[5]; | 334 | VAddr input_addr = rp.PopStaticBuffer(); |
| 313 | u32 buffer2_addr = cmd_buff[65]; | ||
| 314 | 335 | ||
| 315 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 336 | VAddr output_addr = rp.PeekStaticBuffer(0); |
| 337 | |||
| 338 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||
| 339 | rb.Push(RESULT_SUCCESS); // No error | ||
| 316 | 340 | ||
| 317 | LOG_WARNING(Service_APT, | 341 | LOG_WARNING(Service_APT, |
| 318 | "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " | 342 | "(STUBBED) called command=0x%08X, input_size=0x%08X, output_size=0x%08X, " |
| 319 | "buffer1_addr=0x%08X, buffer2_addr=0x%08X", | 343 | "input_addr=0x%08X, output_addr=0x%08X", |
| 320 | command, buffer1_size, buffer2_size, buffer1_addr, buffer2_addr); | 344 | utility_command, input_size, output_size, input_addr, output_addr); |
| 321 | } | 345 | } |
| 322 | 346 | ||
| 323 | void SetAppCpuTimeLimit(Service::Interface* self) { | 347 | void SetAppCpuTimeLimit(Service::Interface* self) { |
| 324 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 348 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x4F, 2, 0); // 0x4F0080 |
| 325 | u32 value = cmd_buff[1]; | 349 | u32 value = rp.Pop<u32>(); |
| 326 | cpu_percent = cmd_buff[2]; | 350 | cpu_percent = rp.Pop<u32>(); |
| 327 | 351 | ||
| 328 | if (value != 1) { | 352 | if (value != 1) { |
| 329 | LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value); | 353 | LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value); |
| 330 | } | 354 | } |
| 331 | 355 | ||
| 332 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 356 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 357 | rb.Push(RESULT_SUCCESS); // No error | ||
| 333 | 358 | ||
| 334 | LOG_WARNING(Service_APT, "(STUBBED) called cpu_percent=%u, value=%u", cpu_percent, value); | 359 | LOG_WARNING(Service_APT, "(STUBBED) called cpu_percent=%u, value=%u", cpu_percent, value); |
| 335 | } | 360 | } |
| 336 | 361 | ||
| 337 | void GetAppCpuTimeLimit(Service::Interface* self) { | 362 | void GetAppCpuTimeLimit(Service::Interface* self) { |
| 338 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 363 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x50, 1, 0); // 0x500040 |
| 339 | u32 value = cmd_buff[1]; | 364 | u32 value = rp.Pop<u32>(); |
| 340 | 365 | ||
| 341 | if (value != 1) { | 366 | if (value != 1) { |
| 342 | LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value); | 367 | LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value); |
| 343 | } | 368 | } |
| 344 | 369 | ||
| 345 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 370 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |
| 346 | cmd_buff[2] = cpu_percent; | 371 | rb.Push(RESULT_SUCCESS); // No error |
| 372 | rb.Push(cpu_percent); | ||
| 347 | 373 | ||
| 348 | LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value); | 374 | LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value); |
| 349 | } | 375 | } |
| 350 | 376 | ||
| 351 | void PrepareToStartLibraryApplet(Service::Interface* self) { | 377 | void PrepareToStartLibraryApplet(Service::Interface* self) { |
| 352 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 378 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x18, 1, 0); // 0x180040 |
| 353 | AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); | 379 | AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); |
| 380 | |||
| 381 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||
| 354 | auto applet = HLE::Applets::Applet::Get(applet_id); | 382 | auto applet = HLE::Applets::Applet::Get(applet_id); |
| 355 | if (applet) { | 383 | if (applet) { |
| 356 | LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); | 384 | LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); |
| 357 | cmd_buff[1] = RESULT_SUCCESS.raw; | 385 | rb.Push(RESULT_SUCCESS); |
| 358 | } else { | 386 | } else { |
| 359 | cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; | 387 | rb.Push(HLE::Applets::Applet::Create(applet_id)); |
| 360 | } | 388 | } |
| 361 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); | 389 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); |
| 362 | } | 390 | } |
| 363 | 391 | ||
| 364 | void PreloadLibraryApplet(Service::Interface* self) { | 392 | void PreloadLibraryApplet(Service::Interface* self) { |
| 365 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 393 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x16, 1, 0); // 0x160040 |
| 366 | AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); | 394 | AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); |
| 395 | |||
| 396 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||
| 367 | auto applet = HLE::Applets::Applet::Get(applet_id); | 397 | auto applet = HLE::Applets::Applet::Get(applet_id); |
| 368 | if (applet) { | 398 | if (applet) { |
| 369 | LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); | 399 | LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id); |
| 370 | cmd_buff[1] = RESULT_SUCCESS.raw; | 400 | rb.Push(RESULT_SUCCESS); |
| 371 | } else { | 401 | } else { |
| 372 | cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw; | 402 | rb.Push(HLE::Applets::Applet::Create(applet_id)); |
| 373 | } | 403 | } |
| 374 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); | 404 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); |
| 375 | } | 405 | } |
| 376 | 406 | ||
| 377 | void StartLibraryApplet(Service::Interface* self) { | 407 | void StartLibraryApplet(Service::Interface* self) { |
| 378 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 408 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1E, 2, 4); // 0x1E0084 |
| 379 | AppletId applet_id = static_cast<AppletId>(cmd_buff[1]); | 409 | AppletId applet_id = static_cast<AppletId>(rp.Pop<u32>()); |
| 380 | std::shared_ptr<HLE::Applets::Applet> applet = HLE::Applets::Applet::Get(applet_id); | 410 | std::shared_ptr<HLE::Applets::Applet> applet = HLE::Applets::Applet::Get(applet_id); |
| 381 | 411 | ||
| 382 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); | 412 | LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id); |
| 383 | 413 | ||
| 384 | if (applet == nullptr) { | 414 | if (applet == nullptr) { |
| 385 | LOG_ERROR(Service_APT, "unknown applet id=%08X", applet_id); | 415 | LOG_ERROR(Service_APT, "unknown applet id=%08X", applet_id); |
| 386 | cmd_buff[1] = -1; // TODO(Subv): Find the right error code | 416 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0, false); |
| 417 | rb.Push(u32(-1)); // TODO(Subv): Find the right error code | ||
| 387 | return; | 418 | return; |
| 388 | } | 419 | } |
| 389 | 420 | ||
| 390 | size_t buffer_size = cmd_buff[2]; | 421 | size_t buffer_size = rp.Pop<u32>(); |
| 391 | VAddr buffer_addr = cmd_buff[6]; | 422 | Kernel::Handle handle = rp.PopHandle(); |
| 423 | VAddr buffer_addr = rp.PopStaticBuffer(); | ||
| 392 | 424 | ||
| 393 | AppletStartupParameter parameter; | 425 | AppletStartupParameter parameter; |
| 394 | parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); | 426 | parameter.object = Kernel::g_handle_table.GetGeneric(handle); |
| 395 | parameter.buffer.resize(buffer_size); | 427 | parameter.buffer.resize(buffer_size); |
| 396 | Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); | 428 | Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); |
| 397 | 429 | ||
| 398 | cmd_buff[1] = applet->Start(parameter).raw; | 430 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 431 | rb.Push(applet->Start(parameter)); | ||
| 399 | } | 432 | } |
| 400 | 433 | ||
| 401 | void CancelLibraryApplet(Service::Interface* self) { | 434 | void CancelLibraryApplet(Service::Interface* self) { |
| 402 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 435 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x3B, 1, 0); // 0x003B0040 |
| 403 | u32 exiting = cmd_buff[1] & 0xFF; | 436 | u32 exiting = rp.Pop<u32>() & 0xFF; |
| 404 | 437 | ||
| 405 | cmd_buff[1] = 1; // TODO: Find the return code meaning | 438 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 439 | rb.Push(u32(1)); | ||
| 406 | 440 | ||
| 407 | LOG_WARNING(Service_APT, "(STUBBED) called exiting=%u", exiting); | 441 | LOG_WARNING(Service_APT, "(STUBBED) called exiting=%u", exiting); |
| 408 | } | 442 | } |
| 409 | 443 | ||
| 410 | void SetScreenCapPostPermission(Service::Interface* self) { | 444 | void SetScreenCapPostPermission(Service::Interface* self) { |
| 411 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 445 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x55, 1, 0); // 0x00550040 |
| 412 | 446 | ||
| 413 | screen_capture_post_permission = static_cast<ScreencapPostPermission>(cmd_buff[1] & 0xF); | 447 | screen_capture_post_permission = static_cast<ScreencapPostPermission>(rp.Pop<u32>() & 0xF); |
| 414 | 448 | ||
| 415 | cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); | 449 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 416 | cmd_buff[1] = RESULT_SUCCESS.raw; | 450 | rb.Push(RESULT_SUCCESS); // No error |
| 417 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", | 451 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", |
| 418 | screen_capture_post_permission); | 452 | screen_capture_post_permission); |
| 419 | } | 453 | } |
| 420 | 454 | ||
| 421 | void GetScreenCapPostPermission(Service::Interface* self) { | 455 | void GetScreenCapPostPermission(Service::Interface* self) { |
| 422 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 456 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x56, 0, 0); // 0x00560000 |
| 423 | 457 | ||
| 424 | cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); | 458 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |
| 425 | cmd_buff[1] = RESULT_SUCCESS.raw; | 459 | rb.Push(RESULT_SUCCESS); // No error |
| 426 | cmd_buff[2] = static_cast<u32>(screen_capture_post_permission); | 460 | rb.Push(static_cast<u32>(screen_capture_post_permission)); |
| 427 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", | 461 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", |
| 428 | screen_capture_post_permission); | 462 | screen_capture_post_permission); |
| 429 | } | 463 | } |
| 430 | 464 | ||
| 431 | void GetAppletInfo(Service::Interface* self) { | 465 | void GetAppletInfo(Service::Interface* self) { |
| 432 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 466 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x6, 1, 0); // 0x60040 |
| 433 | auto app_id = static_cast<AppletId>(cmd_buff[1]); | 467 | auto app_id = static_cast<AppletId>(rp.Pop<u32>()); |
| 434 | 468 | ||
| 435 | if (auto applet = HLE::Applets::Applet::Get(app_id)) { | 469 | if (auto applet = HLE::Applets::Applet::Get(app_id)) { |
| 436 | // TODO(Subv): Get the title id for the current applet and write it in the response[2-3] | 470 | // TODO(Subv): Get the title id for the current applet and write it in the response[2-3] |
| 437 | cmd_buff[1] = RESULT_SUCCESS.raw; | 471 | IPC::RequestBuilder rb = rp.MakeBuilder(7, 0); |
| 438 | cmd_buff[4] = static_cast<u32>(Service::FS::MediaType::NAND); | 472 | rb.Push(RESULT_SUCCESS); |
| 439 | cmd_buff[5] = 1; // Registered | 473 | u64 titileId = 0; |
| 440 | cmd_buff[6] = 1; // Loaded | 474 | rb.Push(titileId); |
| 441 | cmd_buff[7] = 0; // Applet Attributes | 475 | rb.Push(static_cast<u32>(Service::FS::MediaType::NAND)); |
| 476 | rb.Push(u64(1)); // Registered | ||
| 477 | rb.Push(u64(1)); // Loaded | ||
| 478 | rb.Push(u64(0)); // Applet Attributes | ||
| 442 | } else { | 479 | } else { |
| 443 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, | 480 | IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |
| 444 | ErrorSummary::NotFound, ErrorLevel::Status) | 481 | rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, |
| 445 | .raw; | 482 | ErrorLevel::Status)); |
| 446 | } | 483 | } |
| 447 | LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); | 484 | LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); |
| 448 | } | 485 | } |
| 449 | 486 | ||
| 450 | void GetStartupArgument(Service::Interface* self) { | 487 | void GetStartupArgument(Service::Interface* self) { |
| 451 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 488 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x51, 2, 0); // 0x00510080 |
| 452 | u32 parameter_size = cmd_buff[1]; | 489 | u32 parameter_size = rp.Pop<u32>(); |
| 453 | StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]); | 490 | StartupArgumentType startup_argument_type = |
| 491 | static_cast<StartupArgumentType>(rp.Pop<u32>() & 0xF); | ||
| 454 | 492 | ||
| 455 | if (parameter_size >= 0x300) { | 493 | if (parameter_size >= 0x300) { |
| 456 | LOG_ERROR( | 494 | LOG_ERROR( |
| @@ -460,7 +498,13 @@ void GetStartupArgument(Service::Interface* self) { | |||
| 460 | return; | 498 | return; |
| 461 | } | 499 | } |
| 462 | 500 | ||
| 463 | u32 addr = cmd_buff[65]; | 501 | size_t static_buff_size; |
| 502 | VAddr addr = rp.PeekStaticBuffer(0, &static_buff_size); | ||
| 503 | if (parameter_size > static_buff_size) | ||
| 504 | LOG_WARNING(Service_APT, "GetStartupArgument: parameter_size is bigger than the size in " | ||
| 505 | "the buffer descriptor (0x%08X > 0x%08X)", | ||
| 506 | parameter_size, static_buff_size); | ||
| 507 | |||
| 464 | if (addr && parameter_size) { | 508 | if (addr && parameter_size) { |
| 465 | Memory::ZeroBlock(addr, parameter_size); | 509 | Memory::ZeroBlock(addr, parameter_size); |
| 466 | } | 510 | } |
| @@ -468,8 +512,9 @@ void GetStartupArgument(Service::Interface* self) { | |||
| 468 | LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x", | 512 | LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x", |
| 469 | startup_argument_type, parameter_size); | 513 | startup_argument_type, parameter_size); |
| 470 | 514 | ||
| 471 | cmd_buff[1] = RESULT_SUCCESS.raw; | 515 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |
| 472 | cmd_buff[2] = 0; | 516 | rb.Push(RESULT_SUCCESS); |
| 517 | rb.Push(u32(0)); | ||
| 473 | } | 518 | } |
| 474 | 519 | ||
| 475 | void Wrap(Service::Interface* self) { | 520 | void Wrap(Service::Interface* self) { |
| @@ -574,25 +619,25 @@ void Unwrap(Service::Interface* self) { | |||
| 574 | } | 619 | } |
| 575 | 620 | ||
| 576 | void CheckNew3DSApp(Service::Interface* self) { | 621 | void CheckNew3DSApp(Service::Interface* self) { |
| 577 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 622 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x101, 0, 0); // 0x01010000 |
| 578 | 623 | ||
| 624 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||
| 579 | if (unknown_ns_state_field) { | 625 | if (unknown_ns_state_field) { |
| 580 | cmd_buff[1] = RESULT_SUCCESS.raw; | 626 | rb.Push(RESULT_SUCCESS); |
| 581 | cmd_buff[2] = 0; | 627 | rb.Push(u32(0)); |
| 582 | } else { | 628 | } else { |
| 583 | PTM::CheckNew3DS(self); | 629 | PTM::CheckNew3DS(rb); |
| 584 | } | 630 | } |
| 585 | 631 | ||
| 586 | cmd_buff[0] = IPC::MakeHeader(0x101, 2, 0); | ||
| 587 | LOG_WARNING(Service_APT, "(STUBBED) called"); | 632 | LOG_WARNING(Service_APT, "(STUBBED) called"); |
| 588 | } | 633 | } |
| 589 | 634 | ||
| 590 | void CheckNew3DS(Service::Interface* self) { | 635 | void CheckNew3DS(Service::Interface* self) { |
| 591 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 636 | IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x102, 0, 0); // 0x01020000 |
| 637 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||
| 592 | 638 | ||
| 593 | PTM::CheckNew3DS(self); | 639 | PTM::CheckNew3DS(rb); |
| 594 | 640 | ||
| 595 | cmd_buff[0] = IPC::MakeHeader(0x102, 2, 0); | ||
| 596 | LOG_WARNING(Service_APT, "(STUBBED) called"); | 641 | LOG_WARNING(Service_APT, "(STUBBED) called"); |
| 597 | } | 642 | } |
| 598 | 643 | ||
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 8ff808fd9..016ac8d4f 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp | |||
| @@ -92,8 +92,7 @@ void GetSoftwareClosedFlag(Service::Interface* self) { | |||
| 92 | LOG_WARNING(Service_PTM, "(STUBBED) called"); | 92 | LOG_WARNING(Service_PTM, "(STUBBED) called"); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void CheckNew3DS(Service::Interface* self) { | 95 | void CheckNew3DS(IPC::RequestBuilder& rb) { |
| 96 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 97 | const bool is_new_3ds = Settings::values.is_new_3ds; | 96 | const bool is_new_3ds = Settings::values.is_new_3ds; |
| 98 | 97 | ||
| 99 | if (is_new_3ds) { | 98 | if (is_new_3ds) { |
| @@ -101,12 +100,17 @@ void CheckNew3DS(Service::Interface* self) { | |||
| 101 | "settings. Citra does not fully support New 3DS emulation yet!"); | 100 | "settings. Citra does not fully support New 3DS emulation yet!"); |
| 102 | } | 101 | } |
| 103 | 102 | ||
| 104 | cmd_buff[1] = RESULT_SUCCESS.raw; | 103 | rb.Push(RESULT_SUCCESS); |
| 105 | cmd_buff[2] = is_new_3ds ? 1 : 0; | 104 | rb.Push(u32(is_new_3ds ? 1 : 0)); |
| 106 | 105 | ||
| 107 | LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast<u32>(is_new_3ds)); | 106 | LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast<u32>(is_new_3ds)); |
| 108 | } | 107 | } |
| 109 | 108 | ||
| 109 | void CheckNew3DS(Service::Interface* self) { | ||
| 110 | IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x040A0000); | ||
| 111 | CheckNew3DS(rb); | ||
| 112 | } | ||
| 113 | |||
| 110 | void Init() { | 114 | void Init() { |
| 111 | AddService(new PTM_Gets); | 115 | AddService(new PTM_Gets); |
| 112 | AddService(new PTM_Play); | 116 | AddService(new PTM_Play); |
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index a1a628012..683fb445b 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "core/hle/ipc_helpers.h" | ||
| 8 | 9 | ||
| 9 | namespace Service { | 10 | namespace Service { |
| 10 | 11 | ||
| @@ -97,6 +98,7 @@ void GetSoftwareClosedFlag(Interface* self); | |||
| 97 | * 2: u8 output: 0 = Old3DS, 1 = New3DS. | 98 | * 2: u8 output: 0 = Old3DS, 1 = New3DS. |
| 98 | */ | 99 | */ |
| 99 | void CheckNew3DS(Interface* self); | 100 | void CheckNew3DS(Interface* self); |
| 101 | void CheckNew3DS(IPC::RequestBuilder& rb); | ||
| 100 | 102 | ||
| 101 | /// Initialize the PTM service | 103 | /// Initialize the PTM service |
| 102 | void Init(); | 104 | void Init(); |