summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/ipc.h4
-rw-r--r--src/core/hle/ipc_helpers.h4
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp34
-rw-r--r--src/core/hle/kernel/hle_ipc.h6
-rw-r--r--src/core/hle/service/am/applet_oe.cpp86
5 files changed, 127 insertions, 7 deletions
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index 1840fac12..0dcaede67 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -133,6 +133,10 @@ struct BufferDescriptorC {
133 address |= static_cast<VAddr>(address_bits_32_47) << 32; 133 address |= static_cast<VAddr>(address_bits_32_47) << 32;
134 return address; 134 return address;
135 } 135 }
136
137 u64 Size() const {
138 return static_cast<u64>(size);
139 }
136}; 140};
137static_assert(sizeof(BufferDescriptorC) == 8, "BufferDescriptorC size is incorrect"); 141static_assert(sizeof(BufferDescriptorC) == 8, "BufferDescriptorC size is incorrect");
138 142
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 25530a3c8..4c9b0de28 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -54,6 +54,10 @@ public:
54 unsigned GetCurrentOffset() const { 54 unsigned GetCurrentOffset() const {
55 return static_cast<unsigned>(index); 55 return static_cast<unsigned>(index);
56 } 56 }
57
58 void SetCurrentOffset(unsigned offset) {
59 index = static_cast<ptrdiff_t>(offset);
60 }
57}; 61};
58 62
59class RequestBuilder : public RequestHelperBase { 63class RequestBuilder : public RequestHelperBase {
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index ac62a0d5a..73bb6a8be 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -81,13 +81,8 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
81 for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) { 81 for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) {
82 buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); 82 buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
83 } 83 }
84 if (command_header->buf_c_descriptor_flags != 84
85 IPC::CommandHeader::BufferDescriptorCFlag::Disabled) { 85 buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size;
86 if (command_header->buf_c_descriptor_flags !=
87 IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) {
88 UNIMPLEMENTED();
89 }
90 }
91 86
92 // Padding to align to 16 bytes 87 // Padding to align to 16 bytes
93 rp.AlignWithPadding(); 88 rp.AlignWithPadding();
@@ -117,6 +112,31 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
117 ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); 112 ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O'));
118 } 113 }
119 114
115 rp.SetCurrentOffset(buffer_c_offset);
116
117 // For Inline buffers, the response data is written directly to buffer_c_offset
118 // and in this case we don't have any BufferDescriptorC on the request.
119 if (command_header->buf_c_descriptor_flags >
120 IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) {
121 if (command_header->buf_c_descriptor_flags ==
122 IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) {
123 buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>());
124 } else {
125 unsigned num_buf_c_descriptors =
126 static_cast<unsigned>(command_header->buf_c_descriptor_flags.Value()) - 2;
127
128 // This is used to detect possible underflows, in case something is broken
129 // with the two ifs above and the flags value is == 0 || == 1.
130 ASSERT(num_buf_c_descriptors < 14);
131
132 for (unsigned i = 0; i < num_buf_c_descriptors; ++i) {
133 buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>());
134 }
135 }
136 }
137
138 rp.SetCurrentOffset(data_payload_offset);
139
120 command = rp.Pop<u32_le>(); 140 command = rp.Pop<u32_le>();
121 rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. 141 rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
122} 142}
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 6dceb766d..80fa48d7f 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -143,6 +143,10 @@ public:
143 return buffer_b_desciptors; 143 return buffer_b_desciptors;
144 } 144 }
145 145
146 const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const {
147 return buffer_c_desciptors;
148 }
149
146 const std::unique_ptr<IPC::DomainMessageHeader>& GetDomainMessageHeader() const { 150 const std::unique_ptr<IPC::DomainMessageHeader>& GetDomainMessageHeader() const {
147 return domain_message_header; 151 return domain_message_header;
148 } 152 }
@@ -200,8 +204,10 @@ private:
200 std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; 204 std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors;
201 std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; 205 std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors;
202 std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; 206 std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors;
207 std::vector<IPC::BufferDescriptorC> buffer_c_desciptors;
203 208
204 unsigned data_payload_offset{}; 209 unsigned data_payload_offset{};
210 unsigned buffer_c_offset{};
205 u32_le command{}; 211 u32_le command{};
206}; 212};
207 213
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index b360e7e5f..0d7f9c03d 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -201,10 +201,76 @@ private:
201 Kernel::SharedPtr<Kernel::Event> event; 201 Kernel::SharedPtr<Kernel::Event> event;
202}; 202};
203 203
204class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
205public:
206 explicit IStorageAccessor(std::vector<u8> buffer)
207 : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
208 static const FunctionInfo functions[] = {
209 {0, &IStorageAccessor::GetSize, "GetSize"},
210 {11, &IStorageAccessor::Read, "Read"},
211 };
212 RegisterHandlers(functions);
213 }
214
215private:
216 std::vector<u8> buffer;
217
218 void GetSize(Kernel::HLERequestContext& ctx) {
219 IPC::RequestBuilder rb{ctx, 4};
220
221 rb.Push(RESULT_SUCCESS);
222 rb.Push(static_cast<u64>(buffer.size()));
223
224 LOG_DEBUG(Service, "called");
225 }
226
227 void Read(Kernel::HLERequestContext& ctx) {
228 IPC::RequestParser rp{ctx};
229
230 u64 offset = rp.Pop<u64>();
231
232 const auto& output_buffer = ctx.BufferDescriptorC()[0];
233
234 ASSERT(offset + output_buffer.Size() <= buffer.size());
235
236 Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size());
237
238 IPC::RequestBuilder rb{ctx, 2};
239
240 rb.Push(RESULT_SUCCESS);
241
242 LOG_DEBUG(Service, "called");
243 }
244};
245
246class IStorage final : public ServiceFramework<IStorage> {
247public:
248 explicit IStorage(std::vector<u8> buffer)
249 : ServiceFramework("IStorage"), buffer(std::move(buffer)) {
250 static const FunctionInfo functions[] = {
251 {0, &IStorage::Open, "Open"},
252 };
253 RegisterHandlers(functions);
254 }
255
256private:
257 std::vector<u8> buffer;
258
259 void Open(Kernel::HLERequestContext& ctx) {
260 IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
261
262 rb.Push(RESULT_SUCCESS);
263 rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
264
265 LOG_DEBUG(Service, "called");
266 }
267};
268
204class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { 269class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
205public: 270public:
206 IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { 271 IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
207 static const FunctionInfo functions[] = { 272 static const FunctionInfo functions[] = {
273 {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
208 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, 274 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
209 {66, &IApplicationFunctions::InitializeGamePlayRecording, 275 {66, &IApplicationFunctions::InitializeGamePlayRecording,
210 "InitializeGamePlayRecording"}, 276 "InitializeGamePlayRecording"},
@@ -215,6 +281,26 @@ public:
215 } 281 }
216 282
217private: 283private:
284 void PopLaunchParameter(Kernel::HLERequestContext& ctx) {
285 constexpr u8 data[0x88] = {
286 0xca, 0x97, 0x94, 0xc7, // Magic
287 1, 0, 0, 0, // IsAccountSelected (bool)
288 1, 0, 0, 0, // User Id (word 0)
289 0, 0, 0, 0, // User Id (word 1)
290 0, 0, 0, 0, // User Id (word 2)
291 0, 0, 0, 0 // User Id (word 3)
292 };
293
294 std::vector<u8> buffer(data, data + sizeof(data));
295
296 IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
297
298 rb.Push(RESULT_SUCCESS);
299 rb.PushIpcInterface<AM::IStorage>(buffer);
300
301 LOG_DEBUG(Service, "called");
302 }
303
218 void SetTerminateResult(Kernel::HLERequestContext& ctx) { 304 void SetTerminateResult(Kernel::HLERequestContext& ctx) {
219 // Takes an input u32 Result, no output. 305 // Takes an input u32 Result, no output.
220 // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. 306 // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak.