From 501e23ce59a84cb0b0ef3db5b1c84939fa732811 Mon Sep 17 00:00:00 2001 From: Lectem Date: Wed, 28 Dec 2016 17:11:14 +0100 Subject: refactor APT service to use the new IPC helpers --- src/core/hle/service/ptm/ptm.cpp | 12 ++++++++---- src/core/hle/service/ptm/ptm.h | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src/core/hle/service/ptm') 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) { LOG_WARNING(Service_PTM, "(STUBBED) called"); } -void CheckNew3DS(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void CheckNew3DS(IPC::RequestBuilder& rb) { const bool is_new_3ds = Settings::values.is_new_3ds; if (is_new_3ds) { @@ -101,12 +100,17 @@ void CheckNew3DS(Service::Interface* self) { "settings. Citra does not fully support New 3DS emulation yet!"); } - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = is_new_3ds ? 1 : 0; + rb.Push(RESULT_SUCCESS); + rb.Push(u32(is_new_3ds ? 1 : 0)); LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast(is_new_3ds)); } +void CheckNew3DS(Service::Interface* self) { + IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x040A0000); + CheckNew3DS(rb); +} + void Init() { AddService(new PTM_Gets); 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 @@ #pragma once #include "common/common_types.h" +#include "core/hle/ipc_helpers.h" namespace Service { @@ -97,6 +98,7 @@ void GetSoftwareClosedFlag(Interface* self); * 2: u8 output: 0 = Old3DS, 1 = New3DS. */ void CheckNew3DS(Interface* self); +void CheckNew3DS(IPC::RequestBuilder& rb); /// Initialize the PTM service void Init(); -- cgit v1.2.3 From fb70c9683c088233810abe298d587eaf671f6041 Mon Sep 17 00:00:00 2001 From: Lectem Date: Fri, 30 Dec 2016 15:54:40 +0100 Subject: move push out of class body and add u8 u16 bool specializations --- src/core/hle/ipc.h | 7 +- src/core/hle/ipc_helpers.h | 152 +++++++++++++++++++++++++++------------ src/core/hle/service/ptm/ptm.cpp | 2 +- src/core/hle/service/y2r_u.cpp | 8 +-- 4 files changed, 114 insertions(+), 55 deletions(-) (limited to 'src/core/hle/service/ptm') diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index cd9a5863d..3a5d481a5 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -10,7 +10,8 @@ namespace Kernel { -static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header +/// Offset into command buffer of header +static const int kCommandHeaderOffset = 0x80; /** * Returns a pointer to the command buffer in the current thread's TLS @@ -26,8 +27,8 @@ inline u32* GetCommandBuffer(const int offset = 0) { offset); } -static const int kStaticBuffersOffset = - 0x100; ///< Offset into static buffers, relative to command buffer header +/// Offset into static buffers, relative to command buffer header +static const int kStaticBuffersOffset = 0x100; /** * Returns a pointer to the static buffers area in the current thread's TLS diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 11a33c8bd..263b0ff5d 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -62,14 +62,8 @@ public: template void Push(T value); - void Push(u32 value) { - cmdbuf[index++] = value; - } template - void Push(const First& first_value, const Other&... other_values) { - Push(first_value); - Push(other_values...); - } + void Push(const First& first_value, const Other&... other_values); /** * @brief Copies the content of the given trivially copyable class to the buffer as a normal @@ -77,59 +71,96 @@ public: * @note: The input class must be correctly packed/padded to fit hardware layout. */ template - void PushRaw(const T& value) { - static_assert(std::is_trivially_copyable(), "Raw types should be trivially copyable"); - std::memcpy(cmdbuf + index, &value, sizeof(T)); - index += (sizeof(T) + 3) / 4; // round up to word length - } + void PushRaw(const T& value); // TODO : ensure that translate params are added after all regular params template - void PushCopyHandles(H... handles) { - Push(CopyHandleDesc(sizeof...(H))); - Push(static_cast(handles)...); - } + void PushCopyHandles(H... handles); template - void PushMoveHandles(H... handles) { - Push(MoveHandleDesc(sizeof...(H))); - Push(static_cast(handles)...); - } + void PushMoveHandles(H... handles); - void PushCurrentPIDHandle() { - Push(CallingPidDesc()); - Push(u32(0)); - } + void PushCurrentPIDHandle(); - void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id) { - Push(StaticBufferDesc(size, buffer_id)); - Push(buffer_vaddr); - } + void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id); - void PushMappedBuffer(VAddr buffer_vaddr, u32 size, MappedBufferPermissions perms) { - Push(MappedBufferDesc(size, perms)); - Push(buffer_vaddr); - } + void PushMappedBuffer(VAddr buffer_vaddr, u32 size, MappedBufferPermissions perms); }; /// Push /// template <> -inline void RequestBuilder::Push(u32 value) { - Push(value); +inline void RequestBuilder::Push(u32 value) { + cmdbuf[index++] = value; +} + +template +void RequestBuilder::PushRaw(const T& value) { + static_assert(std::is_trivially_copyable(), "Raw types should be trivially copyable"); + std::memcpy(cmdbuf + index, &value, sizeof(T)); + index += (sizeof(T) + 3) / 4; // round up to word length +} + +template <> +inline void RequestBuilder::Push(u8 value) { + PushRaw(value); +} + +template <> +inline void RequestBuilder::Push(u16 value) { + PushRaw(value); } template <> -inline void RequestBuilder::Push(u64 value) { +inline void RequestBuilder::Push(u64 value) { Push(static_cast(value)); Push(static_cast(value >> 32)); } template <> -inline void RequestBuilder::Push(ResultCode value) { +inline void RequestBuilder::Push(bool value) { + Push(u8(value)); +} + +template <> +inline void RequestBuilder::Push(ResultCode value) { Push(value.raw); } +template +void RequestBuilder::Push(const First& first_value, const Other&... other_values) { + Push(first_value); + Push(other_values...); +} + +template +inline void RequestBuilder::PushCopyHandles(H... handles) { + Push(CopyHandleDesc(sizeof...(H))); + Push(static_cast(handles)...); +} + +template +inline void RequestBuilder::PushMoveHandles(H... handles) { + Push(MoveHandleDesc(sizeof...(H))); + Push(static_cast(handles)...); +} + +inline void RequestBuilder::PushCurrentPIDHandle() { + Push(CallingPidDesc()); + Push(u32(0)); +} + +inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id) { + Push(StaticBufferDesc(size, buffer_id)); + Push(buffer_vaddr); +} + +inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, u32 size, + MappedBufferPermissions perms) { + Push(MappedBufferDesc(size, perms)); + Push(buffer_vaddr); +} + class RequestParser : public RequestHelperBase { public: RequestParser(u32* command_buffer, Header command_header) @@ -197,24 +228,60 @@ public: */ template void PopRaw(T& value); + + /** + * @brief Reads the next normal parameters as a struct, by copying it into a new value + * @note: The output class must be correctly packed/padded to fit hardware layout. + */ + template + T PopRaw(); }; /// Pop /// template <> -inline u32 RequestParser::Pop() { +inline u32 RequestParser::Pop() { return cmdbuf[index++]; } +template +void RequestParser::PopRaw(T& value) { + static_assert(std::is_trivially_copyable(), "Raw types should be trivially copyable"); + std::memcpy(&value, cmdbuf + index, sizeof(T)); + index += (sizeof(T) + 3) / 4; // round up to word length +} + +template +T RequestParser::PopRaw() { + T value; + PopRaw(value); + return value; +} + template <> -inline u64 RequestParser::Pop() { +inline u8 RequestParser::Pop() { + return PopRaw(); +} + +template <> +inline u16 RequestParser::Pop() { + return PopRaw(); +} + +template <> +inline u64 RequestParser::Pop() { const u64 lsw = Pop(); const u64 msw = Pop(); return msw << 32 | lsw; } template <> -inline ResultCode RequestParser::Pop() { +inline bool RequestParser::Pop() { + return Pop() != 0; // != 0 to remove warning C4800 +} + +template <> +inline ResultCode RequestParser::Pop() { return ResultCode{Pop()}; } @@ -277,11 +344,4 @@ inline VAddr RequestParser::PopMappedBuffer(size_t* data_size, return Pop(); } -template -void RequestParser::PopRaw(T& value) { - static_assert(std::is_trivially_copyable(), "Raw types should be trivially copyable"); - std::memcpy(&value, cmdbuf + index, sizeof(T)); - index += (sizeof(T) + 3) / 4; // round up to word length -} - } // namespace IPC diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 016ac8d4f..bdfa7391a 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -101,7 +101,7 @@ void CheckNew3DS(IPC::RequestBuilder& rb) { } rb.Push(RESULT_SUCCESS); - rb.Push(u32(is_new_3ds ? 1 : 0)); + rb.Push(is_new_3ds); LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast(is_new_3ds)); } diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp index 907d9c8fa..cfea62962 100644 --- a/src/core/hle/service/y2r_u.cpp +++ b/src/core/hle/service/y2r_u.cpp @@ -189,11 +189,9 @@ static void SetSpacialDithering(Interface* self) { * 2 : u8, 0 = Disabled, 1 = Enabled */ static void GetSpacialDithering(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = spacial_dithering_enabled; + IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0xA, 2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(bool(spacial_dithering_enabled)); LOG_WARNING(Service_Y2R, "(STUBBED) called"); } -- cgit v1.2.3 From 12ed7464771e4c6b1992ef4438be9038fb59b2fc Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 18 Mar 2017 11:47:40 +0100 Subject: IPCHelper Skip method + address comments for apt --- src/core/hle/ipc_helpers.h | 8 ++++- src/core/hle/service/apt/apt.cpp | 74 +++++++++++++++++++++------------------- src/core/hle/service/ptm/ptm.cpp | 2 +- 3 files changed, 46 insertions(+), 38 deletions(-) (limited to 'src/core/hle/service/ptm') diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 98c95a7f3..06c4c5a85 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -28,13 +28,19 @@ public: header.raw); } + void Skip(unsigned size_in_words, bool set_to_null) { + if (set_to_null) + memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); + index += size_in_words; + } + /** * @brief Retrieves the address of a static buffer, used when a buffer is needed for output * @param buffer_id The index of the static buffer * @param data_size If non-null, will store the size of the buffer */ VAddr PeekStaticBuffer(u8 buffer_id, size_t* data_size = nullptr) const { - u32* static_buffer = cmdbuf + Kernel::kStaticBuffersOffset / 4 + buffer_id * 2; + u32* static_buffer = cmdbuf + Kernel::kStaticBuffersOffset / sizeof(u32) + buffer_id * 2; if (data_size) *data_size = StaticBufferDescInfo{static_buffer[0]}.size; return static_buffer[1]; diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index c323deaa4..48437aa73 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -69,10 +69,11 @@ void Initialize(Service::Interface* self) { void GetSharedFont(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x44, 0, 0); // 0x00440000 + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); if (!shared_font_mem) { LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(-1); // TODO: Find the right error code + rb.Skip(1 + 2, true); return; } @@ -85,7 +86,6 @@ void GetSharedFont(Service::Interface* self) { shared_font_relocated = true; } - IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); rb.Push(RESULT_SUCCESS); // No error // Since the SharedMemory interface doesn't provide the address at which the memory was // allocated, the real APT service calculates this address by scanning the entire address space @@ -113,10 +113,10 @@ void GetLockHandle(Service::Interface* self) { rb.Push(RESULT_SUCCESS); // No error rb.Push(applet_attributes); // Applet Attributes, this value is passed to Enable. rb.Push(0); // Least significant bit = power button state - Kernel::Handle handleCopy = Kernel::g_handle_table.Create(lock).MoveFrom(); - rb.PushCopyHandles(handleCopy); + Kernel::Handle handle_copy = Kernel::g_handle_table.Create(lock).MoveFrom(); + rb.PushCopyHandles(handle_copy); - LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handleCopy, + LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", handle_copy, applet_attributes); } @@ -150,14 +150,14 @@ void IsRegistered(Service::Interface* self) { // TODO(Subv): An application is considered "registered" if it has already called APT::Enable // handle this properly once we implement multiprocess support. - bool isRegistered = false; // Set to not registered by default + bool is_registered = false; // Set to not registered by default if (app_id == static_cast(AppletId::AnyLibraryApplet)) { - isRegistered = HLE::Applets::IsLibraryAppletRunning() ? true : false; + is_registered = HLE::Applets::IsLibraryAppletRunning(); } else if (auto applet = HLE::Applets::Applet::Get(static_cast(app_id))) { - isRegistered = true; // Set to registered + is_registered = true; // Set to registered } - rb.Push(isRegistered); + rb.Push(is_registered); LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); } @@ -177,10 +177,9 @@ void SendParameter(Service::Interface* self) { u32 dst_app_id = rp.Pop(); u32 signal_type = rp.Pop(); u32 buffer_size = rp.Pop(); - u32 value = rp.Pop(); - u32 handle = rp.Pop(); - u32 size = rp.Pop(); - u32 buffer = rp.Pop(); + Kernel::Handle handle = rp.PopHandle(); + size_t size; + VAddr buffer = rp.PopStaticBuffer(&size); std::shared_ptr dest_applet = HLE::Applets::Applet::Get(static_cast(dst_app_id)); @@ -203,11 +202,10 @@ void SendParameter(Service::Interface* self) { rb.Push(dest_applet->ReceiveParameter(param)); - LOG_WARNING( - Service_APT, - "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," - "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", - src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); + LOG_WARNING(Service_APT, + "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," + "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", + src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); } void ReceiveParameter(Service::Interface* self) { @@ -218,8 +216,9 @@ void ReceiveParameter(Service::Interface* self) { size_t static_buff_size; VAddr buffer = rp.PeekStaticBuffer(0, &static_buff_size); if (buffer_size > static_buff_size) - LOG_WARNING(Service_APT, "ReceiveParameter: buffer_size is bigger than the size in the " - "buffer descriptor (0x%08X > 0x%08X)", + LOG_WARNING(Service_APT, + "ReceiveParameter: buffer_size is bigger than the size in the " + "buffer descriptor (0x%08X > 0x%08zX)", buffer_size, static_buff_size); IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); @@ -236,7 +235,7 @@ void ReceiveParameter(Service::Interface* self) { Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); - LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); + LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } void GlanceParameter(Service::Interface* self) { @@ -247,8 +246,9 @@ void GlanceParameter(Service::Interface* self) { size_t static_buff_size; VAddr buffer = rp.PeekStaticBuffer(0, &static_buff_size); if (buffer_size > static_buff_size) - LOG_WARNING(Service_APT, "ReceiveParameter: buffer_size is bigger than the size in the " - "buffer descriptor (0x%08X > 0x%08X)", + LOG_WARNING(Service_APT, + "ReceiveParameter: buffer_size is bigger than the size in the " + "buffer descriptor (0x%08X > 0x%08zX)", buffer_size, static_buff_size); IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); @@ -265,7 +265,7 @@ void GlanceParameter(Service::Interface* self) { Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); - LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); + LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } void CancelParameter(Service::Interface* self) { @@ -285,7 +285,7 @@ void CancelParameter(Service::Interface* self) { } void PrepareToStartApplication(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x00150140); + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x15, 5, 0); // 0x00150140 u32 title_info1 = rp.Pop(); u32 title_info2 = rp.Pop(); u32 title_info3 = rp.Pop(); @@ -306,26 +306,26 @@ void PrepareToStartApplication(Service::Interface* self) { } void StartApplication(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x001B00C4); + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1B, 3, 4); // 0x001B00C4 u32 buffer1_size = rp.Pop(); u32 buffer2_size = rp.Pop(); u32 flag = rp.Pop(); - u32 size1 = rp.Pop(); - u32 buffer1_ptr = rp.Pop(); - u32 size2 = rp.Pop(); - u32 buffer2_ptr = rp.Pop(); + size_t size1; + VAddr buffer1_ptr = rp.PopStaticBuffer(&size1); + size_t size2; + VAddr buffer2_ptr = rp.PopStaticBuffer(&size2); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); // No error LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," - "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", + "size1=0x%08zX, buffer1_ptr=0x%08X, size2=0x%08zX, buffer2_ptr=0x%08X", buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); } void AppletUtility(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x004B00C2); + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x4B, 3, 2); // 0x004B00C2 // These are from 3dbrew - I'm not really sure what they're used for. u32 utility_command = rp.Pop(); @@ -438,7 +438,7 @@ void CancelLibraryApplet(Service::Interface* self) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(1); - LOG_WARNING(Service_APT, "(STUBBED) called exiting=%u", exiting); + LOG_WARNING(Service_APT, "(STUBBED) called exiting=%d", exiting); } void SetScreenCapPostPermission(Service::Interface* self) { @@ -501,8 +501,9 @@ void GetStartupArgument(Service::Interface* self) { size_t static_buff_size; VAddr addr = rp.PeekStaticBuffer(0, &static_buff_size); if (parameter_size > static_buff_size) - LOG_WARNING(Service_APT, "GetStartupArgument: parameter_size is bigger than the size in " - "the buffer descriptor (0x%08X > 0x%08X)", + LOG_WARNING(Service_APT, + "GetStartupArgument: parameter_size is bigger than the size in " + "the buffer descriptor (0x%08X > 0x%08zX)", parameter_size, static_buff_size); if (addr && parameter_size) { @@ -512,9 +513,10 @@ void GetStartupArgument(Service::Interface* self) { LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x", startup_argument_type, parameter_size); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); rb.Push(RESULT_SUCCESS); rb.Push(0); + rb.PushStaticBuffer(addr, parameter_size, 0); } void Wrap(Service::Interface* self) { diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index bdfa7391a..8a343a613 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -107,7 +107,7 @@ void CheckNew3DS(IPC::RequestBuilder& rb) { } void CheckNew3DS(Service::Interface* self) { - IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x040A0000); + IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x40A, 0, 0); // 0x040A0000 CheckNew3DS(rb); } -- cgit v1.2.3