diff options
Diffstat (limited to '')
64 files changed, 834 insertions, 134 deletions
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index e386ccdc6..038af7909 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp @@ -28,4 +28,4 @@ void Init() { config_mem.firm_ctr_sdk_ver = 0x0000F297; } -} // namespace +} // namespace ConfigMem diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h index 42fa6d789..1840d1760 100644 --- a/src/core/hle/config_mem.h +++ b/src/core/hle/config_mem.h @@ -53,4 +53,4 @@ extern ConfigMemDef config_mem; void Init(); -} // namespace +} // namespace ConfigMem 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 { address |= static_cast<VAddr>(address_bits_32_47) << 32; return address; } + + u64 Size() const { + return static_cast<u64>(size); + } }; static_assert(sizeof(BufferDescriptorC) == 8, "BufferDescriptorC size is incorrect"); 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: unsigned GetCurrentOffset() const { return static_cast<unsigned>(index); } + + void SetCurrentOffset(unsigned offset) { + index = static_cast<ptrdiff_t>(offset); + } }; class RequestBuilder : public RequestHelperBase { diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 1d24401b1..f902ddf2d 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -57,4 +57,4 @@ private: ~AddressArbiter() override; }; -} // namespace FileSys +} // namespace Kernel diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index ce5d94e99..fb2b6f7a3 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -39,4 +39,4 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() { return MakeResult(std::get<SharedPtr<ClientSession>>(sessions)); } -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 8f7d6ac44..a829aeb6d 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h @@ -47,4 +47,4 @@ private: ~ClientPort() override; }; -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 646a5cc64..72773d8b1 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -48,4 +48,4 @@ ResultCode ClientSession::SendSyncRequest(SharedPtr<Thread> thread) { return server->HandleSyncRequest(std::move(thread)); } -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index 671174ec4..d6ab4f893 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -45,4 +45,4 @@ private: ~ClientSession() override; }; -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/condition_variable.cpp b/src/core/hle/kernel/condition_variable.cpp index 5942eae61..561666384 100644 --- a/src/core/hle/kernel/condition_variable.cpp +++ b/src/core/hle/kernel/condition_variable.cpp @@ -43,7 +43,7 @@ void ConditionVariable::Acquire(Thread* thread) { ResultCode ConditionVariable::Release(s32 target) { if (target == -1) { // When -1, wake up all waiting threads - SetAvailableCount(GetWaitingThreads().size()); + SetAvailableCount(static_cast<s32>(GetWaitingThreads().size())); WakeupAllWaitingThreads(); } else { // Otherwise, wake up just a single thread diff --git a/src/core/hle/kernel/condition_variable.h b/src/core/hle/kernel/condition_variable.h index 0610a284f..0d54031cb 100644 --- a/src/core/hle/kernel/condition_variable.h +++ b/src/core/hle/kernel/condition_variable.h @@ -4,8 +4,8 @@ #pragma once -#include <queue> #include <string> +#include <queue> #include "common/common_types.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/wait_object.h" diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 23f9df0d6..9cae2369f 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -52,4 +52,4 @@ void Event::WakeupAllWaitingThreads() { signaled = false; } -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index cc41abb85..e5c924a75 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -49,4 +49,4 @@ private: ~Event() override; }; -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 12506e64c..74d3d0514 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -104,4 +104,4 @@ void HandleTable::Clear() { next_free_slot = 0; } -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index dba5573a8..935cc22b5 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -130,4 +130,4 @@ private: extern HandleTable g_handle_table; -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ac62a0d5a..ecf32c18a 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) { for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) { buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); } - if (command_header->buf_c_descriptor_flags != - IPC::CommandHeader::BufferDescriptorCFlag::Disabled) { - if (command_header->buf_c_descriptor_flags != - IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { - UNIMPLEMENTED(); - } - } + + buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; // Padding to align to 16 bytes rp.AlignWithPadding(); @@ -104,9 +99,8 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { data_payload_offset = rp.GetCurrentOffset(); - if (domain_message_header && - domain_message_header->command == - IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { + if (domain_message_header && domain_message_header->command == + IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { // CloseVirtualHandle command does not have SFC* or any data return; } @@ -117,6 +111,31 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); } + rp.SetCurrentOffset(buffer_c_offset); + + // For Inline buffers, the response data is written directly to buffer_c_offset + // and in this case we don't have any BufferDescriptorC on the request. + if (command_header->buf_c_descriptor_flags > + IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) { + if (command_header->buf_c_descriptor_flags == + IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { + buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); + } else { + unsigned num_buf_c_descriptors = + static_cast<unsigned>(command_header->buf_c_descriptor_flags.Value()) - 2; + + // This is used to detect possible underflows, in case something is broken + // with the two ifs above and the flags value is == 0 || == 1. + ASSERT(num_buf_c_descriptors < 14); + + for (unsigned i = 0; i < num_buf_c_descriptors; ++i) { + buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); + } + } + } + + rp.SetCurrentOffset(data_payload_offset); + command = rp.Pop<u32_le>(); rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. } @@ -190,7 +209,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P for (auto& object : domain_objects) { request_handlers.emplace_back(object); - dst_cmdbuf[domain_offset++] = request_handlers.size(); + dst_cmdbuf[domain_offset++] = static_cast<u32_le>(request_handlers.size()); } } return RESULT_SUCCESS; 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: return buffer_b_desciptors; } + const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { + return buffer_c_desciptors; + } + const std::unique_ptr<IPC::DomainMessageHeader>& GetDomainMessageHeader() const { return domain_message_header; } @@ -200,8 +204,10 @@ private: std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; + std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; unsigned data_payload_offset{}; + unsigned buffer_c_offset{}; u32_le command{}; }; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index 517dc47a8..0149a3ed6 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp @@ -151,4 +151,4 @@ void ResourceLimitsInit() { void ResourceLimitsShutdown() {} -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h index 42874eb8d..1a0ca11f1 100644 --- a/src/core/hle/kernel/resource_limit.h +++ b/src/core/hle/kernel/resource_limit.h @@ -123,4 +123,4 @@ void ResourceLimitsInit(); // Destroys the resource limits void ResourceLimitsShutdown(); -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index 49a9cdfa3..0b7061403 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -50,4 +50,4 @@ std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortP return std::make_tuple(std::move(server_port), std::move(client_port)); } -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index 6fe7c7f2f..9ef4ecc35 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h @@ -72,4 +72,4 @@ private: ~ServerPort() override; }; -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index f4360ddf3..6ff4ef8c1 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -113,4 +113,4 @@ private: * in the command buffer. */ ResultCode TranslateHLERequest(ServerSession* server_session); -} +} // namespace Kernel diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp index 8a2a7e3fd..642914744 100644 --- a/src/core/hle/kernel/session.cpp +++ b/src/core/hle/kernel/session.cpp @@ -9,4 +9,4 @@ namespace Kernel { Session::Session() {} Session::~Session() {} -} +} // namespace Kernel diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 2cf319e99..e69b034a7 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -24,4 +24,4 @@ public: ServerSession* server = nullptr; ///< The server endpoint of the session. SharedPtr<ClientPort> port; ///< The port that this session is associated with (optional). }; -} +} // namespace Kernel diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 93a6f2182..e948819c0 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -98,10 +98,10 @@ public: ResultCode Unmap(Process* target_process, VAddr address); /** - * Gets a pointer to the shared memory block - * @param offset Offset from the start of the shared memory block to get pointer - * @return Pointer to the shared memory block from the specified offset - */ + * Gets a pointer to the shared memory block + * @param offset Offset from the start of the shared memory block to get pointer + * @return Pointer to the shared memory block from the specified offset + */ u8* GetPointer(u32 offset = 0); /// Process that created this shared memory block. @@ -129,4 +129,4 @@ private: ~SharedMemory() override; }; -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 088058ebc..516309036 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -57,7 +57,7 @@ static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { } /// Connect to an OS service given the port name, returns the handle to the port to out -static ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address) { +static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address) { if (!Memory::IsValidVirtualAddress(port_name_address)) return ERR_NOT_FOUND; @@ -253,8 +253,8 @@ static ResultCode CancelSynchronization(Handle thread_handle) { } /// Attempts to locks a mutex, creating it if it does not already exist -static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr, - Handle requesting_thread_handle) { +static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr, + Handle requesting_thread_handle) { LOG_TRACE(Kernel_SVC, "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " "requesting_current_thread_handle=0x%08X", @@ -278,7 +278,7 @@ static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr, } /// Unlock a mutex -static ResultCode UnlockMutex(VAddr mutex_addr) { +static ResultCode ArbitrateUnlock(VAddr mutex_addr) { LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr); SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); @@ -315,7 +315,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) *result = g_current_process->allowed_thread_priority_mask; break; case GetInfoType::MapRegionBaseAddr: - *result = vm_manager.GetAddressSpaceBaseAddr(); + *result = vm_manager.GetMapRegionBaseAddr(); break; case GetInfoType::MapRegionSize: *result = vm_manager.GetAddressSpaceSize(); @@ -739,6 +739,18 @@ static ResultCode SetThreadCoreMask(u64, u64, u64) { return RESULT_SUCCESS; } +static ResultCode CreateSharedMemory(Handle* handle, u64 sz, u32 local_permissions, + u32 remote_permissions) { + LOG_TRACE(Kernel_SVC, "called, sz=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", sz, + local_permissions, remote_permissions); + auto sharedMemHandle = SharedMemory::Create( + g_handle_table.Get<Process>(KernelHandle::CurrentProcess), sz, + (Kernel::MemoryPermission)local_permissions, (Kernel::MemoryPermission)remote_permissions); + + CASCADE_RESULT(*handle, g_handle_table.Create(sharedMemHandle)); + return RESULT_SUCCESS; +} + namespace { struct FunctionDef { using Func = void(); @@ -776,12 +788,12 @@ static const FunctionDef SVC_Table[] = { {0x17, SvcWrap<ResetSignal>, "ResetSignal"}, {0x18, SvcWrap<WaitSynchronization>, "WaitSynchronization"}, {0x19, SvcWrap<CancelSynchronization>, "CancelSynchronization"}, - {0x1A, SvcWrap<LockMutex>, "LockMutex"}, - {0x1B, SvcWrap<UnlockMutex>, "UnlockMutex"}, + {0x1A, SvcWrap<ArbitrateLock>, "ArbitrateLock"}, + {0x1B, SvcWrap<ArbitrateUnlock>, "ArbitrateUnlock"}, {0x1C, SvcWrap<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"}, {0x1D, SvcWrap<SignalProcessWideKey>, "SignalProcessWideKey"}, {0x1E, SvcWrap<GetSystemTick>, "GetSystemTick"}, - {0x1F, SvcWrap<ConnectToPort>, "ConnectToPort"}, + {0x1F, SvcWrap<ConnectToNamedPort>, "ConnectToNamedPort"}, {0x20, nullptr, "SendSyncRequestLight"}, {0x21, SvcWrap<SendSyncRequest>, "SendSyncRequest"}, {0x22, nullptr, "SendSyncRequestWithUserBuffer"}, @@ -825,12 +837,12 @@ static const FunctionDef SVC_Table[] = { {0x48, nullptr, "Unknown"}, {0x49, nullptr, "Unknown"}, {0x4A, nullptr, "Unknown"}, - {0x4B, nullptr, "Unknown"}, - {0x4C, nullptr, "Unknown"}, + {0x4B, nullptr, "CreateJitMemory"}, + {0x4C, nullptr, "MapJitMemory"}, {0x4D, nullptr, "SleepSystem"}, {0x4E, nullptr, "ReadWriteRegister"}, {0x4F, nullptr, "SetProcessActivity"}, - {0x50, nullptr, "CreateSharedMemory"}, + {0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"}, {0x51, nullptr, "MapTransferMemory"}, {0x52, nullptr, "UnmapTransferMemory"}, {0x53, nullptr, "CreateInterruptEvent"}, diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h index 42cc41da3..bc471d01e 100644 --- a/src/core/hle/kernel/svc.h +++ b/src/core/hle/kernel/svc.h @@ -14,7 +14,11 @@ struct MemoryInfo { u32 type; u32 attributes; u32 permission; + u32 device_refcount; + u32 ipc_refcount; + INSERT_PADDING_WORDS(1); }; +static_assert(sizeof(MemoryInfo) == 0x28, "MemoryInfo has incorrect size."); struct PageInfo { u64 flags; diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index fd7054bbd..7a165d8dc 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -145,6 +145,15 @@ void SvcWrap() { FuncReturn(retval); } +template <ResultCode func(Handle*, u64, u32, u32)> +void SvcWrap() { + u32 param_1 = 0; + u32 retval = + func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; + Core::CPU().SetReg(1, param_1); + FuncReturn(retval); +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Function wrappers that return type u32 diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index a93a6c87a..8da745634 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -111,4 +111,4 @@ void TimersInit() { void TimersShutdown() {} -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 82552372d..82d19cefc 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -76,4 +76,4 @@ void TimersInit(); /// Tears down the timer variables void TimersShutdown(); -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index bf261699e..93662a45e 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -375,6 +375,11 @@ u64 VMManager::GetAddressSpaceSize() { return MAX_ADDRESS; } +VAddr VMManager::GetMapRegionBaseAddr() { + LOG_WARNING(Kernel, "(STUBBED) called"); + return Memory::HEAP_VADDR; +} + VAddr VMManager::GetNewMapRegionBaseAddr() { LOG_WARNING(Kernel, "(STUBBED) called"); return 0x8000000; diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 7a7fee54a..b17385c7c 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -192,6 +192,9 @@ public: /// Gets the total address space address size, used by svcGetInfo u64 GetAddressSpaceSize(); + /// Gets the map region base address, used by svcGetInfo + VAddr GetMapRegionBaseAddr(); + /// Gets the base address for a new memory region, used by svcGetInfo VAddr GetNewMapRegionBaseAddr(); diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index 147f4e62e..7f0192fd3 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -9,15 +9,76 @@ namespace Service { namespace Account { +class IProfile final : public ServiceFramework<IProfile> { +public: + IProfile() : ServiceFramework("IProfile") { + static const FunctionInfo functions[] = { + {1, &IProfile::GetBase, "GetBase"}, + }; + RegisterHandlers(functions); + } + +private: + void GetBase(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + ProfileBase profile_base{}; + IPC::RequestBuilder rb{ctx, 16}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(profile_base); + } +}; + +class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { +public: + IManagerForApplication() : ServiceFramework("IProfile") { + static const FunctionInfo functions[] = { + {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, + }; + RegisterHandlers(functions); + } + +private: + void CheckAvailability(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::RequestBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(true); // TODO: Check when this is supposed to return true and when not + } +}; + +void ACC_U0::GetUserExistence(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::RequestBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(true); // TODO: Check when this is supposed to return true and when not +} + +void ACC_U0::GetProfile(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IProfile>(); + LOG_DEBUG(Service, "called"); +} + void ACC_U0::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::RequestBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } +void ACC_U0::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IManagerForApplication>(); + LOG_DEBUG(Service, "called"); +} + ACC_U0::ACC_U0() : ServiceFramework("acc:u0") { static const FunctionInfo functions[] = { + {1, &ACC_U0::GetUserExistence, "GetUserExistence"}, + {5, &ACC_U0::GetProfile, "GetProfile"}, {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, + {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h index ac243d5b8..51676e859 100644 --- a/src/core/hle/service/acc/acc_u0.h +++ b/src/core/hle/service/acc/acc_u0.h @@ -9,13 +9,28 @@ namespace Service { namespace Account { +// TODO: RE this structure +struct UserData { + INSERT_PADDING_BYTES(0x80); +}; +static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size"); + +// TODO: RE this structure +struct ProfileBase { + INSERT_PADDING_BYTES(0x38); +}; +static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase structure has incorrect size"); + class ACC_U0 final : public ServiceFramework<ACC_U0> { public: ACC_U0(); ~ACC_U0() = default; private: + void GetUserExistence(Kernel::HLERequestContext& ctx); + void GetProfile(Kernel::HLERequestContext& ctx); void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); + void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); }; } // namespace Account diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index b360e7e5f..b4a6ad232 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -55,6 +55,8 @@ class ISelfController final : public ServiceFramework<ISelfController> { public: ISelfController() : ServiceFramework("ISelfController") { static const FunctionInfo functions[] = { + {1, &ISelfController::LockExit, "LockExit"}, + {2, &ISelfController::UnlockExit, "UnlockExit"}, {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, {12, &ISelfController::SetPerformanceModeChangedNotification, @@ -128,6 +130,20 @@ private: LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled)); } + + void LockExit(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); + } + + void UnlockExit(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); + } }; class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { @@ -201,10 +217,77 @@ private: Kernel::SharedPtr<Kernel::Event> event; }; +class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { +public: + explicit IStorageAccessor(std::vector<u8> buffer) + : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) { + static const FunctionInfo functions[] = { + {0, &IStorageAccessor::GetSize, "GetSize"}, + {11, &IStorageAccessor::Read, "Read"}, + }; + RegisterHandlers(functions); + } + +private: + std::vector<u8> buffer; + + void GetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 4}; + + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast<u64>(buffer.size())); + + LOG_DEBUG(Service, "called"); + } + + void Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + u64 offset = rp.Pop<u64>(); + + const auto& output_buffer = ctx.BufferDescriptorC()[0]; + + ASSERT(offset + output_buffer.Size() <= buffer.size()); + + Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size()); + + IPC::RequestBuilder rb{ctx, 2}; + + rb.Push(RESULT_SUCCESS); + + LOG_DEBUG(Service, "called"); + } +}; + +class IStorage final : public ServiceFramework<IStorage> { +public: + explicit IStorage(std::vector<u8> buffer) + : ServiceFramework("IStorage"), buffer(std::move(buffer)) { + static const FunctionInfo functions[] = { + {0, &IStorage::Open, "Open"}, + }; + RegisterHandlers(functions); + } + +private: + std::vector<u8> buffer; + + void Open(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<AM::IStorageAccessor>(buffer); + + LOG_DEBUG(Service, "called"); + } +}; + class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { public: IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { static const FunctionInfo functions[] = { + {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, + {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, @@ -215,6 +298,26 @@ public: } private: + void PopLaunchParameter(Kernel::HLERequestContext& ctx) { + constexpr u8 data[0x88] = { + 0xca, 0x97, 0x94, 0xc7, // Magic + 1, 0, 0, 0, // IsAccountSelected (bool) + 1, 0, 0, 0, // User Id (word 0) + 0, 0, 0, 0, // User Id (word 1) + 0, 0, 0, 0, // User Id (word 2) + 0, 0, 0, 0 // User Id (word 3) + }; + + std::vector<u8> buffer(data, data + sizeof(data)); + + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<AM::IStorage>(buffer); + + LOG_DEBUG(Service, "called"); + } + void SetTerminateResult(Kernel::HLERequestContext& ctx) { // Takes an input u32 Result, no output. // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. @@ -228,6 +331,13 @@ private: LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); } + void GetDesiredLanguage(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push<u64>(SystemLanguage::English); + LOG_WARNING(Service, "(STUBBED) called"); + } + void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index beb75bf2a..6ee5b0e9f 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -10,6 +10,12 @@ namespace Service { namespace AM { +// TODO: Add more languages +enum SystemLanguage { + Japanese = 0, + English = 1, +}; + class AppletOE final : public ServiceFramework<AppletOE> { public: AppletOE(); diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp index 66d94ff52..bf7e12288 100644 --- a/src/core/hle/service/apm/apm.cpp +++ b/src/core/hle/service/apm/apm.cpp @@ -51,7 +51,8 @@ private: APM::APM() : ServiceFramework("apm") { static const FunctionInfo functions[] = { - {0x00000000, &APM::OpenSession, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"}, + {0x00000000, &APM::OpenSession, "OpenSession"}, + {0x00000001, nullptr, "GetPerformanceMode"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 6254237fa..be7a6ff65 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -18,9 +18,9 @@ namespace HID { // Updating period for each HID device. // TODO(shinyquagsire23): These need better values. -constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 234; -constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 104; -constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 101; +constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 10000; +constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 10000; +constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 10000; class IAppletResource final : public ServiceFramework<IAppletResource> { public: diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index 2d0d2fb65..13c9ee3d3 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -47,6 +47,7 @@ private: /// Log field type enum class Field : u8 { + Skip = 1, Message = 2, Line = 3, Filename = 4, @@ -85,6 +86,11 @@ private: while (addr < end_addr) { const Field field{static_cast<Field>(Memory::Read8(addr++))}; size_t length{Memory::Read8(addr++)}; + + if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) { + ++addr; + } + switch (field) { case Field::Message: message = Memory::ReadCString(addr, length); @@ -99,6 +105,7 @@ private: function = Memory::ReadCString(addr, length); break; } + addr += length; } diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 0670ca155..417455200 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -48,6 +48,18 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { rb.Push(nv_result); } +void NVDRV::Close(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + u32 fd = rp.Pop<u32>(); + + auto result = nvdrv->Close(fd); + + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(result); +} + void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::RequestBuilder rb{ctx, 3}; @@ -55,12 +67,25 @@ void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); } +void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u64 pid = rp.Pop<u64>(); + u64 unk = rp.Pop<u64>(); + + LOG_WARNING(Service, "(STUBBED) called, pid=0x%llx, unk=0x%llx", pid, unk); + + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) : ServiceFramework(name), nvdrv(std::move(nvdrv)) { static const FunctionInfo functions[] = { {0, &NVDRV::Open, "Open"}, {1, &NVDRV::Ioctl, "Ioctl"}, + {2, &NVDRV::Close, "Close"}, {3, &NVDRV::Initialize, "Initialize"}, + {8, &NVDRV::SetClientPID, "SetClientPID"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 8c95b7217..2283f358e 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h @@ -20,7 +20,9 @@ public: private: void Open(Kernel::HLERequestContext& ctx); void Ioctl(Kernel::HLERequestContext& ctx); + void Close(Kernel::HLERequestContext& ctx); void Initialize(Kernel::HLERequestContext& ctx); + void SetClientPID(Kernel::HLERequestContext& ctx); std::shared_ptr<Module> nvdrv; }; diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index cf525a875..9d3013c16 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -7,8 +7,8 @@ #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" #include "core/hle/service/nvdrv/devices/nvmap.h" -#include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvdrv/interface.h" +#include "core/hle/service/nvdrv/nvdrv.h" namespace Service { namespace Nvidia { @@ -49,5 +49,15 @@ u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector return device->ioctl(command, input, output); } +ResultCode Module::Close(u32 fd) { + auto itr = open_files.find(fd); + ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); + + open_files.erase(itr); + + // TODO(flerovium): return correct result code if operation failed. + return RESULT_SUCCESS; +} + } // namespace Nvidia } // namespace Service diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 1940ced99..e44644624 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -35,6 +35,8 @@ public: u32 Open(std::string device_name); /// Sends an ioctl command to the specified file descriptor. u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output); + /// Closes a device file descriptor and returns operation success. + ResultCode Close(u32 fd); private: /// Id to use for the next open file descriptor. diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index fe76b381c..19213a2f4 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -24,8 +24,10 @@ #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/pctl/pctl.h" #include "core/hle/service/service.h" +#include "core/hle/service/set/set.h" #include "core/hle/service/sm/controller.h" #include "core/hle/service/sm/sm.h" +#include "core/hle/service/sockets/sockets.h" #include "core/hle/service/time/time.h" #include "core/hle/service/vi/vi.h" @@ -174,8 +176,10 @@ void Init() { LM::InstallInterfaces(*SM::g_service_manager); Nvidia::InstallInterfaces(*SM::g_service_manager); PCTL::InstallInterfaces(*SM::g_service_manager); + Sockets::InstallInterfaces(*SM::g_service_manager); Time::InstallInterfaces(*SM::g_service_manager); VI::InstallInterfaces(*SM::g_service_manager); + Set::InstallInterfaces(*SM::g_service_manager); LOG_DEBUG(Service, "initialized OK"); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 8e1c5b399..9c2e826da 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -21,7 +21,7 @@ class ClientPort; class ServerPort; class ServerSession; class HLERequestContext; -} +} // namespace Kernel namespace Service { @@ -189,4 +189,4 @@ extern std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_ /// Adds a port to the named port table void AddNamedPort(std::string name, Kernel::SharedPtr<Kernel::ClientPort> port); -} // namespace +} // namespace Service diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp new file mode 100644 index 000000000..3715acd74 --- /dev/null +++ b/src/core/hle/service/set/set.cpp @@ -0,0 +1,42 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <chrono> +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/client_session.h" +#include "core/hle/service/set/set.h" + +namespace Service { +namespace Set { + +void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { + constexpr std::array<u8, 13> lang_codes{}; + + const auto& output_buffer = ctx.BufferDescriptorC()[0]; + + Memory::WriteBlock(output_buffer.Address(), lang_codes.data(), lang_codes.size()); + + IPC::RequestBuilder rb{ctx, 4}; + + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast<u64>(lang_codes.size())); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +SET::SET(const char* name) : ServiceFramework(name) { + static const FunctionInfo functions[] = { + {1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"}, + }; + RegisterHandlers(functions); +} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared<SET>("set")->InstallAsService(service_manager); +} + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h new file mode 100644 index 000000000..61e957946 --- /dev/null +++ b/src/core/hle/service/set/set.h @@ -0,0 +1,25 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace Set { + +class SET final : public ServiceFramework<SET> { +public: + explicit SET(const char* name); + ~SET() = default; + +private: + void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx); +}; + +/// Registers all Set services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index e8f5d0e4a..7b1c8ee37 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp @@ -32,6 +32,12 @@ void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service, "called"); } +void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) { + DuplicateSession(ctx); + + LOG_WARNING(Service, "(STUBBED) called, using DuplicateSession"); +} + void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); @@ -46,7 +52,7 @@ Controller::Controller() : ServiceFramework("IpcController") { {0x00000001, nullptr, "ConvertDomainToSession"}, {0x00000002, &Controller::DuplicateSession, "DuplicateSession"}, {0x00000003, &Controller::QueryPointerBufferSize, "QueryPointerBufferSize"}, - {0x00000004, nullptr, "DuplicateSessionEx"}, + {0x00000004, &Controller::DuplicateSessionEx, "DuplicateSessionEx"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/sm/controller.h b/src/core/hle/service/sm/controller.h index 0b873b492..7b4bc4b75 100644 --- a/src/core/hle/service/sm/controller.h +++ b/src/core/hle/service/sm/controller.h @@ -17,6 +17,7 @@ public: private: void ConvertSessionToDomain(Kernel::HLERequestContext& ctx); void DuplicateSession(Kernel::HLERequestContext& ctx); + void DuplicateSessionEx(Kernel::HLERequestContext& ctx); void QueryPointerBufferSize(Kernel::HLERequestContext& ctx); }; diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index f3bffac54..c4078f02f 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -103,6 +103,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { rb.Push(client_port.Code()); LOG_ERROR(Service_SM, "called service=%s -> error 0x%08X", name.c_str(), client_port.Code().raw); + UNIMPLEMENTED(); return; } diff --git a/src/core/hle/service/sockets/bsd_u.cpp b/src/core/hle/service/sockets/bsd_u.cpp new file mode 100644 index 000000000..a819acc96 --- /dev/null +++ b/src/core/hle/service/sockets/bsd_u.cpp @@ -0,0 +1,67 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/sockets/bsd_u.h" + +namespace Service { +namespace Sockets { + +void BSD_U::RegisterClient(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::RequestBuilder rb{ctx, 3}; + + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); // bsd errno +} + +void BSD_U::Socket(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + u32 domain = rp.Pop<u32>(); + u32 type = rp.Pop<u32>(); + u32 protocol = rp.Pop<u32>(); + + LOG_WARNING(Service, "(STUBBED) called domain=%u type=%u protocol=%u", domain, type, protocol); + + u32 fd = next_fd++; + + IPC::RequestBuilder rb{ctx, 4}; + + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(fd); + rb.Push<u32>(0); // bsd errno +} + +void BSD_U::Connect(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::RequestBuilder rb{ctx, 4}; + + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); // ret + rb.Push<u32>(0); // bsd errno +} + +void BSD_U::SendTo(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::RequestBuilder rb{ctx, 4}; + + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); // ret + rb.Push<u32>(0); // bsd errno +} + +BSD_U::BSD_U() : ServiceFramework("bsd:u") { + static const FunctionInfo functions[] = {{0, &BSD_U::RegisterClient, "RegisterClient"}, + {2, &BSD_U::Socket, "Socket"}, + {11, &BSD_U::SendTo, "SendTo"}, + {14, &BSD_U::Connect, "Connect"}}; + RegisterHandlers(functions); +} + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/sockets/bsd_u.h b/src/core/hle/service/sockets/bsd_u.h new file mode 100644 index 000000000..1fe96d850 --- /dev/null +++ b/src/core/hle/service/sockets/bsd_u.h @@ -0,0 +1,29 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace Sockets { + +class BSD_U final : public ServiceFramework<BSD_U> { +public: + BSD_U(); + ~BSD_U() = default; + +private: + void RegisterClient(Kernel::HLERequestContext& ctx); + void Socket(Kernel::HLERequestContext& ctx); + void Connect(Kernel::HLERequestContext& ctx); + void SendTo(Kernel::HLERequestContext& ctx); + + /// Id to use for the next open file descriptor. + u32 next_fd = 1; +}; + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h new file mode 100644 index 000000000..32a3ac8c5 --- /dev/null +++ b/src/core/hle/service/sockets/sfdnsres.h @@ -0,0 +1,22 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace Sockets { + +class SFDNSRES final : public ServiceFramework<SFDNSRES> { +public: + SFDNSRES() : ServiceFramework("sfdnsres") {} + ~SFDNSRES() = default; + +private: +}; + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp new file mode 100644 index 000000000..f1396eaa1 --- /dev/null +++ b/src/core/hle/service/sockets/sockets.cpp @@ -0,0 +1,18 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/sockets/bsd_u.h" +#include "core/hle/service/sockets/sfdnsres.h" +#include "core/hle/service/sockets/sockets.h" + +namespace Service { +namespace Sockets { + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared<BSD_U>()->InstallAsService(service_manager); + std::make_shared<SFDNSRES>()->InstallAsService(service_manager); +} + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h new file mode 100644 index 000000000..7e89c8d2c --- /dev/null +++ b/src/core/hle/service/sockets/sockets.h @@ -0,0 +1,16 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace Sockets { + +/// Registers all Sockets services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index e3d58aa60..9fed89246 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -2,14 +2,142 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <chrono> +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/client_session.h" #include "core/hle/service/time/time.h" #include "core/hle/service/time/time_s.h" +#include "core/hle/service/time/time_u.h" namespace Service { namespace Time { +class ISystemClock final : public ServiceFramework<ISystemClock> { +public: + ISystemClock() : ServiceFramework("ISystemClock") { + static const FunctionInfo functions[] = { + {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, + }; + RegisterHandlers(functions); + } + +private: + void GetCurrentTime(Kernel::HLERequestContext& ctx) { + const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()) + .count()}; + IPC::RequestBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push<u64>(time_since_epoch); + LOG_DEBUG(Service, "called"); + } +}; + +class ISteadyClock final : public ServiceFramework<ISteadyClock> { +public: + ISteadyClock() : ServiceFramework("ISteadyClock") {} +}; + +class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { +public: + ITimeZoneService() : ServiceFramework("ITimeZoneService") { + static const FunctionInfo functions[] = { + {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"}, + {2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"}, + {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, + }; + RegisterHandlers(functions); + } + +private: + void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + LocationName location_name{}; + IPC::RequestBuilder rb{ctx, (sizeof(LocationName) / 4) + 2}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(location_name); + } + + void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::RequestBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); + } + + void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u64 posix_time = rp.Pop<u64>(); + + LOG_WARNING(Service, "(STUBBED) called, posix_time=0x%016llX", posix_time); + + CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; + CalendarAdditionalInfo additional_info{}; + IPC::RequestBuilder rb{ctx, 10}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(calendar_time); + rb.PushRaw(additional_info); + } +}; + +void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { + auto client_port = std::make_shared<ISystemClock>()->CreatePort(); + auto session = client_port->Connect(); + if (session.Succeeded()) { + LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", + (*session)->GetObjectId()); + IPC::RequestBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushMoveObjects(std::move(session).Unwrap()); + } else { + UNIMPLEMENTED(); + } +} + +void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { + auto client_port = std::make_shared<ISystemClock>()->CreatePort(); + auto session = client_port->Connect(); + if (session.Succeeded()) { + LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", + (*session)->GetObjectId()); + IPC::RequestBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushMoveObjects(std::move(session).Unwrap()); + } else { + UNIMPLEMENTED(); + } +} + +void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { + auto client_port = std::make_shared<ISteadyClock>()->CreatePort(); + auto session = client_port->Connect(); + if (session.Succeeded()) { + LOG_DEBUG(Service, "called, initialized ISteadyClock -> session=%u", + (*session)->GetObjectId()); + IPC::RequestBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushMoveObjects(std::move(session).Unwrap()); + } else { + UNIMPLEMENTED(); + } +} + +void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<ITimeZoneService>(); + LOG_DEBUG(Service, "called"); +} + +Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) + : ServiceFramework(name), time(std::move(time)) {} + void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<TimeS>()->InstallAsService(service_manager); + auto time = std::make_shared<Module>(); + std::make_shared<TIME_S>(time)->InstallAsService(service_manager); + std::make_shared<TIME_U>(time)->InstallAsService(service_manager); } } // namespace Time diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 7d0803e24..399f474d6 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -9,6 +9,46 @@ namespace Service { namespace Time { +// TODO(Rozelette) RE this structure +struct LocationName { + INSERT_PADDING_BYTES(0x24); +}; +static_assert(sizeof(LocationName) == 0x24, "LocationName is incorrect size"); + +struct CalendarTime { + u16_le year; + u8 month; // Starts at 1 + u8 day; // Starts at 1 + u8 hour; + u8 minute; + u8 second; + INSERT_PADDING_BYTES(1); +}; +static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size"); + +// TODO(Rozelette) RE this structure +struct CalendarAdditionalInfo { + INSERT_PADDING_BYTES(0x18); +}; +static_assert(sizeof(CalendarAdditionalInfo) == 0x18, + "CalendarAdditionalInfo structure has incorrect size"); + +class Module final { +public: + class Interface : public ServiceFramework<Interface> { + public: + Interface(std::shared_ptr<Module> time, const char* name); + + void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); + void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx); + void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); + void GetTimeZoneService(Kernel::HLERequestContext& ctx); + + protected: + std::shared_ptr<Module> time; + }; +}; + /// Registers all Time services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp index 6b0597d8e..1634d3300 100644 --- a/src/core/hle/service/time/time_s.cpp +++ b/src/core/hle/service/time/time_s.cpp @@ -2,54 +2,14 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <chrono> -#include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/service/time/time_s.h" namespace Service { namespace Time { -class ISystemClock final : public ServiceFramework<ISystemClock> { -public: - ISystemClock() : ServiceFramework("ISystemClock") { - static const FunctionInfo functions[] = { - {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, - }; - RegisterHandlers(functions); - } - -private: - void GetCurrentTime(Kernel::HLERequestContext& ctx) { - const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count()}; - IPC::RequestBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); - rb.Push<u64>(time_since_epoch); - LOG_DEBUG(Service, "called"); - } -}; - -void TimeS::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { - auto client_port = std::make_shared<ISystemClock>()->CreatePort(); - auto session = client_port->Connect(); - if (session.Succeeded()) { - LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", - (*session)->GetObjectId()); - IPC::RequestBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushMoveObjects(std::move(session).Unwrap()); - } else { - UNIMPLEMENTED(); - } -} - -TimeS::TimeS() : ServiceFramework("time:s") { +TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") { static const FunctionInfo functions[] = { - {0x00000000, &TimeS::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, + {0, &TIME_S::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/time/time_s.h b/src/core/hle/service/time/time_s.h index 073227910..abc2a8c5a 100644 --- a/src/core/hle/service/time/time_s.h +++ b/src/core/hle/service/time/time_s.h @@ -4,19 +4,14 @@ #pragma once -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/service/service.h" +#include "core/hle/service/time/time.h" namespace Service { namespace Time { -class TimeS final : public ServiceFramework<TimeS> { +class TIME_S final : public Module::Interface { public: - TimeS(); - ~TimeS() = default; - -private: - void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); + explicit TIME_S(std::shared_ptr<Module> time); }; } // namespace Time diff --git a/src/core/hle/service/time/time_u.cpp b/src/core/hle/service/time/time_u.cpp new file mode 100644 index 000000000..ae4f78adf --- /dev/null +++ b/src/core/hle/service/time/time_u.cpp @@ -0,0 +1,21 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/time/time_u.h" + +namespace Service { +namespace Time { + +TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:u") { + static const FunctionInfo functions[] = { + {0, &TIME_U::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, + {1, &TIME_U::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, + {2, &TIME_U::GetStandardSteadyClock, "GetStandardSteadyClock"}, + {3, &TIME_U::GetTimeZoneService, "GetTimeZoneService"}, + }; + RegisterHandlers(functions); +} + +} // namespace Time +} // namespace Service diff --git a/src/core/hle/service/time/time_u.h b/src/core/hle/service/time/time_u.h new file mode 100644 index 000000000..f99d25057 --- /dev/null +++ b/src/core/hle/service/time/time_u.h @@ -0,0 +1,18 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/time/time.h" + +namespace Service { +namespace Time { + +class TIME_U final : public Module::Interface { +public: + explicit TIME_U(std::shared_ptr<Module> time); +}; + +} // namespace Time +} // namespace Service diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index cae2c4466..c624e734e 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -26,7 +26,7 @@ public: // This default size was chosen arbitrarily. static constexpr size_t DefaultBufferSize = 0x40; Parcel() : buffer(DefaultBufferSize) {} - Parcel(std::vector<u8> data) : buffer(std::move(data)) {} + explicit Parcel(std::vector<u8> data) : buffer(std::move(data)) {} virtual ~Parcel() = default; template <typename T> @@ -47,8 +47,9 @@ public: } std::vector<u8> ReadBlock(size_t length) { - std::vector<u8> data(length); - std::memcpy(data.data(), buffer.data() + read_index, length); + const u8* const begin = buffer.data() + read_index; + const u8* const end = begin + length; + std::vector<u8> data(begin, end); read_index += length; read_index = Common::AlignUp(read_index, 4); return data; @@ -94,16 +95,16 @@ public: Header header{}; header.data_offset = sizeof(Header); - header.data_size = write_index - sizeof(Header); + header.data_size = static_cast<u32_le>(write_index - sizeof(Header)); std::memcpy(buffer.data(), &header, sizeof(Header)); return buffer; } protected: - virtual void SerializeData(){}; + virtual void SerializeData() {} - virtual void DeserializeData(){}; + virtual void DeserializeData() {} private: struct Header { @@ -121,7 +122,7 @@ private: class NativeWindow : public Parcel { public: - NativeWindow(u32 id) : Parcel() { + explicit NativeWindow(u32 id) : Parcel() { data.id = id; } ~NativeWindow() override = default; @@ -137,7 +138,7 @@ private: u32_le process_id; u32_le id; INSERT_PADDING_BYTES(0xC); - std::array<u8, 8> dspdrv = {'d', 's', 'p', 'd', 'r', 'v'}; + std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; INSERT_PADDING_BYTES(8); }; static_assert(sizeof(Data) == 0x28, "ParcelData has wrong size"); @@ -147,12 +148,12 @@ private: class IGBPConnectRequestParcel : public Parcel { public: - IGBPConnectRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { + explicit IGBPConnectRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { Deserialize(); } ~IGBPConnectRequestParcel() override = default; - void DeserializeData() { + void DeserializeData() override { std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -168,7 +169,7 @@ public: class IGBPConnectResponseParcel : public Parcel { public: - IGBPConnectResponseParcel(u32 width, u32 height) : Parcel() { + explicit IGBPConnectResponseParcel(u32 width, u32 height) : Parcel() { data.width = width; data.height = height; } @@ -194,12 +195,13 @@ private: class IGBPSetPreallocatedBufferRequestParcel : public Parcel { public: - IGBPSetPreallocatedBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { + explicit IGBPSetPreallocatedBufferRequestParcel(const std::vector<u8>& buffer) + : Parcel(buffer) { Deserialize(); } ~IGBPSetPreallocatedBufferRequestParcel() override = default; - void DeserializeData() { + void DeserializeData() override { std::u16string token = ReadInterfaceToken(); data = Read<Data>(); ASSERT(data.graphic_buffer_length == sizeof(IGBPBuffer)); @@ -231,12 +233,12 @@ protected: class IGBPDequeueBufferRequestParcel : public Parcel { public: - IGBPDequeueBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { + explicit IGBPDequeueBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { Deserialize(); } ~IGBPDequeueBufferRequestParcel() override = default; - void DeserializeData() { + void DeserializeData() override { std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -254,7 +256,7 @@ public: class IGBPDequeueBufferResponseParcel : public Parcel { public: - IGBPDequeueBufferResponseParcel(u32 slot) : Parcel(), slot(slot) {} + explicit IGBPDequeueBufferResponseParcel(u32 slot) : Parcel(), slot(slot) {} ~IGBPDequeueBufferResponseParcel() override = default; protected: @@ -271,12 +273,12 @@ protected: class IGBPRequestBufferRequestParcel : public Parcel { public: - IGBPRequestBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { + explicit IGBPRequestBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { Deserialize(); } ~IGBPRequestBufferRequestParcel() override = default; - void DeserializeData() { + void DeserializeData() override { std::u16string token = ReadInterfaceToken(); slot = Read<u32_le>(); } @@ -286,7 +288,7 @@ public: class IGBPRequestBufferResponseParcel : public Parcel { public: - IGBPRequestBufferResponseParcel(IGBPBuffer buffer) : Parcel(), buffer(buffer) {} + explicit IGBPRequestBufferResponseParcel(IGBPBuffer buffer) : Parcel(), buffer(buffer) {} ~IGBPRequestBufferResponseParcel() override = default; protected: @@ -307,12 +309,12 @@ protected: class IGBPQueueBufferRequestParcel : public Parcel { public: - IGBPQueueBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { + explicit IGBPQueueBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) { Deserialize(); } ~IGBPQueueBufferRequestParcel() override = default; - void DeserializeData() { + void DeserializeData() override { std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -330,7 +332,7 @@ public: class IGBPQueueBufferResponseParcel : public Parcel { public: - IGBPQueueBufferResponseParcel(u32 width, u32 height) : Parcel() { + explicit IGBPQueueBufferResponseParcel(u32 width, u32 height) : Parcel() { data.width = width; data.height = height; } @@ -356,7 +358,7 @@ private: class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { public: - IHOSBinderDriver(std::shared_ptr<NVFlinger> nv_flinger) + explicit IHOSBinderDriver(std::shared_ptr<NVFlinger> nv_flinger) : ServiceFramework("IHOSBinderDriver"), nv_flinger(std::move(nv_flinger)) { static const FunctionInfo functions[] = { {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, @@ -506,7 +508,7 @@ private: class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { public: - IManagerDisplayService(std::shared_ptr<NVFlinger> nv_flinger) + explicit IManagerDisplayService(std::shared_ptr<NVFlinger> nv_flinger) : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) { static const FunctionInfo functions[] = { {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp index 9ce8af961..bba4a0715 100644 --- a/src/core/hle/shared_page.cpp +++ b/src/core/hle/shared_page.cpp @@ -82,4 +82,4 @@ void Init() { CoreTiming::ScheduleEvent(0, update_time_event); } -} // namespace +} // namespace SharedPage diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h index 864695ae1..a58259888 100644 --- a/src/core/hle/shared_page.h +++ b/src/core/hle/shared_page.h @@ -66,4 +66,4 @@ extern SharedPageDef shared_page; void Init(); -} // namespace +} // namespace SharedPage |