summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/ipc.h81
-rw-r--r--src/core/hle/ipc_helpers.h275
-rw-r--r--src/core/hle/service/fs/fs_user.cpp27
-rw-r--r--src/core/hle/service/service.h1
-rw-r--r--src/core/hle/service/y2r_u.cpp47
6 files changed, 364 insertions, 68 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index fa7878c65..b178914dd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -219,6 +219,7 @@ set(HEADERS
219 hle/config_mem.h 219 hle/config_mem.h
220 hle/function_wrappers.h 220 hle/function_wrappers.h
221 hle/ipc.h 221 hle/ipc.h
222 hle/ipc_helpers.h
222 hle/applets/applet.h 223 hle/applets/applet.h
223 hle/applets/erreula.h 224 hle/applets/erreula.h
224 hle/applets/mii_selector.h 225 hle/applets/mii_selector.h
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index 4e094faa7..4535b61c0 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -18,12 +18,26 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of
18 * the thread's TLS to an intermediate buffer in kernel memory, and then copied again to 18 * the thread's TLS to an intermediate buffer in kernel memory, and then copied again to
19 * the service handler process' memory. 19 * the service handler process' memory.
20 * @param offset Optional offset into command buffer 20 * @param offset Optional offset into command buffer
21 * @param offset Optional offset into command buffer (in bytes)
21 * @return Pointer to command buffer 22 * @return Pointer to command buffer
22 */ 23 */
23inline u32* GetCommandBuffer(const int offset = 0) { 24inline u32* GetCommandBuffer(const int offset = 0) {
24 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + 25 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
25 offset); 26 offset);
26} 27}
28
29static const int kStaticBuffersOffset =
30 0x100; ///< Offset into static buffers, relative to command buffer header
31
32/**
33 * Returns a pointer to the static buffers area in the current thread's TLS
34 * TODO(Subv): cf. GetCommandBuffer
35 * @param offset Optional offset into static buffers area (in bytes)
36 * @return Pointer to static buffers area
37 */
38inline u32* GetStaticBuffers(const int offset = 0) {
39 return GetCommandBuffer(kStaticBuffersOffset + offset);
40}
27} 41}
28 42
29namespace IPC { 43namespace IPC {
@@ -40,10 +54,17 @@ enum DescriptorType : u32 {
40 CallingPid = 0x20, 54 CallingPid = 0x20,
41}; 55};
42 56
57union Header {
58 u32 raw;
59 BitField<0, 6, u32> translate_params_size;
60 BitField<6, 6, u32> normal_params_size;
61 BitField<16, 16, u32> command_id;
62};
63
43/** 64/**
44 * @brief Creates a command header to be used for IPC 65 * @brief Creates a command header to be used for IPC
45 * @param command_id ID of the command to create a header for. 66 * @param command_id ID of the command to create a header for.
46 * @param normal_params Size of the normal parameters in words. Up to 63. 67 * @param normal_params_size Size of the normal parameters in words. Up to 63.
47 * @param translate_params_size Size of the translate parameters in words. Up to 63. 68 * @param translate_params_size Size of the translate parameters in words. Up to 63.
48 * @return The created IPC header. 69 * @return The created IPC header.
49 * 70 *
@@ -51,24 +72,16 @@ enum DescriptorType : u32 {
51 * through modifications and checks by the kernel. 72 * through modifications and checks by the kernel.
52 * The translate parameters are described by headers generated with the IPC::*Desc functions. 73 * The translate parameters are described by headers generated with the IPC::*Desc functions.
53 * 74 *
54 * @note While #normal_params is equivalent to the number of normal parameters, 75 * @note While #normal_params_size is equivalent to the number of normal parameters,
55 * #translate_params_size includes the size occupied by the translate parameters headers. 76 * #translate_params_size includes the size occupied by the translate parameters headers.
56 */ 77 */
57constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, 78inline u32 MakeHeader(u16 command_id, unsigned int normal_params_size,
58 unsigned int translate_params_size) { 79 unsigned int translate_params_size) {
59 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | 80 Header header;
60 (u32(translate_params_size) & 0x3F); 81 header.command_id.Assign(command_id);
61} 82 header.normal_params_size.Assign(normal_params_size);
62 83 header.translate_params_size.Assign(translate_params_size);
63union Header { 84 return header.raw;
64 u32 raw;
65 BitField<0, 6, u32> translate_params_size;
66 BitField<6, 6, u32> normal_params;
67 BitField<16, 16, u32> command_id;
68};
69
70inline Header ParseHeader(u32 header) {
71 return {header};
72} 85}
73 86
74constexpr u32 MoveHandleDesc(u32 num_handles = 1) { 87constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
@@ -83,7 +96,7 @@ constexpr u32 CallingPidDesc() {
83 return CallingPid; 96 return CallingPid;
84} 97}
85 98
86constexpr bool isHandleDescriptor(u32 descriptor) { 99constexpr bool IsHandleDescriptor(u32 descriptor) {
87 return (descriptor & 0xF) == 0x0; 100 return (descriptor & 0xF) == 0x0;
88} 101}
89 102
@@ -91,18 +104,19 @@ constexpr u32 HandleNumberFromDesc(u32 handle_descriptor) {
91 return (handle_descriptor >> 26) + 1; 104 return (handle_descriptor >> 26) + 1;
92} 105}
93 106
94constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) {
95 return StaticBuffer | (size << 14) | ((buffer_id & 0xF) << 10);
96}
97
98union StaticBufferDescInfo { 107union StaticBufferDescInfo {
99 u32 raw; 108 u32 raw;
109 BitField<0, 4, u32> descriptor_type;
100 BitField<10, 4, u32> buffer_id; 110 BitField<10, 4, u32> buffer_id;
101 BitField<14, 18, u32> size; 111 BitField<14, 18, u32> size;
102}; 112};
103 113
104inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { 114inline u32 StaticBufferDesc(u32 size, u8 buffer_id) {
105 return {desc}; 115 StaticBufferDescInfo info;
116 info.descriptor_type.Assign(StaticBuffer);
117 info.buffer_id.Assign(buffer_id);
118 info.size.Assign(size);
119 return info.raw;
106} 120}
107 121
108/** 122/**
@@ -122,29 +136,30 @@ inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
122 return type | (size << 8) | ((buffer_id & 0xF) << 4); 136 return type | (size << 8) | ((buffer_id & 0xF) << 4);
123} 137}
124 138
125enum MappedBufferPermissions { 139enum MappedBufferPermissions : u32 {
126 R = 1, 140 R = 1,
127 W = 2, 141 W = 2,
128 RW = R | W, 142 RW = R | W,
129}; 143};
130 144
131constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
132 return MappedBuffer | (size << 4) | (u32(perms) << 1);
133}
134
135union MappedBufferDescInfo { 145union MappedBufferDescInfo {
136 u32 raw; 146 u32 raw;
137 BitField<4, 28, u32> size; 147 BitField<0, 4, u32> flags;
138 BitField<1, 2, MappedBufferPermissions> perms; 148 BitField<1, 2, MappedBufferPermissions> perms;
149 BitField<4, 28, u32> size;
139}; 150};
140 151
141inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { 152inline u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
142 return {desc}; 153 MappedBufferDescInfo info;
154 info.flags.Assign(MappedBuffer);
155 info.perms.Assign(perms);
156 info.size.Assign(size);
157 return info.raw;
143} 158}
144 159
145inline DescriptorType GetDescriptorType(u32 descriptor) { 160inline DescriptorType GetDescriptorType(u32 descriptor) {
146 // Note: Those checks must be done in this order 161 // Note: Those checks must be done in this order
147 if (isHandleDescriptor(descriptor)) 162 if (IsHandleDescriptor(descriptor))
148 return (DescriptorType)(descriptor & 0x30); 163 return (DescriptorType)(descriptor & 0x30);
149 164
150 // handle the fact that the following descriptors can have rights 165 // handle the fact that the following descriptors can have rights
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
new file mode 100644
index 000000000..323158bb5
--- /dev/null
+++ b/src/core/hle/ipc_helpers.h
@@ -0,0 +1,275 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6#include "core/hle/ipc.h"
7#include "core/hle/kernel/kernel.h"
8
9namespace IPC {
10
11class RequestHelperBase {
12protected:
13 u32* cmdbuf;
14 ptrdiff_t index = 1;
15 Header header;
16
17public:
18 RequestHelperBase(u32* command_buffer, Header command_header)
19 : cmdbuf(command_buffer), header(command_header) {}
20
21 /// Returns the total size of the request in words
22 size_t TotalSize() const {
23 return 1 /* command header */ + header.normal_params_size + header.translate_params_size;
24 }
25
26 void ValidateHeader() {
27 DEBUG_ASSERT_MSG(index == TotalSize(), "Operations do not match the header (cmd 0x%x)",
28 header.raw);
29 }
30};
31
32class RequestBuilder : public RequestHelperBase {
33public:
34 RequestBuilder(u32* command_buffer, Header command_header)
35 : RequestHelperBase(command_buffer, command_header) {
36 cmdbuf[0] = header.raw;
37 }
38 explicit RequestBuilder(u32* command_buffer, u32 command_header)
39 : RequestBuilder(command_buffer, Header{command_header}) {}
40 RequestBuilder(u32* command_buffer, u16 command_id, unsigned normal_params_size,
41 unsigned translate_params_size)
42 : RequestBuilder(command_buffer,
43 MakeHeader(command_id, normal_params_size, translate_params_size)) {}
44
45 // Validate on destruction, as there shouldn't be any case where we don't want it
46 ~RequestBuilder() {
47 ValidateHeader();
48 }
49
50 template <typename T>
51 void Push(T value);
52
53 void Push(u32 value) {
54 cmdbuf[index++] = value;
55 }
56 template <typename First, typename... Other>
57 void Push(const First& first_value, const Other&... other_values) {
58 Push(first_value);
59 Push(other_values...);
60 }
61
62 /**
63 * @brief Copies the content of the given trivially copyable class to the buffer as a normal
64 * param
65 * @note: The input class must be correctly packed/padded to fit hardware layout.
66 */
67 template <typename T>
68 void PushRaw(const T& value) {
69 static_assert(std::is_trivially_copyable<T>(), "Raw types should be trivially copyable");
70 std::memcpy(cmdbuf + index, &value, sizeof(T));
71 index += (sizeof(T) + 3) / 4; // round up to word length
72 }
73
74 // TODO : ensure that translate params are added after all regular params
75 template <typename... H>
76 void PushCopyHandles(H... handles) {
77 Push(CopyHandleDesc(sizeof...(H)));
78 Push(static_cast<Kernel::Handle>(handles)...);
79 }
80
81 template <typename... H>
82 void PushMoveHandles(H... handles) {
83 Push(MoveHandleDesc(sizeof...(H)));
84 Push(static_cast<Kernel::Handle>(handles)...);
85 }
86
87 void PushCurrentPIDHandle() {
88 Push(CallingPidDesc());
89 Push(u32(0));
90 }
91
92 void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id) {
93 Push(StaticBufferDesc(size, buffer_id));
94 Push(buffer_vaddr);
95 }
96
97 void PushMappedBuffer(VAddr buffer_vaddr, u32 size, MappedBufferPermissions perms) {
98 Push(MappedBufferDesc(size, perms));
99 Push(buffer_vaddr);
100 }
101};
102
103/// Push ///
104
105template <>
106inline void RequestBuilder::Push<u32>(u32 value) {
107 Push(value);
108}
109
110template <>
111inline void RequestBuilder::Push<u64>(u64 value) {
112 Push(static_cast<u32>(value));
113 Push(static_cast<u32>(value >> 32));
114}
115
116template <>
117inline void RequestBuilder::Push<ResultCode>(ResultCode value) {
118 Push(value.raw);
119}
120
121class RequestParser : public RequestHelperBase {
122public:
123 RequestParser(u32* command_buffer, Header command_header)
124 : RequestHelperBase(command_buffer, command_header) {}
125 explicit RequestParser(u32* command_buffer, u32 command_header)
126 : RequestParser(command_buffer, Header{command_header}) {}
127 RequestParser(u32* command_buffer, u16 command_id, unsigned normal_params_size,
128 unsigned translate_params_size)
129 : RequestParser(command_buffer,
130 MakeHeader(command_id, normal_params_size, translate_params_size)) {}
131
132 RequestBuilder MakeBuilder(u32 normal_params_size, u32 translate_params_size,
133 bool validateHeader = true) {
134 if (validateHeader)
135 ValidateHeader();
136 Header builderHeader{
137 MakeHeader(header.command_id, normal_params_size, translate_params_size)};
138 return {cmdbuf, builderHeader};
139 }
140
141 template <typename T>
142 T Pop();
143
144 template <typename T>
145 void Pop(T& value);
146
147 template <typename First, typename... Other>
148 void Pop(First& first_value, Other&... other_values);
149
150 Kernel::Handle PopHandle();
151
152 template <typename... H>
153 void PopHandles(H&... handles);
154
155 /**
156 * @brief Pops the static buffer vaddr
157 * @return The virtual address of the buffer
158 * @param[out] data_size If non-null, the pointed value will be set to the size of the data
159 * @param[out] useStaticBuffersToGetVaddr Indicates if we should read the vaddr from the static
160 * buffers (which is the correct thing to do, but no service presently implement it) instead of
161 * using the same value as the process who sent the request
162 * given by the source process
163 *
164 * Static buffers must be set up before any IPC request using those is sent.
165 * It is the duty of the process (usually services) to allocate and set up the receiving static
166 * buffer information
167 * Please note that the setup uses virtual addresses.
168 */
169 VAddr PopStaticBuffer(size_t* data_size = nullptr, bool useStaticBuffersToGetVaddr = false);
170
171 /**
172 * @brief Pops the mapped buffer vaddr
173 * @return The virtual address of the buffer
174 * @param[out] data_size If non-null, the pointed value will be set to the size of the data
175 * given by the source process
176 * @param[out] buffer_perms If non-null, the pointed value will be set to the permissions of the
177 * buffer
178 */
179 VAddr PopMappedBuffer(size_t* data_size = nullptr,
180 MappedBufferPermissions* buffer_perms = nullptr);
181
182 /**
183 * @brief Reads the next normal parameters as a struct, by copying it
184 * @note: The output class must be correctly packed/padded to fit hardware layout.
185 */
186 template <typename T>
187 void PopRaw(T& value);
188};
189
190/// Pop ///
191
192template <>
193inline u32 RequestParser::Pop<u32>() {
194 return cmdbuf[index++];
195}
196
197template <>
198inline u64 RequestParser::Pop<u64>() {
199 const u64 lsw = Pop<u32>();
200 const u64 msw = Pop<u32>();
201 return msw << 32 | lsw;
202}
203
204template <>
205inline ResultCode RequestParser::Pop<ResultCode>() {
206 return ResultCode{Pop<u32>()};
207}
208
209template <typename T>
210void RequestParser::Pop(T& value) {
211 value = Pop<T>();
212}
213
214template <typename First, typename... Other>
215void RequestParser::Pop(First& first_value, Other&... other_values) {
216 first_value = Pop<First>();
217 Pop(other_values...);
218}
219
220inline Kernel::Handle RequestParser::PopHandle() {
221 const u32 handle_descriptor = Pop<u32>();
222 DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor),
223 "Tried to pop handle(s) but the descriptor is not a handle descriptor");
224 DEBUG_ASSERT_MSG(HandleNumberFromDesc(handle_descriptor) == 1,
225 "Descriptor indicates that there isn't exactly one handle");
226 return Pop<Kernel::Handle>();
227}
228
229template <typename... H>
230void RequestParser::PopHandles(H&... handles) {
231 const u32 handle_descriptor = Pop<u32>();
232 const int handles_number = sizeof...(H);
233 DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor),
234 "Tried to pop handle(s) but the descriptor is not a handle descriptor");
235 DEBUG_ASSERT_MSG(handles_number == HandleNumberFromDesc(handle_descriptor),
236 "Number of handles doesn't match the descriptor");
237 Pop(static_cast<Kernel::Handle&>(handles)...);
238}
239
240inline VAddr RequestParser::PopStaticBuffer(size_t* data_size, bool useStaticBuffersToGetVaddr) {
241 const u32 sbuffer_descriptor = Pop<u32>();
242 StaticBufferDescInfo bufferInfo{sbuffer_descriptor};
243 if (data_size != nullptr)
244 *data_size = bufferInfo.size;
245 if (!useStaticBuffersToGetVaddr)
246 return Pop<VAddr>();
247 else {
248 ASSERT_MSG(0, "remove the assert if multiprocess/IPC translation are implemented.");
249 // The buffer has already been copied to the static buffer by the kernel during
250 // translation
251 Pop<VAddr>(); // Pop the calling process buffer address
252 // and get the vaddr from the static buffers
253 return cmdbuf[(0x100 >> 2) + bufferInfo.buffer_id * 2 + 1];
254 }
255}
256
257inline VAddr RequestParser::PopMappedBuffer(size_t* data_size,
258 MappedBufferPermissions* buffer_perms) {
259 const u32 sbuffer_descriptor = Pop<u32>();
260 MappedBufferDescInfo bufferInfo{sbuffer_descriptor};
261 if (data_size != nullptr)
262 *data_size = bufferInfo.size;
263 if (buffer_perms != nullptr)
264 *buffer_perms = bufferInfo.perms;
265 return Pop<VAddr>();
266}
267
268template <typename T>
269void RequestParser::PopRaw(T& value) {
270 static_assert(std::is_trivially_copyable<T>(), "Raw types should be trivially copyable");
271 std::memcpy(&value, cmdbuf + index, sizeof(T));
272 index += (sizeof(T) + 3) / 4; // round up to word length
273}
274
275} // namespace IPC
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 337da1387..33b290699 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -54,15 +54,17 @@ static void Initialize(Service::Interface* self) {
54 * 3 : File handle 54 * 3 : File handle
55 */ 55 */
56static void OpenFile(Service::Interface* self) { 56static void OpenFile(Service::Interface* self) {
57 u32* cmd_buff = Kernel::GetCommandBuffer(); 57 // The helper should be passed by argument to the function
58 IPC::RequestParser rp(Kernel::GetCommandBuffer(), {0x080201C2});
59 rp.Pop<u32>(); // Always 0 ?
58 60
59 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 61 ArchiveHandle archive_handle = rp.Pop<u64>();
60 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 62 auto filename_type = static_cast<FileSys::LowPathType>(rp.Pop<u32>());
61 u32 filename_size = cmd_buff[5]; 63 u32 filename_size = rp.Pop<u32>();
62 FileSys::Mode mode; 64 FileSys::Mode mode;
63 mode.hex = cmd_buff[6]; 65 mode.hex = rp.Pop<u32>();
64 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. 66 u32 attributes = rp.Pop<u32>(); // TODO(Link Mauve): do something with those attributes.
65 u32 filename_ptr = cmd_buff[9]; 67 VAddr filename_ptr = rp.PopStaticBuffer();
66 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 68 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
67 69
68 LOG_DEBUG(Service_FS, "path=%s, mode=%u attrs=%u", file_path.DebugStr().c_str(), mode.hex, 70 LOG_DEBUG(Service_FS, "path=%s, mode=%u attrs=%u", file_path.DebugStr().c_str(), mode.hex,
@@ -70,16 +72,17 @@ static void OpenFile(Service::Interface* self) {
70 72
71 ResultVal<std::shared_ptr<File>> file_res = 73 ResultVal<std::shared_ptr<File>> file_res =
72 OpenFileFromArchive(archive_handle, file_path, mode); 74 OpenFileFromArchive(archive_handle, file_path, mode);
73 cmd_buff[1] = file_res.Code().raw; 75 IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
76 rb.Push(file_res.Code());
74 if (file_res.Succeeded()) { 77 if (file_res.Succeeded()) {
75 std::shared_ptr<File> file = *file_res; 78 std::shared_ptr<File> file = *file_res;
76 auto sessions = ServerSession::CreateSessionPair(file->GetName(), file); 79 auto sessions = ServerSession::CreateSessionPair(file->GetName(), file);
77 file->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions)); 80 file->ClientConnected(std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions));
78 cmd_buff[3] = Kernel::g_handle_table 81 rb.PushMoveHandles(Kernel::g_handle_table
79 .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions)) 82 .Create(std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions))
80 .MoveFrom(); 83 .MoveFrom());
81 } else { 84 } else {
82 cmd_buff[3] = 0; 85 rb.PushMoveHandles(0);
83 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 86 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
84 } 87 }
85} 88}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index a7ba7688f..e6a5f1417 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -10,6 +10,7 @@
10#include <boost/container/flat_map.hpp> 10#include <boost/container/flat_map.hpp>
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/hle/ipc.h" 12#include "core/hle/ipc.h"
13#include "core/hle/ipc_helpers.h"
13#include "core/hle/kernel/client_port.h" 14#include "core/hle/kernel/client_port.h"
14#include "core/hle/kernel/thread.h" 15#include "core/hle/kernel/thread.h"
15#include "core/hle/result.h" 16#include "core/hle/result.h"
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index 31bb466fc..907d9c8fa 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -281,37 +281,39 @@ static void GetTransferEndEvent(Interface* self) {
281} 281}
282 282
283static void SetSendingY(Interface* self) { 283static void SetSendingY(Interface* self) {
284 u32* cmd_buff = Kernel::GetCommandBuffer(); 284 // The helper should be passed by argument to the function
285 285 IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x00100102);
286 conversion.src_Y.address = cmd_buff[1]; 286 conversion.src_Y.address = rp.Pop<u32>();
287 conversion.src_Y.image_size = cmd_buff[2]; 287 conversion.src_Y.image_size = rp.Pop<u32>();
288 conversion.src_Y.transfer_unit = cmd_buff[3]; 288 conversion.src_Y.transfer_unit = rp.Pop<u32>();
289 conversion.src_Y.gap = cmd_buff[4]; 289 conversion.src_Y.gap = rp.Pop<u32>();
290 Kernel::Handle src_process_handle = rp.PopHandle();
290 291
291 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); 292 IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
292 cmd_buff[1] = RESULT_SUCCESS.raw; 293 rb.Push(RESULT_SUCCESS);
293 294
294 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " 295 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
295 "src_process_handle=0x%08X", 296 "src_process_handle=0x%08X",
296 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap, 297 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap,
297 cmd_buff[6]); 298 src_process_handle);
298} 299}
299 300
300static void SetSendingU(Interface* self) { 301static void SetSendingU(Interface* self) {
301 u32* cmd_buff = Kernel::GetCommandBuffer(); 302 // The helper should be passed by argument to the function
303 IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x00110102);
304 conversion.src_U.address = rp.Pop<u32>();
305 conversion.src_U.image_size = rp.Pop<u32>();
306 conversion.src_U.transfer_unit = rp.Pop<u32>();
307 conversion.src_U.gap = rp.Pop<u32>();
308 Kernel::Handle src_process_handle = rp.PopHandle();
302 309
303 conversion.src_U.address = cmd_buff[1]; 310 IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
304 conversion.src_U.image_size = cmd_buff[2]; 311 rb.Push(RESULT_SUCCESS);
305 conversion.src_U.transfer_unit = cmd_buff[3];
306 conversion.src_U.gap = cmd_buff[4];
307
308 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0);
309 cmd_buff[1] = RESULT_SUCCESS.raw;
310 312
311 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " 313 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
312 "src_process_handle=0x%08X", 314 "src_process_handle=0x%08X",
313 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap, 315 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap,
314 cmd_buff[6]); 316 src_process_handle);
315} 317}
316 318
317static void SetSendingV(Interface* self) { 319static void SetSendingV(Interface* self) {
@@ -561,11 +563,10 @@ static void GetAlpha(Interface* self) {
561} 563}
562 564
563static void SetDitheringWeightParams(Interface* self) { 565static void SetDitheringWeightParams(Interface* self) {
564 u32* cmd_buff = Kernel::GetCommandBuffer(); 566 IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x24, 8, 0); // 0x240200
565 std::memcpy(&dithering_weight_params, &cmd_buff[1], sizeof(DitheringWeightParams)); 567 rp.PopRaw(dithering_weight_params);
566 568 IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
567 cmd_buff[0] = IPC::MakeHeader(0x24, 1, 0); 569 rb.Push(RESULT_SUCCESS);
568 cmd_buff[1] = RESULT_SUCCESS.raw;
569 570
570 LOG_DEBUG(Service_Y2R, "called"); 571 LOG_DEBUG(Service_Y2R, "called");
571} 572}