From cb385e8241d6e3d5623e789f43ff7272d7af9637 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Thu, 11 May 2023 11:15:30 +0200 Subject: [PATCH] clean up old files --- src/common/cache_management.cpp | 59 - src/common/cache_management.h | 27 - src/common/common_headers.h | 12 - src/core/core_timing_util.h | 58 - src/core/hle/ipc_helpers.h | 505 -------- src/core/hle/kernel/hle_ipc.cpp | 531 -------- src/core/hle/kernel/hle_ipc.h | 421 ------ src/core/hle/kernel/k_linked_list.h | 238 ---- .../k_memory_layout.board.nintendo_nx.cpp | 201 --- src/core/hle/kernel/service_thread.cpp | 206 --- src/core/hle/kernel/service_thread.h | 29 - src/core/hle/kernel/svc_wrap.h | 733 ----------- src/core/hle/kernel/time_manager.cpp | 44 - src/core/hle/kernel/time_manager.h | 41 - src/core/hle/service/am/tcap.cpp | 22 - src/core/hle/service/am/tcap.h | 20 - src/core/hle/service/audio/auddbg.cpp | 21 - src/core/hle/service/audio/auddbg.h | 20 - src/core/hle/service/audio/audin_a.cpp | 23 - src/core/hle/service/audio/audin_a.h | 20 - src/core/hle/service/audio/audout_a.cpp | 25 - src/core/hle/service/audio/audout_a.h | 20 - src/core/hle/service/audio/audren_a.cpp | 27 - src/core/hle/service/audio/audren_a.h | 20 - src/core/hle/service/audio/codecctl.cpp | 29 - src/core/hle/service/audio/codecctl.h | 20 - src/core/hle/service/friend/errors.h | 11 - src/core/hle/service/nfc/mifare_user.cpp | 400 ------ src/core/hle/service/nfc/mifare_user.h | 52 - src/core/hle/service/nfc/nfc_device.cpp | 288 ----- src/core/hle/service/nfc/nfc_device.h | 78 -- src/core/hle/service/nfc/nfc_user.cpp | 365 ------ src/core/hle/service/nfc/nfc_user.h | 52 - src/core/hle/service/nfp/amiibo_crypto.cpp | 405 ------ src/core/hle/service/nfp/amiibo_crypto.h | 106 -- src/core/hle/service/nfp/nfp_device.cpp | 1137 ----------------- src/core/hle/service/nfp/nfp_device.h | 120 -- src/core/hle/service/nfp/nfp_user.cpp | 672 ---------- src/core/hle/service/nfp/nfp_user.h | 63 - src/core/hle/service/nvflinger/binder.h | 43 - src/core/hle/service/nvflinger/buffer_item.h | 46 - .../nvflinger/buffer_item_consumer.cpp | 59 - .../service/nvflinger/buffer_item_consumer.h | 28 - .../nvflinger/buffer_queue_consumer.cpp | 213 --- .../service/nvflinger/buffer_queue_consumer.h | 43 - .../service/nvflinger/buffer_queue_core.cpp | 115 -- .../hle/service/nvflinger/buffer_queue_core.h | 80 -- .../hle/service/nvflinger/buffer_queue_defs.h | 21 - .../nvflinger/buffer_queue_producer.cpp | 933 -------------- .../service/nvflinger/buffer_queue_producer.h | 90 -- src/core/hle/service/nvflinger/buffer_slot.h | 38 - .../nvflinger/buffer_transform_flags.h | 25 - .../hle/service/nvflinger/consumer_base.cpp | 133 -- .../hle/service/nvflinger/consumer_base.h | 60 - .../hle/service/nvflinger/consumer_listener.h | 26 - .../nvflinger/graphic_buffer_producer.cpp | 18 - .../nvflinger/graphic_buffer_producer.h | 76 -- .../nvflinger/hos_binder_driver_server.cpp | 36 - .../nvflinger/hos_binder_driver_server.h | 37 - src/core/hle/service/nvflinger/nvflinger.cpp | 335 ----- src/core/hle/service/nvflinger/nvflinger.h | 155 --- src/core/hle/service/nvflinger/parcel.h | 177 --- src/core/hle/service/nvflinger/pixel_format.h | 21 - .../hle/service/nvflinger/producer_listener.h | 17 - src/core/hle/service/nvflinger/status.h | 28 - src/core/hle/service/nvflinger/ui/fence.h | 32 - .../hle/service/nvflinger/ui/graphic_buffer.h | 100 -- src/core/hle/service/nvflinger/window.h | 53 - src/core/hle/service/sockets/ethc.cpp | 42 - src/core/hle/service/sockets/ethc.h | 26 - src/core/hle/service/wlan/wlan.cpp | 186 --- src/core/hle/service/wlan/wlan.h | 18 - src/tests/tests.cpp | 8 - src/tests/video_core/buffer_base.cpp | 549 -------- .../host_shaders/vulkan_blit_color_float.frag | 13 - 75 files changed, 11001 deletions(-) delete mode 100755 src/common/cache_management.cpp delete mode 100755 src/common/cache_management.h delete mode 100755 src/common/common_headers.h delete mode 100755 src/core/core_timing_util.h delete mode 100755 src/core/hle/ipc_helpers.h delete mode 100755 src/core/hle/kernel/hle_ipc.cpp delete mode 100755 src/core/hle/kernel/hle_ipc.h delete mode 100755 src/core/hle/kernel/k_linked_list.h delete mode 100755 src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp delete mode 100755 src/core/hle/kernel/service_thread.cpp delete mode 100755 src/core/hle/kernel/service_thread.h delete mode 100755 src/core/hle/kernel/svc_wrap.h delete mode 100755 src/core/hle/kernel/time_manager.cpp delete mode 100755 src/core/hle/kernel/time_manager.h delete mode 100755 src/core/hle/service/am/tcap.cpp delete mode 100755 src/core/hle/service/am/tcap.h delete mode 100755 src/core/hle/service/audio/auddbg.cpp delete mode 100755 src/core/hle/service/audio/auddbg.h delete mode 100755 src/core/hle/service/audio/audin_a.cpp delete mode 100755 src/core/hle/service/audio/audin_a.h delete mode 100755 src/core/hle/service/audio/audout_a.cpp delete mode 100755 src/core/hle/service/audio/audout_a.h delete mode 100755 src/core/hle/service/audio/audren_a.cpp delete mode 100755 src/core/hle/service/audio/audren_a.h delete mode 100755 src/core/hle/service/audio/codecctl.cpp delete mode 100755 src/core/hle/service/audio/codecctl.h delete mode 100755 src/core/hle/service/friend/errors.h delete mode 100755 src/core/hle/service/nfc/mifare_user.cpp delete mode 100755 src/core/hle/service/nfc/mifare_user.h delete mode 100755 src/core/hle/service/nfc/nfc_device.cpp delete mode 100755 src/core/hle/service/nfc/nfc_device.h delete mode 100755 src/core/hle/service/nfc/nfc_user.cpp delete mode 100755 src/core/hle/service/nfc/nfc_user.h delete mode 100755 src/core/hle/service/nfp/amiibo_crypto.cpp delete mode 100755 src/core/hle/service/nfp/amiibo_crypto.h delete mode 100755 src/core/hle/service/nfp/nfp_device.cpp delete mode 100755 src/core/hle/service/nfp/nfp_device.h delete mode 100755 src/core/hle/service/nfp/nfp_user.cpp delete mode 100755 src/core/hle/service/nfp/nfp_user.h delete mode 100755 src/core/hle/service/nvflinger/binder.h delete mode 100755 src/core/hle/service/nvflinger/buffer_item.h delete mode 100755 src/core/hle/service/nvflinger/buffer_item_consumer.cpp delete mode 100755 src/core/hle/service/nvflinger/buffer_item_consumer.h delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_consumer.cpp delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_consumer.h delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_core.cpp delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_core.h delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_defs.h delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_producer.cpp delete mode 100755 src/core/hle/service/nvflinger/buffer_queue_producer.h delete mode 100755 src/core/hle/service/nvflinger/buffer_slot.h delete mode 100755 src/core/hle/service/nvflinger/buffer_transform_flags.h delete mode 100755 src/core/hle/service/nvflinger/consumer_base.cpp delete mode 100755 src/core/hle/service/nvflinger/consumer_base.h delete mode 100755 src/core/hle/service/nvflinger/consumer_listener.h delete mode 100755 src/core/hle/service/nvflinger/graphic_buffer_producer.cpp delete mode 100755 src/core/hle/service/nvflinger/graphic_buffer_producer.h delete mode 100755 src/core/hle/service/nvflinger/hos_binder_driver_server.cpp delete mode 100755 src/core/hle/service/nvflinger/hos_binder_driver_server.h delete mode 100755 src/core/hle/service/nvflinger/nvflinger.cpp delete mode 100755 src/core/hle/service/nvflinger/nvflinger.h delete mode 100755 src/core/hle/service/nvflinger/parcel.h delete mode 100755 src/core/hle/service/nvflinger/pixel_format.h delete mode 100755 src/core/hle/service/nvflinger/producer_listener.h delete mode 100755 src/core/hle/service/nvflinger/status.h delete mode 100755 src/core/hle/service/nvflinger/ui/fence.h delete mode 100755 src/core/hle/service/nvflinger/ui/graphic_buffer.h delete mode 100755 src/core/hle/service/nvflinger/window.h delete mode 100755 src/core/hle/service/sockets/ethc.cpp delete mode 100755 src/core/hle/service/sockets/ethc.h delete mode 100755 src/core/hle/service/wlan/wlan.cpp delete mode 100755 src/core/hle/service/wlan/wlan.h delete mode 100755 src/tests/tests.cpp delete mode 100755 src/tests/video_core/buffer_base.cpp delete mode 100755 src/video_core/host_shaders/vulkan_blit_color_float.frag diff --git a/src/common/cache_management.cpp b/src/common/cache_management.cpp deleted file mode 100755 index ed353828a..000000000 --- a/src/common/cache_management.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include - -#include "common/cache_management.h" - -namespace Common { - -#if defined(ARCHITECTURE_x86_64) - -// Most cache operations are no-ops on x86 - -void DataCacheLineCleanByVAToPoU(void* start, size_t size) {} -void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size) {} -void DataCacheLineCleanByVAToPoC(void* start, size_t size) {} -void DataCacheZeroByVA(void* start, size_t size) { - std::memset(start, 0, size); -} - -#elif defined(ARCHITECTURE_arm64) - -// BS/DminLine is log2(cache size in words), we want size in bytes -#define EXTRACT_DMINLINE(ctr_el0) (1 << ((((ctr_el0) >> 16) & 0xf) + 2)) -#define EXTRACT_BS(dczid_el0) (1 << (((dczid_el0)&0xf) + 2)) - -#define DEFINE_DC_OP(op_name, function_name) \ - void function_name(void* start, size_t size) { \ - size_t ctr_el0; \ - asm volatile("mrs %[ctr_el0], ctr_el0\n\t" : [ctr_el0] "=r"(ctr_el0)); \ - size_t cacheline_size = EXTRACT_DMINLINE(ctr_el0); \ - uintptr_t va_start = reinterpret_cast(start); \ - uintptr_t va_end = va_start + size; \ - for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \ - asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \ - } \ - } - -#define DEFINE_DC_OP_DCZID(op_name, function_name) \ - void function_name(void* start, size_t size) { \ - size_t dczid_el0; \ - asm volatile("mrs %[dczid_el0], dczid_el0\n\t" : [dczid_el0] "=r"(dczid_el0)); \ - size_t cacheline_size = EXTRACT_BS(dczid_el0); \ - uintptr_t va_start = reinterpret_cast(start); \ - uintptr_t va_end = va_start + size; \ - for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \ - asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \ - } \ - } - -DEFINE_DC_OP(cvau, DataCacheLineCleanByVAToPoU); -DEFINE_DC_OP(civac, DataCacheLineCleanAndInvalidateByVAToPoC); -DEFINE_DC_OP(cvac, DataCacheLineCleanByVAToPoC); -DEFINE_DC_OP_DCZID(zva, DataCacheZeroByVA); - -#endif - -} // namespace Common diff --git a/src/common/cache_management.h b/src/common/cache_management.h deleted file mode 100755 index 038323e95..000000000 --- a/src/common/cache_management.h +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -namespace Common { - -// Data cache instructions enabled at EL0 by SCTLR_EL1.UCI. -// VA = virtual address -// PoC = point of coherency -// PoU = point of unification - -// dc cvau -void DataCacheLineCleanByVAToPoU(void* start, size_t size); - -// dc civac -void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size); - -// dc cvac -void DataCacheLineCleanByVAToPoC(void* start, size_t size); - -// dc zva -void DataCacheZeroByVA(void* start, size_t size); - -} // namespace Common diff --git a/src/common/common_headers.h b/src/common/common_headers.h deleted file mode 100755 index 5f81bef98..000000000 --- a/src/common/common_headers.h +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include - -#include - -#include "common/assert.h" diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h deleted file mode 100755 index 9c01fe0d1..000000000 --- a/src/core/core_timing_util.h +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "common/common_types.h" -#include "core/hardware_properties.h" - -namespace Core::Timing { - -namespace detail { -constexpr u64 CNTFREQ_ADJUSTED = Hardware::CNTFREQ / 1000; -constexpr u64 BASE_CLOCK_RATE_ADJUSTED = Hardware::BASE_CLOCK_RATE / 1000; -} // namespace detail - -[[nodiscard]] constexpr s64 msToCycles(std::chrono::milliseconds ms) { - return ms.count() * detail::BASE_CLOCK_RATE_ADJUSTED; -} - -[[nodiscard]] constexpr s64 usToCycles(std::chrono::microseconds us) { - return us.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000; -} - -[[nodiscard]] constexpr s64 nsToCycles(std::chrono::nanoseconds ns) { - return ns.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000000; -} - -[[nodiscard]] constexpr u64 msToClockCycles(std::chrono::milliseconds ms) { - return static_cast(ms.count()) * detail::CNTFREQ_ADJUSTED; -} - -[[nodiscard]] constexpr u64 usToClockCycles(std::chrono::microseconds us) { - return us.count() * detail::CNTFREQ_ADJUSTED / 1000; -} - -[[nodiscard]] constexpr u64 nsToClockCycles(std::chrono::nanoseconds ns) { - return ns.count() * detail::CNTFREQ_ADJUSTED / 1000000; -} - -[[nodiscard]] constexpr u64 CpuCyclesToClockCycles(u64 ticks) { - return ticks * detail::CNTFREQ_ADJUSTED / detail::BASE_CLOCK_RATE_ADJUSTED; -} - -[[nodiscard]] constexpr std::chrono::milliseconds CyclesToMs(s64 cycles) { - return std::chrono::milliseconds(cycles / detail::BASE_CLOCK_RATE_ADJUSTED); -} - -[[nodiscard]] constexpr std::chrono::nanoseconds CyclesToNs(s64 cycles) { - return std::chrono::nanoseconds(cycles * 1000000 / detail::BASE_CLOCK_RATE_ADJUSTED); -} - -[[nodiscard]] constexpr std::chrono::microseconds CyclesToUs(s64 cycles) { - return std::chrono::microseconds(cycles * 1000 / detail::BASE_CLOCK_RATE_ADJUSTED); -} - -} // namespace Core::Timing diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h deleted file mode 100755 index 16fe60735..000000000 --- a/src/core/hle/ipc_helpers.h +++ /dev/null @@ -1,505 +0,0 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include -#include "common/assert.h" -#include "common/common_types.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_resource_limit.h" -#include "core/hle/kernel/k_session.h" -#include "core/hle/result.h" -#include "core/hle/service/server_manager.h" - -namespace IPC { - -constexpr Result ERR_REMOTE_PROCESS_DEAD{ErrorModule::HIPC, 301}; - -class RequestHelperBase { -protected: - Kernel::HLERequestContext* context = nullptr; - u32* cmdbuf; - u32 index = 0; - -public: - explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} - - explicit RequestHelperBase(Kernel::HLERequestContext& ctx) - : context(&ctx), cmdbuf(ctx.CommandBuffer()) {} - - void Skip(u32 size_in_words, bool set_to_null) { - if (set_to_null) { - memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); - } - index += size_in_words; - } - - /** - * Aligns the current position forward to a 16-byte boundary, padding with zeros. - */ - void AlignWithPadding() { - if (index & 3) { - Skip(static_cast(4 - (index & 3)), true); - } - } - - u32 GetCurrentOffset() const { - return index; - } - - void SetCurrentOffset(u32 offset) { - index = offset; - } -}; - -class ResponseBuilder : public RequestHelperBase { -public: - /// Flags used for customizing the behavior of ResponseBuilder - enum class Flags : u32 { - None = 0, - /// Uses move handles to move objects in the response, even when in a domain. This is - /// required when PushMoveObjects is used. - AlwaysMoveHandles = 1, - }; - - explicit ResponseBuilder(Kernel::HLERequestContext& ctx, u32 normal_params_size_, - u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0, - Flags flags = Flags::None) - : RequestHelperBase(ctx), normal_params_size(normal_params_size_), - num_handles_to_copy(num_handles_to_copy_), - num_objects_to_move(num_objects_to_move_), kernel{ctx.kernel} { - - memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); - - IPC::CommandHeader header{}; - - // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory - // padding. - u32 raw_data_size = ctx.write_size = - ctx.IsTipc() ? normal_params_size - 1 : normal_params_size; - u32 num_handles_to_move{}; - u32 num_domain_objects{}; - const bool always_move_handles{ - (static_cast(flags) & static_cast(Flags::AlwaysMoveHandles)) != 0}; - if (!ctx.GetManager()->IsDomain() || always_move_handles) { - num_handles_to_move = num_objects_to_move; - } else { - num_domain_objects = num_objects_to_move; - } - - if (ctx.GetManager()->IsDomain()) { - raw_data_size += - static_cast(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); - ctx.write_size += num_domain_objects; - } - - if (ctx.IsTipc()) { - header.type.Assign(ctx.GetCommandType()); - } else { - raw_data_size += static_cast(sizeof(IPC::DataPayloadHeader) / sizeof(u32) + 4 + - normal_params_size); - } - - header.data_size.Assign(raw_data_size); - if (num_handles_to_copy || num_handles_to_move) { - header.enable_handle_descriptor.Assign(1); - } - PushRaw(header); - - if (header.enable_handle_descriptor) { - IPC::HandleDescriptorHeader handle_descriptor_header{}; - handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy_); - handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); - PushRaw(handle_descriptor_header); - - ctx.handles_offset = index; - - Skip(num_handles_to_copy + num_handles_to_move, true); - } - - if (!ctx.IsTipc()) { - AlignWithPadding(); - - if (ctx.GetManager()->IsDomain() && ctx.HasDomainMessageHeader()) { - IPC::DomainMessageHeader domain_header{}; - domain_header.num_objects = num_domain_objects; - PushRaw(domain_header); - } - - IPC::DataPayloadHeader data_payload_header{}; - data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); - PushRaw(data_payload_header); - } - - data_payload_index = index; - - ctx.data_payload_offset = index; - ctx.write_size += index; - ctx.domain_offset = static_cast(index + raw_data_size / sizeof(u32)); - } - - template - void PushIpcInterface(std::shared_ptr iface) { - auto manager{context->GetManager()}; - - if (manager->IsDomain()) { - context->AddDomainObject(std::move(iface)); - } else { - kernel.ApplicationProcess()->GetResourceLimit()->Reserve( - Kernel::LimitableResource::SessionCountMax, 1); - - auto* session = Kernel::KSession::Create(kernel); - session->Initialize(nullptr, iface->GetServiceName()); - - auto next_manager = std::make_shared( - kernel, manager->GetServerManager()); - next_manager->SetSessionHandler(iface); - manager->GetServerManager().RegisterSession(&session->GetServerSession(), next_manager); - - context->AddMoveObject(&session->GetClientSession()); - } - } - - template - void PushIpcInterface(Args&&... args) { - PushIpcInterface(std::make_shared(std::forward(args)...)); - } - - void PushImpl(s8 value); - void PushImpl(s16 value); - void PushImpl(s32 value); - void PushImpl(s64 value); - void PushImpl(u8 value); - void PushImpl(u16 value); - void PushImpl(u32 value); - void PushImpl(u64 value); - void PushImpl(float value); - void PushImpl(double value); - void PushImpl(bool value); - void PushImpl(Result value); - - template - void Push(T value) { - return PushImpl(value); - } - - template - void Push(const First& first_value, const Other&... other_values); - - /** - * Helper function for pushing strongly-typed enumeration values. - * - * @tparam Enum The enumeration type to be pushed - * - * @param value The value to push. - * - * @note The underlying size of the enumeration type is the size of the - * data that gets pushed. e.g. "enum class SomeEnum : u16" will - * push a u16-sized amount of data. - */ - template - void PushEnum(Enum value) { - static_assert(std::is_enum_v, "T must be an enum type within a PushEnum call."); - static_assert(!std::is_convertible_v, - "enum type in PushEnum must be a strongly typed enum."); - Push(static_cast>(value)); - } - - /** - * @brief Copies the content of the given trivially copyable class to the buffer as a normal - * param - * @note: The input class must be correctly packed/padded to fit hardware layout. - */ - template - void PushRaw(const T& value); - - template - void PushMoveObjects(O*... pointers); - - template - void PushMoveObjects(O&... pointers); - - template - void PushCopyObjects(O*... pointers); - - template - void PushCopyObjects(O&... pointers); - -private: - u32 normal_params_size{}; - u32 num_handles_to_copy{}; - u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent - u32 data_payload_index{}; - Kernel::KernelCore& kernel; -}; - -/// Push /// - -inline void ResponseBuilder::PushImpl(s32 value) { - cmdbuf[index++] = value; -} - -inline void ResponseBuilder::PushImpl(u32 value) { - cmdbuf[index++] = value; -} - -template -void ResponseBuilder::PushRaw(const T& value) { - static_assert(std::is_trivially_copyable_v, - "It's undefined behavior to use memcpy with non-trivially copyable objects"); - std::memcpy(cmdbuf + index, &value, sizeof(T)); - index += (sizeof(T) + 3) / 4; // round up to word length -} - -inline void ResponseBuilder::PushImpl(Result value) { - // Result codes are actually 64-bit in the IPC buffer, but only the high part is discarded. - Push(value.raw); - Push(0); -} - -inline void ResponseBuilder::PushImpl(s8 value) { - PushRaw(value); -} - -inline void ResponseBuilder::PushImpl(s16 value) { - PushRaw(value); -} - -inline void ResponseBuilder::PushImpl(s64 value) { - PushImpl(static_cast(value)); - PushImpl(static_cast(value >> 32)); -} - -inline void ResponseBuilder::PushImpl(u8 value) { - PushRaw(value); -} - -inline void ResponseBuilder::PushImpl(u16 value) { - PushRaw(value); -} - -inline void ResponseBuilder::PushImpl(u64 value) { - PushImpl(static_cast(value)); - PushImpl(static_cast(value >> 32)); -} - -inline void ResponseBuilder::PushImpl(float value) { - u32 integral; - std::memcpy(&integral, &value, sizeof(u32)); - PushImpl(integral); -} - -inline void ResponseBuilder::PushImpl(double value) { - u64 integral; - std::memcpy(&integral, &value, sizeof(u64)); - PushImpl(integral); -} - -inline void ResponseBuilder::PushImpl(bool value) { - PushImpl(static_cast(value)); -} - -template -void ResponseBuilder::Push(const First& first_value, const Other&... other_values) { - Push(first_value); - Push(other_values...); -} - -template -inline void ResponseBuilder::PushCopyObjects(O*... pointers) { - auto objects = {pointers...}; - for (auto& object : objects) { - context->AddCopyObject(object); - } -} - -template -inline void ResponseBuilder::PushCopyObjects(O&... pointers) { - auto objects = {&pointers...}; - for (auto& object : objects) { - context->AddCopyObject(object); - } -} - -template -inline void ResponseBuilder::PushMoveObjects(O*... pointers) { - auto objects = {pointers...}; - for (auto& object : objects) { - context->AddMoveObject(object); - } -} - -template -inline void ResponseBuilder::PushMoveObjects(O&... pointers) { - auto objects = {&pointers...}; - for (auto& object : objects) { - context->AddMoveObject(object); - } -} - -class RequestParser : public RequestHelperBase { -public: - explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} - - explicit RequestParser(Kernel::HLERequestContext& ctx) : RequestHelperBase(ctx) { - // TIPC does not have data payload offset - if (!ctx.IsTipc()) { - ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete"); - Skip(ctx.GetDataPayloadOffset(), false); - } - - // Skip the u64 command id, it's already stored in the context - static constexpr u32 CommandIdSize = 2; - Skip(CommandIdSize, false); - } - - template - T Pop(); - - template - void Pop(T& value); - - template - void Pop(First& first_value, Other&... other_values); - - template - T PopEnum() { - static_assert(std::is_enum_v, "T must be an enum type within a PopEnum call."); - static_assert(!std::is_convertible_v, - "enum type in PopEnum must be a strongly typed enum."); - return static_cast(Pop>()); - } - - /** - * @brief Reads the next normal parameters as a struct, by copying it - * @note: The output class must be correctly packed/padded to fit hardware layout. - */ - 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(); - - template - std::weak_ptr PopIpcInterface() { - ASSERT(context->GetManager()->IsDomain()); - ASSERT(context->GetDomainMessageHeader().input_object_count > 0); - return context->GetDomainHandler(Pop() - 1); - } -}; - -/// Pop /// - -template <> -inline u32 RequestParser::Pop() { - return cmdbuf[index++]; -} - -template <> -inline s32 RequestParser::Pop() { - return static_cast(Pop()); -} - -// Ignore the -Wclass-memaccess warning on memcpy for non-trivially default constructible objects. -#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif -template -void RequestParser::PopRaw(T& value) { - static_assert(std::is_trivially_copyable_v, - "It's undefined behavior to use memcpy with non-trivially copyable objects"); - std::memcpy(&value, cmdbuf + index, sizeof(T)); - index += (sizeof(T) + 3) / 4; // round up to word length -} -#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) -#pragma GCC diagnostic pop -#endif - -template -T RequestParser::PopRaw() { - T value; - PopRaw(value); - return value; -} - -template <> -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 s8 RequestParser::Pop() { - return static_cast(Pop()); -} - -template <> -inline s16 RequestParser::Pop() { - return static_cast(Pop()); -} - -template <> -inline s64 RequestParser::Pop() { - return static_cast(Pop()); -} - -template <> -inline float RequestParser::Pop() { - const u32 value = Pop(); - float real; - std::memcpy(&real, &value, sizeof(real)); - return real; -} - -template <> -inline double RequestParser::Pop() { - const u64 value = Pop(); - double real; - std::memcpy(&real, &value, sizeof(real)); - return real; -} - -template <> -inline bool RequestParser::Pop() { - return Pop() != 0; -} - -template <> -inline Result RequestParser::Pop() { - return Result{Pop()}; -} - -template -void RequestParser::Pop(T& value) { - value = Pop(); -} - -template -void RequestParser::Pop(First& first_value, Other&... other_values) { - first_value = Pop(); - Pop(other_values...); -} - -} // namespace IPC diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp deleted file mode 100755 index 1c796a864..000000000 --- a/src/core/hle/kernel/hle_ipc.cpp +++ /dev/null @@ -1,531 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include - -#include - -#include "common/assert.h" -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/scratch_buffer.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/k_auto_object.h" -#include "core/hle/kernel/k_handle_table.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_server_port.h" -#include "core/hle/kernel/k_server_session.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/kernel.h" -#include "core/memory.h" - -namespace Kernel { - -SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_) - : kernel{kernel_} {} - -SessionRequestHandler::~SessionRequestHandler() = default; - -SessionRequestManager::SessionRequestManager(KernelCore& kernel_, - Service::ServerManager& server_manager_) - : kernel{kernel_}, server_manager{server_manager_} {} - -SessionRequestManager::~SessionRequestManager() = default; - -bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& context) const { - if (IsDomain() && context.HasDomainMessageHeader()) { - const auto& message_header = context.GetDomainMessageHeader(); - const auto object_id = message_header.object_id; - - if (object_id > DomainHandlerCount()) { - LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); - return false; - } - return !DomainHandler(object_id - 1).expired(); - } else { - return session_handler != nullptr; - } -} - -Result SessionRequestManager::CompleteSyncRequest(KServerSession* server_session, - HLERequestContext& context) { - Result result = ResultSuccess; - - // If the session has been converted to a domain, handle the domain request - if (this->HasSessionRequestHandler(context)) { - if (IsDomain() && context.HasDomainMessageHeader()) { - result = HandleDomainSyncRequest(server_session, context); - // If there is no domain header, the regular session handler is used - } else if (this->HasSessionHandler()) { - // If this manager has an associated HLE handler, forward the request to it. - result = this->SessionHandler().HandleSyncRequest(*server_session, context); - } - } else { - ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); - IPC::ResponseBuilder rb(context, 2); - rb.Push(ResultSuccess); - } - - if (convert_to_domain) { - ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); - this->ConvertToDomain(); - convert_to_domain = false; - } - - return result; -} - -Result SessionRequestManager::HandleDomainSyncRequest(KServerSession* server_session, - HLERequestContext& context) { - if (!context.HasDomainMessageHeader()) { - return ResultSuccess; - } - - // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs - ASSERT(context.GetManager().get() == this); - - // If there is a DomainMessageHeader, then this is CommandType "Request" - const auto& domain_message_header = context.GetDomainMessageHeader(); - const u32 object_id{domain_message_header.object_id}; - switch (domain_message_header.command) { - case IPC::DomainMessageHeader::CommandType::SendMessage: - if (object_id > this->DomainHandlerCount()) { - LOG_CRITICAL(IPC, - "object_id {} is too big! This probably means a recent service call " - "needed to return a new interface!", - object_id); - ASSERT(false); - return ResultSuccess; // Ignore error if asserts are off - } - if (auto strong_ptr = this->DomainHandler(object_id - 1).lock()) { - return strong_ptr->HandleSyncRequest(*server_session, context); - } else { - ASSERT(false); - return ResultSuccess; - } - - case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { - LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); - - this->CloseDomainHandler(object_id - 1); - - IPC::ResponseBuilder rb{context, 2}; - rb.Push(ResultSuccess); - return ResultSuccess; - } - } - - LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); - ASSERT(false); - return ResultSuccess; -} - -HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, - KServerSession* server_session_, KThread* thread_) - : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { - cmd_buf[0] = 0; -} - -HLERequestContext::~HLERequestContext() = default; - -void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf, - bool incoming) { - IPC::RequestParser rp(src_cmdbuf); - command_header = rp.PopRaw(); - - if (command_header->IsCloseCommand()) { - // Close does not populate the rest of the IPC header - return; - } - - // If handle descriptor is present, add size of it - if (command_header->enable_handle_descriptor) { - handle_descriptor_header = rp.PopRaw(); - if (handle_descriptor_header->send_current_pid) { - pid = rp.Pop(); - } - if (incoming) { - // Populate the object lists with the data in the IPC request. - incoming_copy_handles.reserve(handle_descriptor_header->num_handles_to_copy); - incoming_move_handles.reserve(handle_descriptor_header->num_handles_to_move); - - for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { - incoming_copy_handles.push_back(rp.Pop()); - } - for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { - incoming_move_handles.push_back(rp.Pop()); - } - } else { - // For responses we just ignore the handles, they're empty and will be populated when - // translating the response. - rp.Skip(handle_descriptor_header->num_handles_to_copy, false); - rp.Skip(handle_descriptor_header->num_handles_to_move, false); - } - } - - buffer_x_desciptors.reserve(command_header->num_buf_x_descriptors); - buffer_a_desciptors.reserve(command_header->num_buf_a_descriptors); - buffer_b_desciptors.reserve(command_header->num_buf_b_descriptors); - buffer_w_desciptors.reserve(command_header->num_buf_w_descriptors); - - for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { - buffer_x_desciptors.push_back(rp.PopRaw()); - } - for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { - buffer_a_desciptors.push_back(rp.PopRaw()); - } - for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { - buffer_b_desciptors.push_back(rp.PopRaw()); - } - for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { - buffer_w_desciptors.push_back(rp.PopRaw()); - } - - const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; - - if (!command_header->IsTipc()) { - // Padding to align to 16 bytes - rp.AlignWithPadding(); - - if (GetManager()->IsDomain() && - ((command_header->type == IPC::CommandType::Request || - command_header->type == IPC::CommandType::RequestWithContext) || - !incoming)) { - // If this is an incoming message, only CommandType "Request" has a domain header - // All outgoing domain messages have the domain header, if only incoming has it - if (incoming || domain_message_header) { - domain_message_header = rp.PopRaw(); - } else { - if (GetManager()->IsDomain()) { - LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); - } - } - } - - data_payload_header = rp.PopRaw(); - - data_payload_offset = rp.GetCurrentOffset(); - - if (domain_message_header && - domain_message_header->command == - IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { - // CloseVirtualHandle command does not have SFC* or any data - return; - } - - if (incoming) { - ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); - } else { - 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()); - } else { - u32 num_buf_c_descriptors = - static_cast(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 (u32 i = 0; i < num_buf_c_descriptors; ++i) { - buffer_c_desciptors.push_back(rp.PopRaw()); - } - } - } - - rp.SetCurrentOffset(data_payload_offset); - - command = rp.Pop(); - rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. -} - -Result HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, - u32_le* src_cmdbuf) { - ParseCommandBuffer(handle_table, src_cmdbuf, true); - - if (command_header->IsCloseCommand()) { - // Close does not populate the rest of the IPC header - return ResultSuccess; - } - - std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin()); - - return ResultSuccess; -} - -Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { - auto current_offset = handles_offset; - auto& owner_process = *requesting_thread.GetOwnerProcess(); - auto& handle_table = owner_process.GetHandleTable(); - - for (auto& object : outgoing_copy_objects) { - Handle handle{}; - if (object) { - R_TRY(handle_table.Add(&handle, object)); - } - cmd_buf[current_offset++] = handle; - } - for (auto& object : outgoing_move_objects) { - Handle handle{}; - if (object) { - R_TRY(handle_table.Add(&handle, object)); - - // Close our reference to the object, as it is being moved to the caller. - object->Close(); - } - cmd_buf[current_offset++] = handle; - } - - // Write the domain objects to the command buffer, these go after the raw untranslated data. - // TODO(Subv): This completely ignores C buffers. - - if (GetManager()->IsDomain()) { - current_offset = domain_offset - static_cast(outgoing_domain_objects.size()); - for (auto& object : outgoing_domain_objects) { - GetManager()->AppendDomainHandler(std::move(object)); - cmd_buf[current_offset++] = static_cast(GetManager()->DomainHandlerCount()); - } - } - - // Copy the translated command buffer back into the thread's command buffer area. - memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), - write_size * sizeof(u32)); - - return ResultSuccess; -} - -std::vector HLERequestContext::ReadBufferCopy(std::size_t buffer_index) const { - const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && - BufferDescriptorA()[buffer_index].Size()}; - if (is_buffer_a) { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorA().size() > buffer_index, { return {}; }, - "BufferDescriptorA invalid buffer_index {}", buffer_index); - std::vector buffer(BufferDescriptorA()[buffer_index].Size()); - memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); - return buffer; - } else { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorX().size() > buffer_index, { return {}; }, - "BufferDescriptorX invalid buffer_index {}", buffer_index); - std::vector buffer(BufferDescriptorX()[buffer_index].Size()); - memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); - return buffer; - } -} - -std::span HLERequestContext::ReadBuffer(std::size_t buffer_index) const { - static thread_local std::array, 2> read_buffer_a; - static thread_local std::array, 2> read_buffer_x; - - const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && - BufferDescriptorA()[buffer_index].Size()}; - if (is_buffer_a) { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorA().size() > buffer_index, { return {}; }, - "BufferDescriptorA invalid buffer_index {}", buffer_index); - auto& read_buffer = read_buffer_a[buffer_index]; - read_buffer.resize_destructive(BufferDescriptorA()[buffer_index].Size()); - memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), read_buffer.data(), - read_buffer.size()); - return read_buffer; - } else { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorX().size() > buffer_index, { return {}; }, - "BufferDescriptorX invalid buffer_index {}", buffer_index); - auto& read_buffer = read_buffer_x[buffer_index]; - read_buffer.resize_destructive(BufferDescriptorX()[buffer_index].Size()); - memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), read_buffer.data(), - read_buffer.size()); - return read_buffer; - } -} - -std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, - std::size_t buffer_index) const { - if (size == 0) { - LOG_WARNING(Core, "skip empty buffer write"); - return 0; - } - - const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && - BufferDescriptorB()[buffer_index].Size()}; - const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; - if (size > buffer_size) { - LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, - buffer_size); - size = buffer_size; // TODO(bunnei): This needs to be HW tested - } - - if (is_buffer_b) { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorB().size() > buffer_index && - BufferDescriptorB()[buffer_index].Size() >= size, - { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size); - WriteBufferB(buffer, size, buffer_index); - } else { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorC().size() > buffer_index && - BufferDescriptorC()[buffer_index].Size() >= size, - { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size); - WriteBufferC(buffer, size, buffer_index); - } - - return size; -} - -std::size_t HLERequestContext::WriteBufferB(const void* buffer, std::size_t size, - std::size_t buffer_index) const { - if (buffer_index >= BufferDescriptorB().size() || size == 0) { - return 0; - } - - const auto buffer_size{BufferDescriptorB()[buffer_index].Size()}; - if (size > buffer_size) { - LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, - buffer_size); - size = buffer_size; // TODO(bunnei): This needs to be HW tested - } - - memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); - return size; -} - -std::size_t HLERequestContext::WriteBufferC(const void* buffer, std::size_t size, - std::size_t buffer_index) const { - if (buffer_index >= BufferDescriptorC().size() || size == 0) { - return 0; - } - - const auto buffer_size{BufferDescriptorC()[buffer_index].Size()}; - if (size > buffer_size) { - LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, - buffer_size); - size = buffer_size; // TODO(bunnei): This needs to be HW tested - } - - memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); - return size; -} - -std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const { - const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && - BufferDescriptorA()[buffer_index].Size()}; - if (is_buffer_a) { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorA().size() > buffer_index, { return 0; }, - "BufferDescriptorA invalid buffer_index {}", buffer_index); - return BufferDescriptorA()[buffer_index].Size(); - } else { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorX().size() > buffer_index, { return 0; }, - "BufferDescriptorX invalid buffer_index {}", buffer_index); - return BufferDescriptorX()[buffer_index].Size(); - } -} - -std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) const { - const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && - BufferDescriptorB()[buffer_index].Size()}; - if (is_buffer_b) { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorB().size() > buffer_index, { return 0; }, - "BufferDescriptorB invalid buffer_index {}", buffer_index); - return BufferDescriptorB()[buffer_index].Size(); - } else { - ASSERT_OR_EXECUTE_MSG( - BufferDescriptorC().size() > buffer_index, { return 0; }, - "BufferDescriptorC invalid buffer_index {}", buffer_index); - return BufferDescriptorC()[buffer_index].Size(); - } - return 0; -} - -bool HLERequestContext::CanReadBuffer(std::size_t buffer_index) const { - const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && - BufferDescriptorA()[buffer_index].Size()}; - - if (is_buffer_a) { - return BufferDescriptorA().size() > buffer_index; - } else { - return BufferDescriptorX().size() > buffer_index; - } -} - -bool HLERequestContext::CanWriteBuffer(std::size_t buffer_index) const { - const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && - BufferDescriptorB()[buffer_index].Size()}; - - if (is_buffer_b) { - return BufferDescriptorB().size() > buffer_index; - } else { - return BufferDescriptorC().size() > buffer_index; - } -} - -std::string HLERequestContext::Description() const { - if (!command_header) { - return "No command header available"; - } - std::ostringstream s; - s << "IPC::CommandHeader: Type:" << static_cast(command_header->type.Value()); - s << ", X(Pointer):" << command_header->num_buf_x_descriptors; - if (command_header->num_buf_x_descriptors) { - s << '['; - for (u64 i = 0; i < command_header->num_buf_x_descriptors; ++i) { - s << "0x" << std::hex << BufferDescriptorX()[i].Size(); - if (i < command_header->num_buf_x_descriptors - 1) - s << ", "; - } - s << ']'; - } - s << ", A(Send):" << command_header->num_buf_a_descriptors; - if (command_header->num_buf_a_descriptors) { - s << '['; - for (u64 i = 0; i < command_header->num_buf_a_descriptors; ++i) { - s << "0x" << std::hex << BufferDescriptorA()[i].Size(); - if (i < command_header->num_buf_a_descriptors - 1) - s << ", "; - } - s << ']'; - } - s << ", B(Receive):" << command_header->num_buf_b_descriptors; - if (command_header->num_buf_b_descriptors) { - s << '['; - for (u64 i = 0; i < command_header->num_buf_b_descriptors; ++i) { - s << "0x" << std::hex << BufferDescriptorB()[i].Size(); - if (i < command_header->num_buf_b_descriptors - 1) - s << ", "; - } - s << ']'; - } - s << ", C(ReceiveList):" << BufferDescriptorC().size(); - if (!BufferDescriptorC().empty()) { - s << '['; - for (u64 i = 0; i < BufferDescriptorC().size(); ++i) { - s << "0x" << std::hex << BufferDescriptorC()[i].Size(); - if (i < BufferDescriptorC().size() - 1) - s << ", "; - } - s << ']'; - } - s << ", data_size:" << command_header->data_size.Value(); - - return s.str(); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h deleted file mode 100755 index 632dacc83..000000000 --- a/src/core/hle/kernel/hle_ipc.h +++ /dev/null @@ -1,421 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/assert.h" -#include "common/common_types.h" -#include "common/concepts.h" -#include "common/swap.h" -#include "core/hle/ipc.h" -#include "core/hle/kernel/svc_common.h" - -union Result; - -namespace Core::Memory { -class Memory; -} - -namespace IPC { -class ResponseBuilder; -} - -namespace Service { -class ServiceFrameworkBase; -class ServerManager; -} // namespace Service - -namespace Kernel { - -class Domain; -class HLERequestContext; -class KAutoObject; -class KernelCore; -class KEvent; -class KHandleTable; -class KServerPort; -class KProcess; -class KServerSession; -class KThread; -class KReadableEvent; -class KSession; -class SessionRequestManager; - -/** - * Interface implemented by HLE Session handlers. - * This can be provided to a ServerSession in order to hook into several relevant events - * (such as a new connection or a SyncRequest) so they can be implemented in the emulator. - */ -class SessionRequestHandler : public std::enable_shared_from_this { -public: - SessionRequestHandler(KernelCore& kernel_, const char* service_name_); - virtual ~SessionRequestHandler(); - - /** - * Handles a sync request from the emulated application. - * @param server_session The ServerSession that was triggered for this sync request, - * it should be used to differentiate which client (As in ClientSession) we're answering to. - * TODO(Subv): Use a wrapper structure to hold all the information relevant to - * this request (ServerSession, Originator thread, Translated command buffer, etc). - * @returns Result the result code of the translate operation. - */ - virtual Result HandleSyncRequest(Kernel::KServerSession& session, - Kernel::HLERequestContext& context) = 0; - -protected: - KernelCore& kernel; -}; - -using SessionRequestHandlerWeakPtr = std::weak_ptr; -using SessionRequestHandlerPtr = std::shared_ptr; - -/** - * Manages the underlying HLE requests for a session, and whether (or not) the session should be - * treated as a domain. This is managed separately from server sessions, as this state is shared - * when objects are cloned. - */ -class SessionRequestManager final { -public: - explicit SessionRequestManager(KernelCore& kernel, Service::ServerManager& server_manager); - ~SessionRequestManager(); - - bool IsDomain() const { - return is_domain; - } - - void ConvertToDomain() { - domain_handlers = {session_handler}; - is_domain = true; - } - - void ConvertToDomainOnRequestEnd() { - convert_to_domain = true; - } - - std::size_t DomainHandlerCount() const { - return domain_handlers.size(); - } - - bool HasSessionHandler() const { - return session_handler != nullptr; - } - - SessionRequestHandler& SessionHandler() { - return *session_handler; - } - - const SessionRequestHandler& SessionHandler() const { - return *session_handler; - } - - void CloseDomainHandler(std::size_t index) { - if (index < DomainHandlerCount()) { - domain_handlers[index] = nullptr; - } else { - ASSERT_MSG(false, "Unexpected handler index {}", index); - } - } - - SessionRequestHandlerWeakPtr DomainHandler(std::size_t index) const { - ASSERT_MSG(index < DomainHandlerCount(), "Unexpected handler index {}", index); - return domain_handlers.at(index); - } - - void AppendDomainHandler(SessionRequestHandlerPtr&& handler) { - domain_handlers.emplace_back(std::move(handler)); - } - - void SetSessionHandler(SessionRequestHandlerPtr&& handler) { - session_handler = std::move(handler); - } - - bool HasSessionRequestHandler(const HLERequestContext& context) const; - - Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context); - Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context); - - Service::ServerManager& GetServerManager() { - return server_manager; - } - - // TODO: remove this when sm: is implemented with the proper IUserInterface - // abstraction, creating a new C++ handler object for each session: - - bool GetIsInitializedForSm() const { - return is_initialized_for_sm; - } - - void SetIsInitializedForSm() { - is_initialized_for_sm = true; - } - -private: - bool convert_to_domain{}; - bool is_domain{}; - bool is_initialized_for_sm{}; - SessionRequestHandlerPtr session_handler; - std::vector domain_handlers; - -private: - KernelCore& kernel; - Service::ServerManager& server_manager; -}; - -/** - * Class containing information about an in-flight IPC request being handled by an HLE service - * implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and - * when possible use the APIs in this class to service the request. - * - * HLE handle protocol - * =================== - * - * To avoid needing HLE services to keep a separate handle table, or having to directly modify the - * requester's table, a tweaked protocol is used to receive and send handles in requests. The kernel - * will decode the incoming handles into object pointers and insert a id in the buffer where the - * handle would normally be. The service then calls GetIncomingHandle() with that id to get the - * pointer to the object. Similarly, instead of inserting a handle into the command buffer, the - * service calls AddOutgoingHandle() and stores the returned id where the handle would normally go. - * - * The end result is similar to just giving services their own real handle tables, but since these - * ids are local to a specific context, it avoids requiring services to manage handles for objects - * across multiple calls and ensuring that unneeded handles are cleaned up. - */ -class HLERequestContext { -public: - explicit HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, - KServerSession* session, KThread* thread); - ~HLERequestContext(); - - /// Returns a pointer to the IPC command buffer for this request. - [[nodiscard]] u32* CommandBuffer() { - return cmd_buf.data(); - } - - /** - * Returns the session through which this request was made. This can be used as a map key to - * access per-client data on services. - */ - [[nodiscard]] Kernel::KServerSession* Session() { - return server_session; - } - - /// Populates this context with data from the requesting process/thread. - Result PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf); - - /// Writes data from this context back to the requesting process/thread. - Result WriteToOutgoingCommandBuffer(KThread& requesting_thread); - - [[nodiscard]] u32_le GetHipcCommand() const { - return command; - } - - [[nodiscard]] u32_le GetTipcCommand() const { - return static_cast(command_header->type.Value()) - - static_cast(IPC::CommandType::TIPC_CommandRegion); - } - - [[nodiscard]] u32_le GetCommand() const { - return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand(); - } - - [[nodiscard]] bool IsTipc() const { - return command_header->IsTipc(); - } - - [[nodiscard]] IPC::CommandType GetCommandType() const { - return command_header->type; - } - - [[nodiscard]] u64 GetPID() const { - return pid; - } - - [[nodiscard]] u32 GetDataPayloadOffset() const { - return data_payload_offset; - } - - [[nodiscard]] const std::vector& BufferDescriptorX() const { - return buffer_x_desciptors; - } - - [[nodiscard]] const std::vector& BufferDescriptorA() const { - return buffer_a_desciptors; - } - - [[nodiscard]] const std::vector& BufferDescriptorB() const { - return buffer_b_desciptors; - } - - [[nodiscard]] const std::vector& BufferDescriptorC() const { - return buffer_c_desciptors; - } - - [[nodiscard]] const IPC::DomainMessageHeader& GetDomainMessageHeader() const { - return domain_message_header.value(); - } - - [[nodiscard]] bool HasDomainMessageHeader() const { - return domain_message_header.has_value(); - } - - /// Helper function to get a span of a buffer using the appropriate buffer descriptor - [[nodiscard]] std::span ReadBuffer(std::size_t buffer_index = 0) const; - - /// Helper function to read a copy of a buffer using the appropriate buffer descriptor - [[nodiscard]] std::vector ReadBufferCopy(std::size_t buffer_index = 0) const; - - /// Helper function to write a buffer using the appropriate buffer descriptor - std::size_t WriteBuffer(const void* buffer, std::size_t size, - std::size_t buffer_index = 0) const; - - /// Helper function to write buffer B - std::size_t WriteBufferB(const void* buffer, std::size_t size, - std::size_t buffer_index = 0) const; - - /// Helper function to write buffer C - std::size_t WriteBufferC(const void* buffer, std::size_t size, - std::size_t buffer_index = 0) const; - - /* Helper function to write a buffer using the appropriate buffer descriptor - * - * @tparam T an arbitrary container that satisfies the - * ContiguousContainer concept in the C++ standard library or a trivially copyable type. - * - * @param data The container/data to write into a buffer. - * @param buffer_index The buffer in particular to write to. - */ - template >> - std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const { - if constexpr (Common::IsContiguousContainer) { - using ContiguousType = typename T::value_type; - static_assert(std::is_trivially_copyable_v, - "Container to WriteBuffer must contain trivially copyable objects"); - return WriteBuffer(std::data(data), std::size(data) * sizeof(ContiguousType), - buffer_index); - } else { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable"); - return WriteBuffer(&data, sizeof(T), buffer_index); - } - } - - /// Helper function to get the size of the input buffer - [[nodiscard]] std::size_t GetReadBufferSize(std::size_t buffer_index = 0) const; - - /// Helper function to get the size of the output buffer - [[nodiscard]] std::size_t GetWriteBufferSize(std::size_t buffer_index = 0) const; - - /// Helper function to derive the number of elements able to be contained in the read buffer - template - [[nodiscard]] std::size_t GetReadBufferNumElements(std::size_t buffer_index = 0) const { - return GetReadBufferSize(buffer_index) / sizeof(T); - } - - /// Helper function to derive the number of elements able to be contained in the write buffer - template - [[nodiscard]] std::size_t GetWriteBufferNumElements(std::size_t buffer_index = 0) const { - return GetWriteBufferSize(buffer_index) / sizeof(T); - } - - /// Helper function to test whether the input buffer at buffer_index can be read - [[nodiscard]] bool CanReadBuffer(std::size_t buffer_index = 0) const; - - /// Helper function to test whether the output buffer at buffer_index can be written - [[nodiscard]] bool CanWriteBuffer(std::size_t buffer_index = 0) const; - - [[nodiscard]] Handle GetCopyHandle(std::size_t index) const { - return incoming_copy_handles.at(index); - } - - [[nodiscard]] Handle GetMoveHandle(std::size_t index) const { - return incoming_move_handles.at(index); - } - - void AddMoveObject(KAutoObject* object) { - outgoing_move_objects.emplace_back(object); - } - - void AddCopyObject(KAutoObject* object) { - outgoing_copy_objects.emplace_back(object); - } - - void AddDomainObject(SessionRequestHandlerPtr object) { - outgoing_domain_objects.emplace_back(std::move(object)); - } - - template - std::shared_ptr GetDomainHandler(std::size_t index) const { - return std::static_pointer_cast(GetManager()->DomainHandler(index).lock()); - } - - void SetSessionRequestManager(std::weak_ptr manager_) { - manager = manager_; - } - - [[nodiscard]] std::string Description() const; - - [[nodiscard]] KThread& GetThread() { - return *thread; - } - - [[nodiscard]] std::shared_ptr GetManager() const { - return manager.lock(); - } - - bool GetIsDeferred() const { - return is_deferred; - } - - void SetIsDeferred(bool is_deferred_ = true) { - is_deferred = is_deferred_; - } - -private: - friend class IPC::ResponseBuilder; - - void ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf, bool incoming); - - std::array cmd_buf; - Kernel::KServerSession* server_session{}; - KThread* thread; - - std::vector incoming_move_handles; - std::vector incoming_copy_handles; - - std::vector outgoing_move_objects; - std::vector outgoing_copy_objects; - std::vector outgoing_domain_objects; - - std::optional command_header; - std::optional handle_descriptor_header; - std::optional data_payload_header; - std::optional domain_message_header; - std::vector buffer_x_desciptors; - std::vector buffer_a_desciptors; - std::vector buffer_b_desciptors; - std::vector buffer_w_desciptors; - std::vector buffer_c_desciptors; - - u32_le command{}; - u64 pid{}; - u32 write_size{}; - u32 data_payload_offset{}; - u32 handles_offset{}; - u32 domain_offset{}; - - std::weak_ptr manager{}; - bool is_deferred{false}; - - KernelCore& kernel; - Core::Memory::Memory& memory; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h deleted file mode 100755 index 9d54f45f1..000000000 --- a/src/core/hle/kernel/k_linked_list.h +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "common/assert.h" -#include "core/hle/kernel/slab_helpers.h" - -namespace Kernel { - -class KernelCore; - -class KLinkedListNode : public boost::intrusive::list_base_hook<>, - public KSlabAllocated { - -public: - explicit KLinkedListNode(KernelCore&) {} - KLinkedListNode() = default; - - void Initialize(void* it) { - m_item = it; - } - - void* GetItem() const { - return m_item; - } - -private: - void* m_item = nullptr; -}; - -template -class KLinkedList : private boost::intrusive::list { -private: - using BaseList = boost::intrusive::list; - -public: - template - class Iterator; - - using value_type = T; - using size_type = size_t; - using difference_type = ptrdiff_t; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using iterator = Iterator; - using const_iterator = Iterator; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - template - class Iterator { - private: - using BaseIterator = BaseList::iterator; - friend class KLinkedList; - - public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = typename KLinkedList::value_type; - using difference_type = typename KLinkedList::difference_type; - using pointer = std::conditional_t; - using reference = - std::conditional_t; - - public: - explicit Iterator(BaseIterator it) : m_base_it(it) {} - - pointer GetItem() const { - return static_cast(m_base_it->GetItem()); - } - - bool operator==(const Iterator& rhs) const { - return m_base_it == rhs.m_base_it; - } - - bool operator!=(const Iterator& rhs) const { - return !(*this == rhs); - } - - pointer operator->() const { - return this->GetItem(); - } - - reference operator*() const { - return *this->GetItem(); - } - - Iterator& operator++() { - ++m_base_it; - return *this; - } - - Iterator& operator--() { - --m_base_it; - return *this; - } - - Iterator operator++(int) { - const Iterator it{*this}; - ++(*this); - return it; - } - - Iterator operator--(int) { - const Iterator it{*this}; - --(*this); - return it; - } - - operator Iterator() const { - return Iterator(m_base_it); - } - - private: - BaseIterator m_base_it; - }; - -public: - constexpr KLinkedList(KernelCore& kernel_) : BaseList(), kernel{kernel_} {} - - ~KLinkedList() { - // Erase all elements. - for (auto it = begin(); it != end(); it = erase(it)) { - } - - // Ensure we succeeded. - ASSERT(this->empty()); - } - - // Iterator accessors. - iterator begin() { - return iterator(BaseList::begin()); - } - - const_iterator begin() const { - return const_iterator(BaseList::begin()); - } - - iterator end() { - return iterator(BaseList::end()); - } - - const_iterator end() const { - return const_iterator(BaseList::end()); - } - - const_iterator cbegin() const { - return this->begin(); - } - - const_iterator cend() const { - return this->end(); - } - - reverse_iterator rbegin() { - return reverse_iterator(this->end()); - } - - const_reverse_iterator rbegin() const { - return const_reverse_iterator(this->end()); - } - - reverse_iterator rend() { - return reverse_iterator(this->begin()); - } - - const_reverse_iterator rend() const { - return const_reverse_iterator(this->begin()); - } - - const_reverse_iterator crbegin() const { - return this->rbegin(); - } - - const_reverse_iterator crend() const { - return this->rend(); - } - - // Content management. - using BaseList::empty; - using BaseList::size; - - reference back() { - return *(--this->end()); - } - - const_reference back() const { - return *(--this->end()); - } - - reference front() { - return *this->begin(); - } - - const_reference front() const { - return *this->begin(); - } - - iterator insert(const_iterator pos, reference ref) { - KLinkedListNode* new_node = KLinkedListNode::Allocate(kernel); - ASSERT(new_node != nullptr); - new_node->Initialize(std::addressof(ref)); - return iterator(BaseList::insert(pos.m_base_it, *new_node)); - } - - void push_back(reference ref) { - this->insert(this->end(), ref); - } - - void push_front(reference ref) { - this->insert(this->begin(), ref); - } - - void pop_back() { - this->erase(--this->end()); - } - - void pop_front() { - this->erase(this->begin()); - } - - iterator erase(const iterator pos) { - KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); - iterator ret = iterator(BaseList::erase(pos.m_base_it)); - KLinkedListNode::Free(kernel, freed_node); - - return ret; - } - -private: - KernelCore& kernel; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp deleted file mode 100755 index eb9da0caa..000000000 --- a/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/alignment.h" -#include "common/literals.h" -#include "core/hle/kernel/k_memory_layout.h" -#include "core/hle/kernel/k_memory_manager.h" -#include "core/hle/kernel/k_system_control.h" -#include "core/hle/kernel/k_trace.h" - -namespace Kernel { - -namespace { - -using namespace Common::Literals; - -constexpr size_t CarveoutAlignment = 0x20000; -constexpr size_t CarveoutSizeMax = (512_MiB) - CarveoutAlignment; - -bool SetupPowerManagementControllerMemoryRegion(KMemoryLayout& memory_layout) { - // Above firmware 2.0.0, the PMC is not mappable. - return memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x7000E000, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap) && - memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x7000E400, 0xC00, - KMemoryRegionType_PowerManagementController | KMemoryRegionAttr_NoUserMap); -} - -void InsertPoolPartitionRegionIntoBothTrees(KMemoryLayout& memory_layout, size_t start, size_t size, - KMemoryRegionType phys_type, - KMemoryRegionType virt_type, u32& cur_attr) { - const u32 attr = cur_attr++; - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(start, size, - static_cast(phys_type), attr)); - const KMemoryRegion* phys = memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute( - static_cast(phys_type), attr); - ASSERT(phys != nullptr); - ASSERT(phys->GetEndAddress() != 0); - ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size, - static_cast(virt_type), attr)); -} - -} // namespace - -namespace Init { - -void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout) { - ASSERT(SetupPowerManagementControllerMemoryRegion(memory_layout)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x70019000, 0x1000, KMemoryRegionType_MemoryController | KMemoryRegionAttr_NoUserMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x7001C000, 0x1000, KMemoryRegionType_MemoryController0 | KMemoryRegionAttr_NoUserMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x7001D000, 0x1000, KMemoryRegionType_MemoryController1 | KMemoryRegionAttr_NoUserMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x50040000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x50041000, 0x1000, - KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x50042000, 0x1000, - KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); - - // Map IRAM unconditionally, to support debug-logging-to-iram build config. - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x40000000, 0x40000, KMemoryRegionType_LegacyLpsIram | KMemoryRegionAttr_ShouldKernelMap)); - - // Above firmware 2.0.0, prevent mapping the bpmp exception vectors or the ipatch region. - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - 0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); -} - -void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout) { - const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize(); - const PAddr physical_memory_base_address = - KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress); - - // Insert blocks into the tree. - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - physical_memory_base_address, intended_memory_size, KMemoryRegionType_Dram)); - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - physical_memory_base_address, ReservedEarlyDramSize, KMemoryRegionType_DramReservedEarly)); - - // Insert the KTrace block at the end of Dram, if KTrace is enabled. - static_assert(!IsKTraceEnabled || KTraceBufferSize > 0); - if constexpr (IsKTraceEnabled) { - const PAddr ktrace_buffer_phys_addr = - physical_memory_base_address + intended_memory_size - KTraceBufferSize; - ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert( - ktrace_buffer_phys_addr, KTraceBufferSize, KMemoryRegionType_KernelTraceBuffer)); - } -} - -void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout) { - // Start by identifying the extents of the DRAM memory region. - const auto dram_extents = memory_layout.GetMainMemoryPhysicalExtents(); - ASSERT(dram_extents.GetEndAddress() != 0); - - // Determine the end of the pool region. - const u64 pool_end = dram_extents.GetEndAddress() - KTraceBufferSize; - - // Find the start of the kernel DRAM region. - const KMemoryRegion* kernel_dram_region = - memory_layout.GetPhysicalMemoryRegionTree().FindFirstDerived( - KMemoryRegionType_DramKernelBase); - ASSERT(kernel_dram_region != nullptr); - - const u64 kernel_dram_start = kernel_dram_region->GetAddress(); - ASSERT(Common::IsAligned(kernel_dram_start, CarveoutAlignment)); - - // Find the start of the pool partitions region. - const KMemoryRegion* pool_partitions_region = - memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute( - KMemoryRegionType_DramPoolPartition, 0); - ASSERT(pool_partitions_region != nullptr); - const u64 pool_partitions_start = pool_partitions_region->GetAddress(); - - // Setup the pool partition layouts. - // On 5.0.0+, setup modern 4-pool-partition layout. - - // Get Application and Applet pool sizes. - const size_t application_pool_size = KSystemControl::Init::GetApplicationPoolSize(); - const size_t applet_pool_size = KSystemControl::Init::GetAppletPoolSize(); - const size_t unsafe_system_pool_min_size = - KSystemControl::Init::GetMinimumNonSecureSystemPoolSize(); - - // Decide on starting addresses for our pools. - const u64 application_pool_start = pool_end - application_pool_size; - const u64 applet_pool_start = application_pool_start - applet_pool_size; - const u64 unsafe_system_pool_start = std::min( - kernel_dram_start + CarveoutSizeMax, - Common::AlignDown(applet_pool_start - unsafe_system_pool_min_size, CarveoutAlignment)); - const size_t unsafe_system_pool_size = applet_pool_start - unsafe_system_pool_start; - - // We want to arrange application pool depending on where the middle of dram is. - const u64 dram_midpoint = (dram_extents.GetAddress() + dram_extents.GetEndAddress()) / 2; - u32 cur_pool_attr = 0; - size_t total_overhead_size = 0; - if (dram_extents.GetEndAddress() <= dram_midpoint || dram_midpoint <= application_pool_start) { - InsertPoolPartitionRegionIntoBothTrees( - memory_layout, application_pool_start, application_pool_size, - KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool, - cur_pool_attr); - total_overhead_size += - KMemoryManager::CalculateManagementOverheadSize(application_pool_size); - } else { - const size_t first_application_pool_size = dram_midpoint - application_pool_start; - const size_t second_application_pool_size = - application_pool_start + application_pool_size - dram_midpoint; - InsertPoolPartitionRegionIntoBothTrees( - memory_layout, application_pool_start, first_application_pool_size, - KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool, - cur_pool_attr); - InsertPoolPartitionRegionIntoBothTrees( - memory_layout, dram_midpoint, second_application_pool_size, - KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool, - cur_pool_attr); - total_overhead_size += - KMemoryManager::CalculateManagementOverheadSize(first_application_pool_size); - total_overhead_size += - KMemoryManager::CalculateManagementOverheadSize(second_application_pool_size); - } - - // Insert the applet pool. - InsertPoolPartitionRegionIntoBothTrees(memory_layout, applet_pool_start, applet_pool_size, - KMemoryRegionType_DramAppletPool, - KMemoryRegionType_VirtualDramAppletPool, cur_pool_attr); - total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(applet_pool_size); - - // Insert the nonsecure system pool. - InsertPoolPartitionRegionIntoBothTrees( - memory_layout, unsafe_system_pool_start, unsafe_system_pool_size, - KMemoryRegionType_DramSystemNonSecurePool, KMemoryRegionType_VirtualDramSystemNonSecurePool, - cur_pool_attr); - total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(unsafe_system_pool_size); - - // Insert the pool management region. - total_overhead_size += KMemoryManager::CalculateManagementOverheadSize( - (unsafe_system_pool_start - pool_partitions_start) - total_overhead_size); - const u64 pool_management_start = unsafe_system_pool_start - total_overhead_size; - const size_t pool_management_size = total_overhead_size; - u32 pool_management_attr = 0; - InsertPoolPartitionRegionIntoBothTrees( - memory_layout, pool_management_start, pool_management_size, - KMemoryRegionType_DramPoolManagement, KMemoryRegionType_VirtualDramPoolManagement, - pool_management_attr); - - // Insert the system pool. - const u64 system_pool_size = pool_management_start - pool_partitions_start; - InsertPoolPartitionRegionIntoBothTrees(memory_layout, pool_partitions_start, system_pool_size, - KMemoryRegionType_DramSystemPool, - KMemoryRegionType_VirtualDramSystemPool, cur_pool_attr); -} - -} // namespace Init - -} // namespace Kernel diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp deleted file mode 100755 index 5ed588bcc..000000000 --- a/src/core/hle/kernel/service_thread.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include - -#include "common/polyfill_thread.h" -#include "common/scope_exit.h" -#include "common/thread.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_scoped_resource_reservation.h" -#include "core/hle/kernel/k_session.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/service_thread.h" - -namespace Kernel { - -class ServiceThread::Impl final { -public: - explicit Impl(KernelCore& kernel, const std::string& service_name); - ~Impl(); - - void WaitAndProcessImpl(); - void SessionClosed(KServerSession* server_session, - std::shared_ptr manager); - void LoopProcess(); - - void RegisterServerSession(KServerSession* session, - std::shared_ptr manager); - -private: - KernelCore& kernel; - const std::string m_service_name; - - std::jthread m_host_thread{}; - std::mutex m_session_mutex{}; - std::map> m_sessions{}; - KEvent* m_wakeup_event{}; - KThread* m_thread{}; - std::atomic m_shutdown_requested{}; -}; - -void ServiceThread::Impl::WaitAndProcessImpl() { - // Create local list of waitable sessions. - std::vector objs; - std::vector> managers; - - { - // Lock to get the set. - std::scoped_lock lk{m_session_mutex}; - - // Reserve the needed quantity. - objs.reserve(m_sessions.size() + 1); - managers.reserve(m_sessions.size()); - - // Copy to our local list. - for (const auto& [session, manager] : m_sessions) { - objs.push_back(session); - managers.push_back(manager); - } - - // Insert the wakeup event at the end. - objs.push_back(&m_wakeup_event->GetReadableEvent()); - } - - // Wait on the list of sessions. - s32 index{-1}; - Result rc = KSynchronizationObject::Wait(kernel, &index, objs.data(), - static_cast(objs.size()), -1); - ASSERT(!rc.IsFailure()); - - // If this was the wakeup event, clear it and finish. - if (index >= static_cast(objs.size() - 1)) { - m_wakeup_event->Clear(); - return; - } - - // This event is from a server session. - auto* server_session = static_cast(objs[index]); - auto& manager = managers[index]; - - // Fetch the HLE request context. - std::shared_ptr context; - rc = server_session->ReceiveRequest(&context, manager); - - // If the session was closed, handle that. - if (rc == ResultSessionClosed) { - SessionClosed(server_session, manager); - - // Finish. - return; - } - - // TODO: handle other cases - ASSERT(rc == ResultSuccess); - - // Perform the request. - Result service_rc = manager->CompleteSyncRequest(server_session, *context); - - // Reply to the client. - rc = server_session->SendReplyHLE(); - - if (rc == ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) { - SessionClosed(server_session, manager); - return; - } - - // TODO: handle other cases - ASSERT(rc == ResultSuccess); - ASSERT(service_rc == ResultSuccess); -} - -void ServiceThread::Impl::SessionClosed(KServerSession* server_session, - std::shared_ptr manager) { - { - // Lock to get the set. - std::scoped_lock lk{m_session_mutex}; - - // Erase the session. - ASSERT(m_sessions.erase(server_session) == 1); - } - - // Close our reference to the server session. - server_session->Close(); -} - -void ServiceThread::Impl::LoopProcess() { - Common::SetCurrentThreadName(m_service_name.c_str()); - - kernel.RegisterHostThread(m_thread); - - while (!m_shutdown_requested.load()) { - WaitAndProcessImpl(); - } -} - -void ServiceThread::Impl::RegisterServerSession(KServerSession* server_session, - std::shared_ptr manager) { - // Open the server session. - server_session->Open(); - - { - // Lock to get the set. - std::scoped_lock lk{m_session_mutex}; - - // Insert the session and manager. - m_sessions[server_session] = manager; - } - - // Signal the wakeup event. - m_wakeup_event->Signal(); -} - -ServiceThread::Impl::~Impl() { - // Shut down the processing thread. - m_shutdown_requested.store(true); - m_wakeup_event->Signal(); - m_host_thread.join(); - - // Close all remaining sessions. - for (const auto& [server_session, manager] : m_sessions) { - server_session->Close(); - } - - // Destroy remaining managers. - m_sessions.clear(); - - // Close event. - m_wakeup_event->GetReadableEvent().Close(); - m_wakeup_event->Close(); - - // Close thread. - m_thread->Close(); -} - -ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) - : kernel{kernel_}, m_service_name{service_name} { - // Initialize event. - m_wakeup_event = KEvent::Create(kernel); - m_wakeup_event->Initialize(nullptr); - - // Initialize thread. - m_thread = KThread::Create(kernel); - ASSERT(KThread::InitializeDummyThread(m_thread, nullptr).IsSuccess()); - - // Start thread. - m_host_thread = std::jthread([this] { LoopProcess(); }); -} - -ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) - : impl{std::make_unique(kernel, name)} {} - -ServiceThread::~ServiceThread() = default; - -void ServiceThread::RegisterServerSession(KServerSession* session, - std::shared_ptr manager) { - impl->RegisterServerSession(session, manager); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h deleted file mode 100755 index 51f36c1b1..000000000 --- a/src/core/hle/kernel/service_thread.h +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -namespace Kernel { - -class HLERequestContext; -class KernelCore; -class KSession; -class SessionRequestManager; - -class ServiceThread final { -public: - explicit ServiceThread(KernelCore& kernel, const std::string& name); - ~ServiceThread(); - - void RegisterServerSession(KServerSession* session, - std::shared_ptr manager); - -private: - class Impl; - std::unique_ptr impl; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h deleted file mode 100755 index aaeab8c23..000000000 --- a/src/core/hle/kernel/svc_wrap.h +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/arm/arm_interface.h" -#include "core/core.h" -#include "core/hle/kernel/svc_types.h" -#include "core/hle/result.h" -#include "core/memory.h" - -namespace Kernel { - -static inline u64 Param(const Core::System& system, int n) { - return system.CurrentArmInterface().GetReg(n); -} - -static inline u32 Param32(const Core::System& system, int n) { - return static_cast(system.CurrentArmInterface().GetReg(n)); -} - -/** - * HLE a function return from the current ARM userland process - * @param system System context - * @param result Result to return - */ -static inline void FuncReturn(Core::System& system, u64 result) { - system.CurrentArmInterface().SetReg(0, result); -} - -static inline void FuncReturn32(Core::System& system, u32 result) { - system.CurrentArmInterface().SetReg(0, (u64)result); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Function wrappers that return type Result - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0)).raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0))).raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn( - system, - func(system, static_cast(Param(system, 0)), static_cast(Param(system, 1))).raw); -} - -// Used by SetThreadActivity -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1))) - .raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), Param(system, 1), - Param(system, 2), Param(system, 3)) - .raw); -} - -// Used by MapProcessMemory and UnmapProcessMemory -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), static_cast(Param(system, 1)), - Param(system, 2), Param(system, 3)) - .raw); -} - -// Used by ControlCodeMemory -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1)), Param(system, 2), Param(system, 3), - static_cast(Param(system, 4))) - .raw); -} - -template -void SvcWrap64(Core::System& system) { - u32 param = 0; - const u32 retval = func(system, ¶m).raw; - system.CurrentArmInterface().SetReg(1, param); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, static_cast(Param(system, 1))).raw; - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - u32 param_2 = 0; - const u32 retval = func(system, ¶m_1, ¶m_2).raw; - - auto& arm_interface = system.CurrentArmInterface(); - arm_interface.SetReg(1, param_1); - arm_interface.SetReg(2, param_2); - - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1)).raw; - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = - func(system, ¶m_1, Param(system, 1), static_cast(Param(system, 2))).raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u64 param_1 = 0; - const u32 retval = func(system, ¶m_1, static_cast(Param(system, 1))).raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), static_cast(Param(system, 1))).raw); -} - -template -void SvcWrap64(Core::System& system) { - u64 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1)).raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u64 param_1 = 0; - const u32 retval = func(system, ¶m_1, static_cast(Param(system, 1)), - static_cast(Param(system, 2))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by GetResourceLimitLimitValue. -template -void SvcWrap64(Core::System& system) { - u64 param_1 = 0; - const u32 retval = func(system, ¶m_1, static_cast(Param(system, 1)), - static_cast(Param(system, 2))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), Param(system, 1)).raw); -} - -// Used by SetResourceLimitLimitValue -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1)), Param(system, 2)) - .raw); -} - -// Used by SetThreadCoreMask -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1)), Param(system, 2)) - .raw); -} - -// Used by GetThreadCoreMask -template -void SvcWrap64(Core::System& system) { - s32 param_1 = 0; - u64 param_2 = 0; - const Result retval = func(system, static_cast(Param(system, 2)), ¶m_1, ¶m_2); - - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - FuncReturn(system, retval.raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), Param(system, 1), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), Param(system, 1), - static_cast(Param(system, 2)), Param(system, 3)) - .raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), Param(system, 1), - static_cast(Param(system, 2))) - .raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn( - system, - func(system, Param(system, 0), Param(system, 1), static_cast(Param(system, 2))).raw); -} - -// Used by SetMemoryPermission -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), Param(system, 1), - static_cast(Param(system, 2))) - .raw); -} - -// Used by MapSharedMemory -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0)), Param(system, 1), - Param(system, 2), static_cast(Param(system, 3))) - .raw); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn( - system, - func(system, static_cast(Param(system, 0)), Param(system, 1), Param(system, 2)).raw); -} - -// Used by WaitSynchronization -template -void SvcWrap64(Core::System& system) { - s32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast(Param(system, 2)), - static_cast(Param(system, 3))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, Param(system, 0), Param(system, 1), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw); -} - -// Used by GetInfo -template -void SvcWrap64(Core::System& system) { - u64 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1), - static_cast(Param(system, 2)), Param(system, 3)) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3), - static_cast(Param(system, 4)), static_cast(Param(system, 5))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by CreateTransferMemory -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), - static_cast(Param(system, 3))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by CreateCodeMemory -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2)).raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -template -void SvcWrap64(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast(Param(system, 2)), - static_cast(Param(system, 3))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by CreateSession -template -void SvcWrap64(Core::System& system) { - Handle param_1 = 0; - Handle param_2 = 0; - const u32 retval = func(system, ¶m_1, ¶m_2, static_cast(Param(system, 2)), - static_cast(Param(system, 3))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - FuncReturn(system, retval); -} - -// Used by ReplyAndReceive -template -void SvcWrap64(Core::System& system) { - s32 param_1 = 0; - s32 num_handles = static_cast(Param(system, 2)); - - std::vector handles(num_handles); - system.Memory().ReadBlock(Param(system, 1), handles.data(), num_handles * sizeof(Handle)); - - const u32 retval = func(system, ¶m_1, handles.data(), num_handles, - static_cast(Param(system, 3)), static_cast(Param(system, 4))) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by WaitForAddress -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, - func(system, Param(system, 0), static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw); -} - -// Used by SignalToAddress -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, - func(system, Param(system, 0), static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Function wrappers that return type u32 - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system)); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Function wrappers that return type u64 - -template -void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system)); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -/// Function wrappers that return type void - -template -void SvcWrap64(Core::System& system) { - func(system); -} - -template -void SvcWrap64(Core::System& system) { - func(system, static_cast(Param(system, 0))); -} - -template -void SvcWrap64(Core::System& system) { - func(system, static_cast(Param(system, 0)), Param(system, 1), Param(system, 2), - Param(system, 3)); -} - -template -void SvcWrap64(Core::System& system) { - func(system, static_cast(Param(system, 0))); -} - -template -void SvcWrap64(Core::System& system) { - func(system, Param(system, 0), static_cast(Param(system, 1))); -} - -template -void SvcWrap64(Core::System& system) { - func(system, Param(system, 0), Param(system, 1)); -} - -template -void SvcWrap64(Core::System& system) { - func(system, Param(system, 0), Param(system, 1), Param(system, 2)); -} - -template -void SvcWrap64(Core::System& system) { - func(system, static_cast(Param(system, 0)), Param(system, 1), Param(system, 2)); -} - -// Used by QueryMemory32, ArbitrateLock32 -template -void SvcWrap32(Core::System& system) { - FuncReturn32(system, - func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw); -} - -// Used by Break32 -template -void SvcWrap32(Core::System& system) { - func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)); -} - -// Used by ExitProcess32, ExitThread32 -template -void SvcWrap32(Core::System& system) { - func(system); -} - -// Used by GetCurrentProcessorNumber32 -template -void SvcWrap32(Core::System& system) { - FuncReturn32(system, func(system)); -} - -// Used by SleepThread32 -template -void SvcWrap32(Core::System& system) { - func(system, Param32(system, 0), Param32(system, 1)); -} - -// Used by CreateThread32 -template -void SvcWrap32(Core::System& system) { - Handle param_1 = 0; - - const u32 retval = func(system, ¶m_1, Param32(system, 0), Param32(system, 1), - Param32(system, 2), Param32(system, 3), Param32(system, 4)) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by GetInfo32 -template -void SvcWrap32(Core::System& system) { - u32 param_1 = 0; - u32 param_2 = 0; - - const u32 retval = func(system, ¶m_1, ¶m_2, Param32(system, 0), Param32(system, 1), - Param32(system, 2), Param32(system, 3)) - .raw; - - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - FuncReturn(system, retval); -} - -// Used by GetThreadPriority32, ConnectToNamedPort32 -template -void SvcWrap32(Core::System& system) { - u32 param_1 = 0; - const u32 retval = func(system, ¶m_1, Param32(system, 1)).raw; - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by GetThreadId32 -template -void SvcWrap32(Core::System& system) { - u32 param_1 = 0; - u32 param_2 = 0; - - const u32 retval = func(system, ¶m_1, ¶m_2, Param32(system, 1)).raw; - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - FuncReturn(system, retval); -} - -// Used by GetSystemTick32 -template -void SvcWrap32(Core::System& system) { - u32 param_1 = 0; - u32 param_2 = 0; - - func(system, ¶m_1, ¶m_2); - system.CurrentArmInterface().SetReg(0, param_1); - system.CurrentArmInterface().SetReg(1, param_2); -} - -// Used by CreateEvent32 -template -void SvcWrap32(Core::System& system) { - Handle param_1 = 0; - Handle param_2 = 0; - - const u32 retval = func(system, ¶m_1, ¶m_2).raw; - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - FuncReturn(system, retval); -} - -// Used by GetThreadId32 -template -void SvcWrap32(Core::System& system) { - u32 param_1 = 0; - u32 param_2 = 0; - u32 param_3 = 0; - - const u32 retval = func(system, Param32(system, 2), ¶m_1, ¶m_2, ¶m_3).raw; - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - system.CurrentArmInterface().SetReg(3, param_3); - FuncReturn(system, retval); -} - -// Used by GetThreadCoreMask32 -template -void SvcWrap32(Core::System& system) { - s32 param_1 = 0; - u32 param_2 = 0; - u32 param_3 = 0; - - const u32 retval = func(system, Param32(system, 2), ¶m_1, ¶m_2, ¶m_3).raw; - system.CurrentArmInterface().SetReg(1, param_1); - system.CurrentArmInterface().SetReg(2, param_2); - system.CurrentArmInterface().SetReg(3, param_3); - FuncReturn(system, retval); -} - -// Used by SignalProcessWideKey32 -template -void SvcWrap32(Core::System& system) { - func(system, static_cast(Param(system, 0)), static_cast(Param(system, 1))); -} - -// Used by SetThreadActivity32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1))) - .raw; - FuncReturn(system, retval); -} - -// Used by SetThreadPriority32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = - func(system, static_cast(Param(system, 0)), static_cast(Param(system, 1))).raw; - FuncReturn(system, retval); -} - -// Used by SetMemoryAttribute32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = - func(system, static_cast(Param(system, 0)), static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw; - FuncReturn(system, retval); -} - -// Used by MapSharedMemory32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1)), static_cast(Param(system, 2)), - static_cast(Param(system, 3))) - .raw; - FuncReturn(system, retval); -} - -// Used by SetThreadCoreMask32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = - func(system, static_cast(Param(system, 0)), static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw; - FuncReturn(system, retval); -} - -// Used by WaitProcessWideKeyAtomic32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = - func(system, static_cast(Param(system, 0)), static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3)), - static_cast(Param(system, 4))) - .raw; - FuncReturn(system, retval); -} - -// Used by WaitForAddress32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3)), - static_cast(Param(system, 4))) - .raw; - FuncReturn(system, retval); -} - -// Used by SignalToAddress32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = func(system, static_cast(Param(system, 0)), - static_cast(Param(system, 1)), - static_cast(Param(system, 2)), static_cast(Param(system, 3))) - .raw; - FuncReturn(system, retval); -} - -// Used by SendSyncRequest32, ArbitrateUnlock32 -template -void SvcWrap32(Core::System& system) { - FuncReturn(system, func(system, static_cast(Param(system, 0))).raw); -} - -// Used by CreateTransferMemory32 -template -void SvcWrap32(Core::System& system) { - Handle handle = 0; - const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2), - static_cast(Param32(system, 3))) - .raw; - system.CurrentArmInterface().SetReg(1, handle); - FuncReturn(system, retval); -} - -// Used by WaitSynchronization32 -template -void SvcWrap32(Core::System& system) { - s32 param_1 = 0; - const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2), - Param32(system, 3), ¶m_1) - .raw; - system.CurrentArmInterface().SetReg(1, param_1); - FuncReturn(system, retval); -} - -// Used by CreateCodeMemory32 -template -void SvcWrap32(Core::System& system) { - Handle handle = 0; - - const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2)).raw; - - system.CurrentArmInterface().SetReg(1, handle); - FuncReturn(system, retval); -} - -// Used by ControlCodeMemory32 -template -void SvcWrap32(Core::System& system) { - const u32 retval = - func(system, Param32(system, 0), Param32(system, 1), Param(system, 2), Param(system, 4), - static_cast(Param32(system, 6))) - .raw; - - FuncReturn(system, retval); -} - -// Used by Invalidate/Store/FlushProcessDataCache32 -template -void SvcWrap32(Core::System& system) { - const u64 address = (Param(system, 3) << 32) | Param(system, 2); - const u64 size = (Param(system, 4) << 32) | Param(system, 1); - FuncReturn32(system, func(system, Param32(system, 0), address, size).raw); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp deleted file mode 100755 index 9873de95c..000000000 --- a/src/core/hle/kernel/time_manager.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/assert.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/time_manager.h" - -namespace Kernel { - -TimeManager::TimeManager(Core::System& system_) : system{system_} { - time_manager_event_type = Core::Timing::CreateEvent( - "Kernel::TimeManagerCallback", - [this](std::uintptr_t thread_handle, s64 time, - std::chrono::nanoseconds) -> std::optional { - KThread* thread = reinterpret_cast(thread_handle); - { - KScopedSchedulerLock sl(system.Kernel()); - thread->OnTimer(); - } - return std::nullopt; - }); -} - -void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { - std::scoped_lock lock{mutex}; - if (nanoseconds > 0) { - ASSERT(thread); - ASSERT(thread->GetState() != ThreadState::Runnable); - system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds}, - time_manager_event_type, - reinterpret_cast(thread)); - } -} - -void TimeManager::UnscheduleTimeEvent(KThread* thread) { - std::scoped_lock lock{mutex}; - system.CoreTiming().UnscheduleEvent(time_manager_event_type, - reinterpret_cast(thread)); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h deleted file mode 100755 index 0e296cfbb..000000000 --- a/src/core/hle/kernel/time_manager.h +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -namespace Core { -class System; -} // namespace Core - -namespace Core::Timing { -struct EventType; -} // namespace Core::Timing - -namespace Kernel { - -class KThread; - -/** - * The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp - * method when the event is triggered. - */ -class TimeManager { -public: - explicit TimeManager(Core::System& system); - - /// Schedule a time event on `timetask` thread that will expire in 'nanoseconds' - void ScheduleTimeEvent(KThread* time_task, s64 nanoseconds); - - /// Unschedule an existing time event - void UnscheduleTimeEvent(KThread* thread); - -private: - Core::System& system; - std::shared_ptr time_manager_event_type; - std::mutex mutex; -}; - -} // namespace Kernel diff --git a/src/core/hle/service/am/tcap.cpp b/src/core/hle/service/am/tcap.cpp deleted file mode 100755 index 91d45df31..000000000 --- a/src/core/hle/service/am/tcap.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/tcap.h" - -namespace Service::AM { - -TCAP::TCAP(Core::System& system_) : ServiceFramework{system_, "tcap"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetContinuousHighSkinTemperatureEvent"}, - {1, nullptr, "SetOperationMode"}, - {2, nullptr, "LoadAndApplySettings"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -TCAP::~TCAP() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/tcap.h b/src/core/hle/service/am/tcap.h deleted file mode 100755 index 11b874d9a..000000000 --- a/src/core/hle/service/am/tcap.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::AM { - -class TCAP final : public ServiceFramework { -public: - explicit TCAP(Core::System& system_); - ~TCAP() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/audio/auddbg.cpp b/src/core/hle/service/audio/auddbg.cpp deleted file mode 100755 index 02b5b3496..000000000 --- a/src/core/hle/service/audio/auddbg.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/auddbg.h" - -namespace Service::Audio { - -AudDbg::AudDbg(Core::System& system_, const char* name) : ServiceFramework{system_, name} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspendForDebug"}, - {1, nullptr, "RequestResumeForDebug"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudDbg::~AudDbg() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/auddbg.h b/src/core/hle/service/audio/auddbg.h deleted file mode 100755 index 354fdf553..000000000 --- a/src/core/hle/service/audio/auddbg.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudDbg final : public ServiceFramework { -public: - explicit AudDbg(Core::System& system_, const char* name); - ~AudDbg() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp deleted file mode 100755 index 6993f1092..000000000 --- a/src/core/hle/service/audio/audin_a.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/audin_a.h" - -namespace Service::Audio { - -AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspend"}, - {1, nullptr, "RequestResume"}, - {2, nullptr, "GetProcessMasterVolume"}, - {3, nullptr, "SetProcessMasterVolume"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudInA::~AudInA() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audin_a.h b/src/core/hle/service/audio/audin_a.h deleted file mode 100755 index 265f8dea2..000000000 --- a/src/core/hle/service/audio/audin_a.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudInA final : public ServiceFramework { -public: - explicit AudInA(Core::System& system_); - ~AudInA() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp deleted file mode 100755 index d302cbb93..000000000 --- a/src/core/hle/service/audio/audout_a.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/audout_a.h" - -namespace Service::Audio { - -AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspend"}, - {1, nullptr, "RequestResume"}, - {2, nullptr, "GetProcessMasterVolume"}, - {3, nullptr, "SetProcessMasterVolume"}, - {4, nullptr, "GetProcessRecordVolume"}, - {5, nullptr, "SetProcessRecordVolume"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudOutA::~AudOutA() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audout_a.h b/src/core/hle/service/audio/audout_a.h deleted file mode 100755 index ad4e14f5a..000000000 --- a/src/core/hle/service/audio/audout_a.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudOutA final : public ServiceFramework { -public: - explicit AudOutA(Core::System& system_); - ~AudOutA() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp deleted file mode 100755 index 8307e3985..000000000 --- a/src/core/hle/service/audio/audren_a.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/audren_a.h" - -namespace Service::Audio { - -AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestSuspend"}, - {1, nullptr, "RequestResume"}, - {2, nullptr, "GetProcessMasterVolume"}, - {3, nullptr, "SetProcessMasterVolume"}, - {4, nullptr, "RegisterAppletResourceUserId"}, - {5, nullptr, "UnregisterAppletResourceUserId"}, - {6, nullptr, "GetProcessRecordVolume"}, - {7, nullptr, "SetProcessRecordVolume"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AudRenA::~AudRenA() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audren_a.h b/src/core/hle/service/audio/audren_a.h deleted file mode 100755 index 393051c1e..000000000 --- a/src/core/hle/service/audio/audren_a.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class AudRenA final : public ServiceFramework { -public: - explicit AudRenA(Core::System& system_); - ~AudRenA() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp deleted file mode 100755 index e358c550e..000000000 --- a/src/core/hle/service/audio/codecctl.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/audio/codecctl.h" - -namespace Service::Audio { - -CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { - static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {1, nullptr, "Finalize"}, - {2, nullptr, "Sleep"}, - {3, nullptr, "Wake"}, - {4, nullptr, "SetVolume"}, - {5, nullptr, "GetVolumeMax"}, - {6, nullptr, "GetVolumeMin"}, - {7, nullptr, "SetActiveTarget"}, - {8, nullptr, "GetActiveTarget"}, - {9, nullptr, "BindHeadphoneMicJackInterrupt"}, - {10, nullptr, "IsHeadphoneMicJackInserted"}, - {11, nullptr, "ClearHeadphoneMicJackInterrupt"}, - {12, nullptr, "IsRequested"}, - }; - RegisterHandlers(functions); -} - -CodecCtl::~CodecCtl() = default; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/codecctl.h b/src/core/hle/service/audio/codecctl.h deleted file mode 100755 index cf8c1d163..000000000 --- a/src/core/hle/service/audio/codecctl.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Audio { - -class CodecCtl final : public ServiceFramework { -public: - explicit CodecCtl(Core::System& system_); - ~CodecCtl() override; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/friend/errors.h b/src/core/hle/service/friend/errors.h deleted file mode 100755 index 3dd6eda28..000000000 --- a/src/core/hle/service/friend/errors.h +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/result.h" - -namespace Service::Friend { - -constexpr Result ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15}; -} diff --git a/src/core/hle/service/nfc/mifare_user.cpp b/src/core/hle/service/nfc/mifare_user.cpp deleted file mode 100755 index e0bbd46e1..000000000 --- a/src/core/hle/service/nfc/mifare_user.cpp +++ /dev/null @@ -1,400 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nfc/mifare_user.h" -#include "core/hle/service/nfc/nfc_device.h" -#include "core/hle/service/nfc/nfc_result.h" - -namespace Service::NFC { - -MFIUser::MFIUser(Core::System& system_) - : ServiceFramework{system_, "NFC::MFIUser"}, service_context{system_, service_name} { - static const FunctionInfo functions[] = { - {0, &MFIUser::Initialize, "Initialize"}, - {1, &MFIUser::Finalize, "Finalize"}, - {2, &MFIUser::ListDevices, "ListDevices"}, - {3, &MFIUser::StartDetection, "StartDetection"}, - {4, &MFIUser::StopDetection, "StopDetection"}, - {5, &MFIUser::Read, "Read"}, - {6, &MFIUser::Write, "Write"}, - {7, &MFIUser::GetTagInfo, "GetTagInfo"}, - {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"}, - {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"}, - {10, &MFIUser::GetState, "GetState"}, - {11, &MFIUser::GetDeviceState, "GetDeviceState"}, - {12, &MFIUser::GetNpadId, "GetNpadId"}, - {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"}, - }; - RegisterHandlers(functions); - - availability_change_event = service_context.CreateEvent("MFIUser:AvailabilityChangeEvent"); - - for (u32 device_index = 0; device_index < 10; device_index++) { - devices[device_index] = - std::make_shared(Core::HID::IndexToNpadIdType(device_index), system, - service_context, availability_change_event); - } -} - -MFIUser ::~MFIUser() { - availability_change_event->Close(); -} - -void MFIUser::Initialize(HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2, 0}; - rb.Push(ResultSuccess); -} - -void MFIUser::Finalize(HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void MFIUser::ListDevices(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareInvalidArgument); - return; - } - - if (ctx.GetWriteBufferSize() == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareInvalidArgument); - return; - } - - std::vector nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements(); - - for (const auto& device : devices) { - if (nfp_devices.size() >= max_allowed_devices) { - continue; - } - if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); - } - } - - if (nfp_devices.empty()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - ctx.WriteBuffer(nfp_devices); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast(nfp_devices.size())); -} - -void MFIUser::StartDetection(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - const auto result = device.value()->StartDetection(NFP::TagProtocol::All); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::StopDetection(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - const auto result = device.value()->StopDetection(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::Read(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto buffer{ctx.ReadBuffer()}; - const auto number_of_commands{ctx.GetReadBufferNumElements()}; - std::vector read_commands(number_of_commands); - - memcpy(read_commands.data(), buffer.data(), - number_of_commands * sizeof(NFP::MifareReadBlockParameter)); - - LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}", - device_handle, number_of_commands); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - Result result = ResultSuccess; - std::vector out_data(number_of_commands); - for (std::size_t i = 0; i < number_of_commands; i++) { - result = device.value()->MifareRead(read_commands[i], out_data[i]); - if (result.IsError()) { - break; - } - } - - ctx.WriteBuffer(out_data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::Write(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto buffer{ctx.ReadBuffer()}; - const auto number_of_commands{ctx.GetReadBufferNumElements()}; - std::vector write_commands(number_of_commands); - - memcpy(write_commands.data(), buffer.data(), - number_of_commands * sizeof(NFP::MifareWriteBlockParameter)); - - LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}", - device_handle, number_of_commands); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - Result result = ResultSuccess; - std::vector out_data(number_of_commands); - for (std::size_t i = 0; i < number_of_commands; i++) { - result = device.value()->MifareWrite(write_commands[i]); - if (result.IsError()) { - break; - } - } - - if (result.IsSuccess()) { - result = device.value()->Flush(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::GetTagInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - NFP::TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info, true); - ctx.WriteBuffer(tag_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void MFIUser::GetActivateEventHandle(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetActivateEvent()); -} - -void MFIUser::GetDeactivateEventHandle(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetDeactivateEvent()); -} - -void MFIUser::GetState(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void MFIUser::GetDeviceState(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetCurrentState()); -} - -void MFIUser::GetNpadId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareDeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetNpadId()); -} - -void MFIUser::GetAvailabilityChangeEventHandle(HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(MifareNfcDisabled); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(availability_change_event->GetReadableEvent()); -} - -std::optional> MFIUser::GetNfcDevice(u64 handle) { - for (auto& device : devices) { - if (device->GetHandle() == handle) { - return device; - } - } - return std::nullopt; -} - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/mifare_user.h b/src/core/hle/service/nfc/mifare_user.h deleted file mode 100755 index 9701f1d7f..000000000 --- a/src/core/hle/service/nfc/mifare_user.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::NFC { -class NfcDevice; - -class MFIUser final : public ServiceFramework { -public: - explicit MFIUser(Core::System& system_); - ~MFIUser(); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - void Initialize(HLERequestContext& ctx); - void Finalize(HLERequestContext& ctx); - void ListDevices(HLERequestContext& ctx); - void StartDetection(HLERequestContext& ctx); - void StopDetection(HLERequestContext& ctx); - void Read(HLERequestContext& ctx); - void Write(HLERequestContext& ctx); - void GetTagInfo(HLERequestContext& ctx); - void GetActivateEventHandle(HLERequestContext& ctx); - void GetDeactivateEventHandle(HLERequestContext& ctx); - void GetState(HLERequestContext& ctx); - void GetDeviceState(HLERequestContext& ctx); - void GetNpadId(HLERequestContext& ctx); - void GetAvailabilityChangeEventHandle(HLERequestContext& ctx); - - std::optional> GetNfcDevice(u64 handle); - - KernelHelpers::ServiceContext service_context; - - std::array, 10> devices{}; - - State state{State::NonInitialized}; - Kernel::KEvent* availability_change_event; -}; - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp deleted file mode 100755 index c7db74d14..000000000 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/input.h" -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nfc/nfc_device.h" -#include "core/hle/service/nfc/nfc_result.h" -#include "core/hle/service/nfc/nfc_user.h" - -namespace Service::NFC { -NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_) - : npad_id{npad_id_}, system{system_}, service_context{service_context_}, - availability_change_event{availability_change_event_} { - activate_event = service_context.CreateEvent("IUser:NFCActivateEvent"); - deactivate_event = service_context.CreateEvent("IUser:NFCDeactivateEvent"); - npad_device = system.HIDCore().GetEmulatedController(npad_id); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); }, - .is_npad_service = false, - }; - is_controller_set = true; - callback_key = npad_device->SetCallback(engine_callback); -} - -NfcDevice::~NfcDevice() { - activate_event->Close(); - deactivate_event->Close(); - if (!is_controller_set) { - return; - } - npad_device->DeleteCallback(callback_key); - is_controller_set = false; -}; - -void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { - if (!is_initalized) { - return; - } - - if (type == Core::HID::ControllerTriggerType::Connected) { - Initialize(); - availability_change_event->Signal(); - return; - } - - if (type == Core::HID::ControllerTriggerType::Disconnected) { - device_state = NFP::DeviceState::Unavailable; - availability_change_event->Signal(); - return; - } - - if (type != Core::HID::ControllerTriggerType::Nfc) { - return; - } - - if (!npad_device->IsConnected()) { - return; - } - - const auto nfc_status = npad_device->GetNfc(); - switch (nfc_status.state) { - case Common::Input::NfcState::NewAmiibo: - LoadNfcTag(nfc_status.data); - break; - case Common::Input::NfcState::AmiiboRemoved: - if (device_state != NFP::DeviceState::SearchingForTag) { - CloseNfcTag(); - } - break; - default: - break; - } -} - -bool NfcDevice::LoadNfcTag(std::span data) { - if (device_state != NFP::DeviceState::SearchingForTag) { - LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state); - return false; - } - - if (data.size() < sizeof(NFP::EncryptedNTAG215File)) { - LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); - return false; - } - - tag_data.resize(data.size()); - memcpy(tag_data.data(), data.data(), data.size()); - memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); - - device_state = NFP::DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(); - activate_event->Signal(); - return true; -} - -void NfcDevice::CloseNfcTag() { - LOG_INFO(Service_NFC, "Remove nfc tag"); - - device_state = NFP::DeviceState::TagRemoved; - encrypted_tag_data = {}; - activate_event->GetReadableEvent().Clear(); - deactivate_event->Signal(); -} - -Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { - return activate_event->GetReadableEvent(); -} - -Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const { - return deactivate_event->GetReadableEvent(); -} - -void NfcDevice::Initialize() { - device_state = - npad_device->HasNfc() ? NFP::DeviceState::Initialized : NFP::DeviceState::Unavailable; - encrypted_tag_data = {}; - is_initalized = true; -} - -void NfcDevice::Finalize() { - if (device_state == NFP::DeviceState::SearchingForTag || - device_state == NFP::DeviceState::TagRemoved) { - StopDetection(); - } - device_state = NFP::DeviceState::Unavailable; - is_initalized = false; -} - -Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { - if (device_state != NFP::DeviceState::Initialized && - device_state != NFP::DeviceState::TagRemoved) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - return WrongDeviceState; - } - - if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::NFC) != - Common::Input::DriverResult::Success) { - LOG_ERROR(Service_NFC, "Nfc not supported"); - return NfcDisabled; - } - - device_state = NFP::DeviceState::SearchingForTag; - allowed_protocols = allowed_protocol; - return ResultSuccess; -} - -Result NfcDevice::StopDetection() { - npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active); - - if (device_state == NFP::DeviceState::Initialized) { - return ResultSuccess; - } - - if (device_state == NFP::DeviceState::TagFound || - device_state == NFP::DeviceState::TagMounted) { - CloseNfcTag(); - return ResultSuccess; - } - if (device_state == NFP::DeviceState::SearchingForTag || - device_state == NFP::DeviceState::TagRemoved) { - device_state = NFP::DeviceState::Initialized; - return ResultSuccess; - } - - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - return WrongDeviceState; -} - -Result NfcDevice::Flush() { - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (!npad_device->WriteNfc(tag_data)) { - LOG_ERROR(Service_NFP, "Error writing to file"); - return MifareReadError; - } - - return ResultSuccess; -} - -Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (is_mifare) { - tag_info = { - .uuid = encrypted_tag_data.uuid.uid, - .uuid_length = static_cast(encrypted_tag_data.uuid.uid.size()), - .protocol = NFP::TagProtocol::TypeA, - .tag_type = NFP::TagType::Type4, - }; - return ResultSuccess; - } - - // Protocol and tag type may change here - tag_info = { - .uuid = encrypted_tag_data.uuid.uid, - .uuid_length = static_cast(encrypted_tag_data.uuid.uid.size()), - .protocol = NFP::TagProtocol::TypeA, - .tag_type = NFP::TagType::Type2, - }; - - return ResultSuccess; -} - -Result NfcDevice::MifareRead(const NFP::MifareReadBlockParameter& parameter, - NFP::MifareReadBlockData& read_block_data) { - const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock); - read_block_data.sector_number = parameter.sector_number; - - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) { - return MifareReadError; - } - - // TODO: Use parameter.sector_key to read encrypted data - memcpy(read_block_data.data.data(), tag_data.data() + sector_index, sizeof(NFP::DataBlock)); - - return ResultSuccess; -} - -Result NfcDevice::MifareWrite(const NFP::MifareWriteBlockParameter& parameter) { - const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock); - - if (device_state != NFP::DeviceState::TagFound && - device_state != NFP::DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == NFP::DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) { - return MifareReadError; - } - - // TODO: Use parameter.sector_key to encrypt the data - memcpy(tag_data.data() + sector_index, parameter.data.data(), sizeof(NFP::DataBlock)); - - return ResultSuccess; -} - -u64 NfcDevice::GetHandle() const { - // Generate a handle based of the npad id - return static_cast(npad_id); -} - -NFP::DeviceState NfcDevice::GetCurrentState() const { - return device_state; -} - -Core::HID::NpadIdType NfcDevice::GetNpadId() const { - return npad_id; -} - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h deleted file mode 100755 index ea63f0537..000000000 --- a/src/core/hle/service/nfc/nfc_device.h +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nfp/nfp_types.h" -#include "core/hle/service/service.h" - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Core { -class System; -} // namespace Core - -namespace Core::HID { -class EmulatedController; -enum class ControllerTriggerType; -enum class NpadIdType : u32; -} // namespace Core::HID - -namespace Service::NFC { -class NfcDevice { -public: - NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_); - ~NfcDevice(); - - void Initialize(); - void Finalize(); - - Result StartDetection(NFP::TagProtocol allowed_protocol); - Result StopDetection(); - Result Flush(); - - Result GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const; - - Result MifareRead(const NFP::MifareReadBlockParameter& parameter, - NFP::MifareReadBlockData& read_block_data); - - Result MifareWrite(const NFP::MifareWriteBlockParameter& parameter); - - u64 GetHandle() const; - NFP::DeviceState GetCurrentState() const; - Core::HID::NpadIdType GetNpadId() const; - - Kernel::KReadableEvent& GetActivateEvent() const; - Kernel::KReadableEvent& GetDeactivateEvent() const; - -private: - void NpadUpdate(Core::HID::ControllerTriggerType type); - bool LoadNfcTag(std::span data); - void CloseNfcTag(); - - bool is_controller_set{}; - int callback_key; - const Core::HID::NpadIdType npad_id; - Core::System& system; - Core::HID::EmulatedController* npad_device = nullptr; - KernelHelpers::ServiceContext& service_context; - Kernel::KEvent* activate_event = nullptr; - Kernel::KEvent* deactivate_event = nullptr; - Kernel::KEvent* availability_change_event = nullptr; - - bool is_initalized{}; - NFP::TagProtocol allowed_protocols{}; - NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; - - NFP::EncryptedNTAG215File encrypted_tag_data{}; - std::vector tag_data{}; -}; - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_user.cpp b/src/core/hle/service/nfc/nfc_user.cpp deleted file mode 100755 index 7c162a4f3..000000000 --- a/src/core/hle/service/nfc/nfc_user.cpp +++ /dev/null @@ -1,365 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nfc/nfc_device.h" -#include "core/hle/service/nfc/nfc_result.h" -#include "core/hle/service/nfc/nfc_user.h" -#include "core/hle/service/time/clock_types.h" - -namespace Service::NFC { - -IUser::IUser(Core::System& system_) - : ServiceFramework{system_, "NFC::IUser"}, service_context{system_, service_name} { - static const FunctionInfo functions[] = { - {0, &IUser::Initialize, "InitializeOld"}, - {1, &IUser::Finalize, "FinalizeOld"}, - {2, &IUser::GetState, "GetStateOld"}, - {3, &IUser::IsNfcEnabled, "IsNfcEnabledOld"}, - {400, &IUser::Initialize, "Initialize"}, - {401, &IUser::Finalize, "Finalize"}, - {402, &IUser::GetState, "GetState"}, - {403, &IUser::IsNfcEnabled, "IsNfcEnabled"}, - {404, &IUser::ListDevices, "ListDevices"}, - {405, &IUser::GetDeviceState, "GetDeviceState"}, - {406, &IUser::GetNpadId, "GetNpadId"}, - {407, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, - {408, &IUser::StartDetection, "StartDetection"}, - {409, &IUser::StopDetection, "StopDetection"}, - {410, &IUser::GetTagInfo, "GetTagInfo"}, - {411, &IUser::AttachActivateEvent, "AttachActivateEvent"}, - {412, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, - {1000, nullptr, "ReadMifare"}, - {1001, nullptr, "WriteMifare"}, - {1300, &IUser::SendCommandByPassThrough, "SendCommandByPassThrough"}, - {1301, nullptr, "KeepPassThroughSession"}, - {1302, nullptr, "ReleasePassThroughSession"}, - }; - RegisterHandlers(functions); - - availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent"); - - for (u32 device_index = 0; device_index < 10; device_index++) { - devices[device_index] = - std::make_shared(Core::HID::IndexToNpadIdType(device_index), system, - service_context, availability_change_event); - } -} - -IUser ::~IUser() { - availability_change_event->Close(); -} - -void IUser::Initialize(HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2, 0}; - rb.Push(ResultSuccess); -} - -void IUser::Finalize(HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IUser::GetState(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void IUser::IsNfcEnabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(state != State::NonInitialized); -} - -void IUser::ListDevices(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - if (ctx.GetWriteBufferSize() == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - std::vector nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements(); - - for (auto& device : devices) { - if (nfp_devices.size() >= max_allowed_devices) { - continue; - } - if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); - } - } - - if (nfp_devices.empty()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - ctx.WriteBuffer(nfp_devices); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast(nfp_devices.size())); -} - -void IUser::GetDeviceState(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetCurrentState()); -} - -void IUser::GetNpadId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetNpadId()); -} - -void IUser::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { - LOG_INFO(Service_NFC, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(availability_change_event->GetReadableEvent()); -} - -void IUser::StartDetection(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto nfp_protocol{rp.PopEnum()}; - LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StartDetection(nfp_protocol); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::StopDetection(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StopDetection(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetTagInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - NFP::TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info, false); - ctx.WriteBuffer(tag_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::AttachActivateEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetActivateEvent()); -} - -void IUser::AttachDeactivateEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetDeactivateEvent()); -} - -void IUser::SendCommandByPassThrough(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto timeout{rp.PopRaw()}; - const auto command_data{ctx.ReadBuffer()}; - - LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", - device_handle, timeout.ToSeconds(), command_data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfcDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - std::vector out_data(1); - // TODO: Request data from nfc device - ctx.WriteBuffer(out_data); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast(out_data.size())); -} - -std::optional> IUser::GetNfcDevice(u64 handle) { - for (auto& device : devices) { - if (device->GetHandle() == handle) { - return device; - } - } - return std::nullopt; -} - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc_user.h b/src/core/hle/service/nfc/nfc_user.h deleted file mode 100755 index aee046ae8..000000000 --- a/src/core/hle/service/nfc/nfc_user.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::NFC { -class NfcDevice; - -class IUser final : public ServiceFramework { -public: - explicit IUser(Core::System& system_); - ~IUser(); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - void Initialize(HLERequestContext& ctx); - void Finalize(HLERequestContext& ctx); - void GetState(HLERequestContext& ctx); - void IsNfcEnabled(HLERequestContext& ctx); - void ListDevices(HLERequestContext& ctx); - void GetDeviceState(HLERequestContext& ctx); - void GetNpadId(HLERequestContext& ctx); - void AttachAvailabilityChangeEvent(HLERequestContext& ctx); - void StartDetection(HLERequestContext& ctx); - void StopDetection(HLERequestContext& ctx); - void GetTagInfo(HLERequestContext& ctx); - void AttachActivateEvent(HLERequestContext& ctx); - void AttachDeactivateEvent(HLERequestContext& ctx); - void SendCommandByPassThrough(HLERequestContext& ctx); - - std::optional> GetNfcDevice(u64 handle); - - KernelHelpers::ServiceContext service_context; - - std::array, 10> devices{}; - - State state{State::NonInitialized}; - Kernel::KEvent* availability_change_event; -}; - -} // namespace Service::NFC diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp deleted file mode 100755 index fc08ce15b..000000000 --- a/src/core/hle/service/nfp/amiibo_crypto.cpp +++ /dev/null @@ -1,405 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -// SPDX-FileCopyrightText: Copyright 2017 socram8888/amiitool -// SPDX-License-Identifier: MIT - -#include -#include -#include - -#include "common/fs/file.h" -#include "common/fs/fs.h" -#include "common/fs/path_util.h" -#include "common/logging/log.h" -#include "core/hle/service/nfp/amiibo_crypto.h" - -namespace Service::NFP::AmiiboCrypto { - -bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) { - const auto& amiibo_data = ntag_file.user_memory; - LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", ntag_file.static_lock); - LOG_DEBUG(Service_NFP, "compability_container=0x{0:x}", ntag_file.compability_container); - LOG_DEBUG(Service_NFP, "write_count={}", static_cast(amiibo_data.write_counter)); - - LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id); - LOG_DEBUG(Service_NFP, "character_variant={}", amiibo_data.model_info.character_variant); - LOG_DEBUG(Service_NFP, "amiibo_type={}", amiibo_data.model_info.amiibo_type); - LOG_DEBUG(Service_NFP, "model_number=0x{0:x}", - static_cast(amiibo_data.model_info.model_number)); - LOG_DEBUG(Service_NFP, "series={}", amiibo_data.model_info.series); - LOG_DEBUG(Service_NFP, "tag_type=0x{0:x}", amiibo_data.model_info.tag_type); - - LOG_DEBUG(Service_NFP, "tag_dynamic_lock=0x{0:x}", ntag_file.dynamic_lock); - LOG_DEBUG(Service_NFP, "tag_CFG0=0x{0:x}", ntag_file.CFG0); - LOG_DEBUG(Service_NFP, "tag_CFG1=0x{0:x}", ntag_file.CFG1); - - // Validate UUID - constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3` - if ((CT ^ ntag_file.uuid.uid[0] ^ ntag_file.uuid.uid[1] ^ ntag_file.uuid.uid[2]) != - ntag_file.uuid.uid[3]) { - return false; - } - if ((ntag_file.uuid.uid[4] ^ ntag_file.uuid.uid[5] ^ ntag_file.uuid.uid[6] ^ - ntag_file.uuid.nintendo_id) != ntag_file.uuid.lock_bytes[0]) { - return false; - } - - // Check against all know constants on an amiibo binary - if (ntag_file.static_lock != 0xE00F) { - return false; - } - if (ntag_file.compability_container != 0xEEFF10F1U) { - return false; - } - if (amiibo_data.constant_value != 0xA5) { - return false; - } - if (amiibo_data.model_info.tag_type != PackedTagType::Type2) { - return false; - } - if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) { - return false; - } - if (ntag_file.CFG0 != 0x04000000U) { - return false; - } - if (ntag_file.CFG1 != 0x5F) { - return false; - } - return true; -} - -bool IsAmiiboValid(const NTAG215File& ntag_file) { - return IsAmiiboValid(EncodedDataToNfcData(ntag_file)); -} - -NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { - NTAG215File encoded_data{}; - - encoded_data.uid = nfc_data.uuid.uid; - encoded_data.nintendo_id = nfc_data.uuid.nintendo_id; - encoded_data.static_lock = nfc_data.static_lock; - encoded_data.compability_container = nfc_data.compability_container; - encoded_data.hmac_data = nfc_data.user_memory.hmac_data; - encoded_data.constant_value = nfc_data.user_memory.constant_value; - encoded_data.write_counter = nfc_data.user_memory.write_counter; - encoded_data.amiibo_version = nfc_data.user_memory.amiibo_version; - encoded_data.settings = nfc_data.user_memory.settings; - encoded_data.owner_mii = nfc_data.user_memory.owner_mii; - encoded_data.application_id = nfc_data.user_memory.application_id; - encoded_data.application_write_counter = nfc_data.user_memory.application_write_counter; - encoded_data.application_area_id = nfc_data.user_memory.application_area_id; - encoded_data.application_id_byte = nfc_data.user_memory.application_id_byte; - encoded_data.unknown = nfc_data.user_memory.unknown; - encoded_data.mii_extension = nfc_data.user_memory.mii_extension; - encoded_data.unknown2 = nfc_data.user_memory.unknown2; - encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc; - encoded_data.application_area = nfc_data.user_memory.application_area; - encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag; - encoded_data.lock_bytes = nfc_data.uuid.lock_bytes; - encoded_data.model_info = nfc_data.user_memory.model_info; - encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt; - encoded_data.dynamic_lock = nfc_data.dynamic_lock; - encoded_data.CFG0 = nfc_data.CFG0; - encoded_data.CFG1 = nfc_data.CFG1; - encoded_data.password = nfc_data.password; - - return encoded_data; -} - -EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) { - EncryptedNTAG215File nfc_data{}; - - nfc_data.uuid.uid = encoded_data.uid; - nfc_data.uuid.nintendo_id = encoded_data.nintendo_id; - nfc_data.uuid.lock_bytes = encoded_data.lock_bytes; - nfc_data.static_lock = encoded_data.static_lock; - nfc_data.compability_container = encoded_data.compability_container; - nfc_data.user_memory.hmac_data = encoded_data.hmac_data; - nfc_data.user_memory.constant_value = encoded_data.constant_value; - nfc_data.user_memory.write_counter = encoded_data.write_counter; - nfc_data.user_memory.amiibo_version = encoded_data.amiibo_version; - nfc_data.user_memory.settings = encoded_data.settings; - nfc_data.user_memory.owner_mii = encoded_data.owner_mii; - nfc_data.user_memory.application_id = encoded_data.application_id; - nfc_data.user_memory.application_write_counter = encoded_data.application_write_counter; - nfc_data.user_memory.application_area_id = encoded_data.application_area_id; - nfc_data.user_memory.application_id_byte = encoded_data.application_id_byte; - nfc_data.user_memory.unknown = encoded_data.unknown; - nfc_data.user_memory.mii_extension = encoded_data.mii_extension; - nfc_data.user_memory.unknown2 = encoded_data.unknown2; - nfc_data.user_memory.register_info_crc = encoded_data.register_info_crc; - nfc_data.user_memory.application_area = encoded_data.application_area; - nfc_data.user_memory.hmac_tag = encoded_data.hmac_tag; - nfc_data.user_memory.model_info = encoded_data.model_info; - nfc_data.user_memory.keygen_salt = encoded_data.keygen_salt; - nfc_data.dynamic_lock = encoded_data.dynamic_lock; - nfc_data.CFG0 = encoded_data.CFG0; - nfc_data.CFG1 = encoded_data.CFG1; - nfc_data.password = encoded_data.password; - - return nfc_data; -} - -u32 GetTagPassword(const TagUuid& uuid) { - // Verify that the generated password is correct - u32 password = 0xAA ^ (uuid.uid[1] ^ uuid.uid[3]); - password &= (0x55 ^ (uuid.uid[2] ^ uuid.uid[4])) << 8; - password &= (0xAA ^ (uuid.uid[3] ^ uuid.uid[5])) << 16; - password &= (0x55 ^ (uuid.uid[4] ^ uuid.uid[6])) << 24; - return password; -} - -HashSeed GetSeed(const NTAG215File& data) { - HashSeed seed{ - .magic = data.write_counter, - .padding = {}, - .uid_1 = data.uid, - .nintendo_id_1 = data.nintendo_id, - .uid_2 = data.uid, - .nintendo_id_2 = data.nintendo_id, - .keygen_salt = data.keygen_salt, - }; - - return seed; -} - -std::vector GenerateInternalKey(const InternalKey& key, const HashSeed& seed) { - const std::size_t seedPart1Len = sizeof(key.magic_bytes) - key.magic_length; - const std::size_t string_size = key.type_string.size(); - std::vector output(string_size + seedPart1Len); - - // Copy whole type string - memccpy(output.data(), key.type_string.data(), '\0', string_size); - - // Append (16 - magic_length) from the input seed - memcpy(output.data() + string_size, &seed, seedPart1Len); - - // Append all bytes from magicBytes - output.insert(output.end(), key.magic_bytes.begin(), - key.magic_bytes.begin() + key.magic_length); - - output.insert(output.end(), seed.uid_1.begin(), seed.uid_1.end()); - output.emplace_back(seed.nintendo_id_1); - output.insert(output.end(), seed.uid_2.begin(), seed.uid_2.end()); - output.emplace_back(seed.nintendo_id_2); - - for (std::size_t i = 0; i < sizeof(seed.keygen_salt); i++) { - output.emplace_back(static_cast(seed.keygen_salt[i] ^ key.xor_pad[i])); - } - - return output; -} - -void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key, - const std::vector& seed) { - // Initialize context - ctx.used = false; - ctx.counter = 0; - ctx.buffer_size = sizeof(ctx.counter) + seed.size(); - memcpy(ctx.buffer.data() + sizeof(u16), seed.data(), seed.size()); - - // Initialize HMAC context - mbedtls_md_init(&hmac_ctx); - mbedtls_md_setup(&hmac_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); - mbedtls_md_hmac_starts(&hmac_ctx, hmac_key.data(), hmac_key.size()); -} - -void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output) { - // If used at least once, reinitialize the HMAC - if (ctx.used) { - mbedtls_md_hmac_reset(&hmac_ctx); - } - - ctx.used = true; - - // Store counter in big endian, and increment it - ctx.buffer[0] = static_cast(ctx.counter >> 8); - ctx.buffer[1] = static_cast(ctx.counter >> 0); - ctx.counter++; - - // Do HMAC magic - mbedtls_md_hmac_update(&hmac_ctx, reinterpret_cast(ctx.buffer.data()), - ctx.buffer_size); - mbedtls_md_hmac_finish(&hmac_ctx, output.data()); -} - -DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) { - const auto seed = GetSeed(data); - - // Generate internal seed - const std::vector internal_key = GenerateInternalKey(key, seed); - - // Initialize context - CryptoCtx ctx{}; - mbedtls_md_context_t hmac_ctx; - CryptoInit(ctx, hmac_ctx, key.hmac_key, internal_key); - - // Generate derived keys - DerivedKeys derived_keys{}; - std::array temp{}; - CryptoStep(ctx, hmac_ctx, temp[0]); - CryptoStep(ctx, hmac_ctx, temp[1]); - memcpy(&derived_keys, temp.data(), sizeof(DerivedKeys)); - - // Cleanup context - mbedtls_md_free(&hmac_ctx); - - return derived_keys; -} - -void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data) { - mbedtls_aes_context aes; - std::size_t nc_off = 0; - std::array nonce_counter{}; - std::array stream_block{}; - - const auto aes_key_size = static_cast(keys.aes_key.size() * 8); - mbedtls_aes_setkey_enc(&aes, keys.aes_key.data(), aes_key_size); - memcpy(nonce_counter.data(), keys.aes_iv.data(), sizeof(keys.aes_iv)); - - constexpr std::size_t encrypted_data_size = HMAC_TAG_START - SETTINGS_START; - mbedtls_aes_crypt_ctr(&aes, encrypted_data_size, &nc_off, nonce_counter.data(), - stream_block.data(), - reinterpret_cast(&in_data.settings), - reinterpret_cast(&out_data.settings)); - - // Copy the rest of the data directly - out_data.uid = in_data.uid; - out_data.nintendo_id = in_data.nintendo_id; - out_data.lock_bytes = in_data.lock_bytes; - out_data.static_lock = in_data.static_lock; - out_data.compability_container = in_data.compability_container; - - out_data.constant_value = in_data.constant_value; - out_data.write_counter = in_data.write_counter; - - out_data.model_info = in_data.model_info; - out_data.keygen_salt = in_data.keygen_salt; - out_data.dynamic_lock = in_data.dynamic_lock; - out_data.CFG0 = in_data.CFG0; - out_data.CFG1 = in_data.CFG1; - out_data.password = in_data.password; -} - -bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info) { - const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); - - const Common::FS::IOFile keys_file{yuzu_keys_dir / "key_retail.bin", - Common::FS::FileAccessMode::Read, - Common::FS::FileType::BinaryFile}; - - if (!keys_file.IsOpen()) { - LOG_ERROR(Service_NFP, "Failed to open key file"); - return false; - } - - if (keys_file.Read(unfixed_info) != 1) { - LOG_ERROR(Service_NFP, "Failed to read unfixed_info"); - return false; - } - if (keys_file.Read(locked_secret) != 1) { - LOG_ERROR(Service_NFP, "Failed to read locked-secret"); - return false; - } - - return true; -} - -bool IsKeyAvailable() { - const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); - return Common::FS::Exists(yuzu_keys_dir / "key_retail.bin"); -} - -bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data) { - InternalKey locked_secret{}; - InternalKey unfixed_info{}; - - if (!LoadKeys(locked_secret, unfixed_info)) { - return false; - } - - // Generate keys - NTAG215File encoded_data = NfcDataToEncodedData(encrypted_tag_data); - const auto data_keys = GenerateKey(unfixed_info, encoded_data); - const auto tag_keys = GenerateKey(locked_secret, encoded_data); - - // Decrypt - Cipher(data_keys, encoded_data, tag_data); - - // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! - constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START; - mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(), - sizeof(HmacKey), reinterpret_cast(&tag_data.uid), - input_length, reinterpret_cast(&tag_data.hmac_tag)); - - // Regenerate data HMAC - constexpr std::size_t input_length2 = DYNAMIC_LOCK_START - WRITE_COUNTER_START; - mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), data_keys.hmac_key.data(), - sizeof(HmacKey), - reinterpret_cast(&tag_data.write_counter), input_length2, - reinterpret_cast(&tag_data.hmac_data)); - - if (tag_data.hmac_data != encrypted_tag_data.user_memory.hmac_data) { - LOG_ERROR(Service_NFP, "hmac_data doesn't match"); - return false; - } - - if (tag_data.hmac_tag != encrypted_tag_data.user_memory.hmac_tag) { - LOG_ERROR(Service_NFP, "hmac_tag doesn't match"); - return false; - } - - return true; -} - -bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_tag_data) { - InternalKey locked_secret{}; - InternalKey unfixed_info{}; - - if (!LoadKeys(locked_secret, unfixed_info)) { - return false; - } - - // Generate keys - const auto data_keys = GenerateKey(unfixed_info, tag_data); - const auto tag_keys = GenerateKey(locked_secret, tag_data); - - NTAG215File encoded_tag_data{}; - - // Generate tag HMAC - constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START; - constexpr std::size_t input_length2 = HMAC_TAG_START - WRITE_COUNTER_START; - mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(), - sizeof(HmacKey), reinterpret_cast(&tag_data.uid), - input_length, reinterpret_cast(&encoded_tag_data.hmac_tag)); - - // Init mbedtls HMAC context - mbedtls_md_context_t ctx; - mbedtls_md_init(&ctx); - mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); - - // Generate data HMAC - mbedtls_md_hmac_starts(&ctx, data_keys.hmac_key.data(), sizeof(HmacKey)); - mbedtls_md_hmac_update(&ctx, reinterpret_cast(&tag_data.write_counter), - input_length2); // Data - mbedtls_md_hmac_update(&ctx, reinterpret_cast(&encoded_tag_data.hmac_tag), - sizeof(HashData)); // Tag HMAC - mbedtls_md_hmac_update(&ctx, reinterpret_cast(&tag_data.uid), - input_length); - mbedtls_md_hmac_finish(&ctx, reinterpret_cast(&encoded_tag_data.hmac_data)); - - // HMAC cleanup - mbedtls_md_free(&ctx); - - // Encrypt - Cipher(data_keys, tag_data, encoded_tag_data); - - // Convert back to hardware - encrypted_tag_data = EncodedDataToNfcData(encoded_tag_data); - - return true; -} - -} // namespace Service::NFP::AmiiboCrypto diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfp/amiibo_crypto.h deleted file mode 100755 index 0b0422a2f..000000000 --- a/src/core/hle/service/nfp/amiibo_crypto.h +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include - -#include "core/hle/service/nfp/nfp_types.h" - -struct mbedtls_md_context_t; - -namespace Service::NFP::AmiiboCrypto { -// Byte locations in Service::NFP::NTAG215File -constexpr std::size_t HMAC_DATA_START = 0x8; -constexpr std::size_t SETTINGS_START = 0x2c; -constexpr std::size_t WRITE_COUNTER_START = 0x29; -constexpr std::size_t HMAC_TAG_START = 0x1B4; -constexpr std::size_t UUID_START = 0x1D4; -constexpr std::size_t DYNAMIC_LOCK_START = 0x208; - -using HmacKey = std::array; -using DrgbOutput = std::array; - -struct HashSeed { - u16_be magic; - std::array padding; - UniqueSerialNumber uid_1; - u8 nintendo_id_1; - UniqueSerialNumber uid_2; - u8 nintendo_id_2; - std::array keygen_salt; -}; -static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size"); - -struct InternalKey { - HmacKey hmac_key; - std::array type_string; - u8 reserved; - u8 magic_length; - std::array magic_bytes; - std::array xor_pad; -}; -static_assert(sizeof(InternalKey) == 0x50, "InternalKey is an invalid size"); -static_assert(std::is_trivially_copyable_v, "InternalKey must be trivially copyable."); - -struct CryptoCtx { - std::array buffer; - bool used; - std::size_t buffer_size; - s16 counter; -}; - -struct DerivedKeys { - std::array aes_key; - std::array aes_iv; - std::array hmac_key; -}; -static_assert(sizeof(DerivedKeys) == 0x30, "DerivedKeys is an invalid size"); - -/// Validates that the amiibo file is not corrupted -bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file); - -/// Validates that the amiibo file is not corrupted -bool IsAmiiboValid(const NTAG215File& ntag_file); - -/// Converts from encrypted file format to encoded file format -NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data); - -/// Converts from encoded file format to encrypted file format -EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data); - -/// Returns password needed to allow write access to protected memory -u32 GetTagPassword(const TagUuid& uuid); - -// Generates Seed needed for key derivation -HashSeed GetSeed(const NTAG215File& data); - -// Middle step on the generation of derived keys -std::vector GenerateInternalKey(const InternalKey& key, const HashSeed& seed); - -// Initializes mbedtls context -void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key, - const std::vector& seed); - -// Feeds data to mbedtls context to generate the derived key -void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output); - -// Generates the derived key from amiibo data -DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data); - -// Encodes or decodes amiibo data -void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data); - -/// Loads both amiibo keys from key_retail.bin -bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info); - -/// Returns true if key_retail.bin exist -bool IsKeyAvailable(); - -/// Decodes encrypted amiibo data returns true if output is valid -bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data); - -/// Encodes plain amiibo data returns true if output is valid -bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_tag_data); - -} // namespace Service::NFP::AmiiboCrypto diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp deleted file mode 100755 index 8eb29ea1d..000000000 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ /dev/null @@ -1,1137 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4701) // Potentially uninitialized local variable 'result' used -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "common/input.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "common/tiny_mt.h" -#include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/mii/mii_manager.h" -#include "core/hle/service/mii/types.h" -#include "core/hle/service/nfp/amiibo_crypto.h" -#include "core/hle/service/nfp/nfp_device.h" -#include "core/hle/service/nfp/nfp_result.h" -#include "core/hle/service/time/time_manager.h" -#include "core/hle/service/time/time_zone_content_manager.h" -#include "core/hle/service/time/time_zone_types.h" - -namespace Service::NFP { -NfpDevice::NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_) - : npad_id{npad_id_}, system{system_}, service_context{service_context_}, - availability_change_event{availability_change_event_} { - activate_event = service_context.CreateEvent("IUser:NFPActivateEvent"); - deactivate_event = service_context.CreateEvent("IUser:NFPDeactivateEvent"); - npad_device = system.HIDCore().GetEmulatedController(npad_id); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); }, - .is_npad_service = false, - }; - is_controller_set = true; - callback_key = npad_device->SetCallback(engine_callback); - - auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()}; - current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point; -} - -NfpDevice::~NfpDevice() { - activate_event->Close(); - deactivate_event->Close(); - if (!is_controller_set) { - return; - } - npad_device->DeleteCallback(callback_key); - is_controller_set = false; -}; - -void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { - if (!is_initalized) { - return; - } - - if (type == Core::HID::ControllerTriggerType::Connected) { - Initialize(); - availability_change_event->Signal(); - return; - } - - if (type == Core::HID::ControllerTriggerType::Disconnected) { - device_state = DeviceState::Unavailable; - availability_change_event->Signal(); - return; - } - - if (type != Core::HID::ControllerTriggerType::Nfc) { - return; - } - - if (!npad_device->IsConnected()) { - return; - } - - const auto nfc_status = npad_device->GetNfc(); - switch (nfc_status.state) { - case Common::Input::NfcState::NewAmiibo: - LoadAmiibo(nfc_status.data); - break; - case Common::Input::NfcState::AmiiboRemoved: - if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { - break; - } - if (device_state != DeviceState::SearchingForTag) { - CloseAmiibo(); - } - break; - default: - break; - } -} - -bool NfpDevice::LoadAmiibo(std::span data) { - if (device_state != DeviceState::SearchingForTag) { - LOG_ERROR(Service_NFP, "Game is not looking for amiibos, current state {}", device_state); - return false; - } - - if (data.size() != sizeof(EncryptedNTAG215File)) { - LOG_ERROR(Service_NFP, "Not an amiibo, size={}", data.size()); - return false; - } - - // TODO: Filter by allowed_protocols here - - memcpy(&tag_data, data.data(), sizeof(EncryptedNTAG215File)); - is_plain_amiibo = AmiiboCrypto::IsAmiiboValid(tag_data); - - if (is_plain_amiibo) { - encrypted_tag_data = AmiiboCrypto::EncodedDataToNfcData(tag_data); - LOG_INFO(Service_NFP, "Using plain amiibo"); - } else { - tag_data = {}; - memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); - } - - device_state = DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(); - activate_event->Signal(); - return true; -} - -void NfpDevice::CloseAmiibo() { - LOG_INFO(Service_NFP, "Remove amiibo"); - - if (device_state == DeviceState::TagMounted) { - Unmount(); - } - - device_state = DeviceState::TagRemoved; - encrypted_tag_data = {}; - tag_data = {}; - activate_event->GetReadableEvent().Clear(); - deactivate_event->Signal(); -} - -Kernel::KReadableEvent& NfpDevice::GetActivateEvent() const { - return activate_event->GetReadableEvent(); -} - -Kernel::KReadableEvent& NfpDevice::GetDeactivateEvent() const { - return deactivate_event->GetReadableEvent(); -} - -void NfpDevice::Initialize() { - device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable; - encrypted_tag_data = {}; - tag_data = {}; - is_initalized = true; -} - -void NfpDevice::Finalize() { - if (device_state == DeviceState::TagMounted) { - Unmount(); - } - if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { - StopDetection(); - } - device_state = DeviceState::Unavailable; - is_initalized = false; -} - -Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { - if (device_state != DeviceState::Initialized && device_state != DeviceState::TagRemoved) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; - } - - if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::NFC) != - Common::Input::DriverResult::Success) { - LOG_ERROR(Service_NFP, "Nfc not supported"); - return NfcDisabled; - } - - device_state = DeviceState::SearchingForTag; - allowed_protocols = allowed_protocol; - return ResultSuccess; -} - -Result NfpDevice::StopDetection() { - npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active); - - if (device_state == DeviceState::Initialized) { - return ResultSuccess; - } - - if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { - CloseAmiibo(); - } - - if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) { - device_state = DeviceState::Initialized; - return ResultSuccess; - } - - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; -} - -Result NfpDevice::Flush() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - auto& settings = tag_data.settings; - - const auto& current_date = GetAmiiboDate(current_posix_time); - if (settings.write_date.raw_date != current_date.raw_date) { - settings.write_date = current_date; - UpdateSettingsCrc(); - } - - tag_data.write_counter++; - - FlushWithBreak(BreakType::Normal); - - is_data_moddified = false; - - return ResultSuccess; -} - -Result NfpDevice::FlushDebug() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - tag_data.write_counter++; - - FlushWithBreak(BreakType::Normal); - - is_data_moddified = false; - - return ResultSuccess; -} - -Result NfpDevice::FlushWithBreak(BreakType break_type) { - if (break_type != BreakType::Normal) { - LOG_ERROR(Service_NFC, "Break type not implemented {}", break_type); - return WrongDeviceState; - } - - std::vector data(sizeof(EncryptedNTAG215File)); - if (is_plain_amiibo) { - memcpy(data.data(), &tag_data, sizeof(tag_data)); - } else { - if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { - LOG_ERROR(Service_NFP, "Failed to encode data"); - return WriteAmiiboFailed; - } - - memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); - } - - if (!npad_device->WriteNfc(data)) { - LOG_ERROR(Service_NFP, "Error writing to file"); - return WriteAmiiboFailed; - } - - return ResultSuccess; -} - -Result NfpDevice::Mount(MountTarget mount_target_) { - if (device_state != DeviceState::TagFound) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - return WrongDeviceState; - } - - // The loaded amiibo is not encrypted - if (is_plain_amiibo) { - device_state = DeviceState::TagMounted; - mount_target = mount_target_; - return ResultSuccess; - } - - if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { - LOG_ERROR(Service_NFP, "Not an amiibo"); - return NotAnAmiibo; - } - - // Mark amiibos as read only when keys are missing - if (!AmiiboCrypto::IsKeyAvailable()) { - LOG_ERROR(Service_NFP, "No keys detected"); - device_state = DeviceState::TagMounted; - mount_target = MountTarget::Rom; - return ResultSuccess; - } - - if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { - LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state); - return CorruptedData; - } - - device_state = DeviceState::TagMounted; - mount_target = mount_target_; - return ResultSuccess; -} - -Result NfpDevice::Unmount() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - // Save data before unloading the amiibo - if (is_data_moddified) { - Flush(); - } - - device_state = DeviceState::TagFound; - mount_target = MountTarget::None; - is_app_area_open = false; - - return ResultSuccess; -} - -Result NfpDevice::GetTagInfo(TagInfo& tag_info) const { - if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - tag_info = { - .uuid = encrypted_tag_data.uuid.uid, - .uuid_length = static_cast(encrypted_tag_data.uuid.uid.size()), - .protocol = TagProtocol::TypeA, - .tag_type = TagType::Type2, - }; - - return ResultSuccess; -} - -Result NfpDevice::GetCommonInfo(CommonInfo& common_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - const auto& settings = tag_data.settings; - - // TODO: Validate this data - common_info = { - .last_write_date = settings.write_date.GetWriteDate(), - .write_counter = tag_data.write_counter, - .version = tag_data.amiibo_version, - .application_area_size = sizeof(ApplicationArea), - }; - return ResultSuccess; -} - -Result NfpDevice::GetModelInfo(ModelInfo& model_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - const auto& model_info_data = encrypted_tag_data.user_memory.model_info; - model_info = { - .character_id = model_info_data.character_id, - .character_variant = model_info_data.character_variant, - .amiibo_type = model_info_data.amiibo_type, - .model_number = model_info_data.model_number, - .series = model_info_data.series, - }; - return ResultSuccess; -} - -Result NfpDevice::GetRegisterInfo(RegisterInfo& register_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; - } - - Service::Mii::MiiManager manager; - const auto& settings = tag_data.settings; - - // TODO: Validate this data - register_info = { - .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii), - .creation_date = settings.init_date.GetWriteDate(), - .amiibo_name = GetAmiiboName(settings), - .font_region = settings.settings.font_region, - }; - - return ResultSuccess; -} - -Result NfpDevice::GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; - } - - Service::Mii::MiiManager manager; - const auto& settings = tag_data.settings; - - // TODO: Validate and complete this data - register_info = { - .mii_store_data = {}, - .creation_date = settings.init_date.GetWriteDate(), - .amiibo_name = GetAmiiboName(settings), - .font_region = settings.settings.font_region, - }; - - return ResultSuccess; -} - -Result NfpDevice::GetAdminInfo(AdminInfo& admin_info) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - u8 flags = static_cast(tag_data.settings.settings.raw >> 0x4); - if (tag_data.settings.settings.amiibo_initialized == 0) { - flags = flags & 0xfe; - } - - u64 application_id = 0; - u32 application_area_id = 0; - AppAreaVersion app_area_version = AppAreaVersion::NotSet; - if (tag_data.settings.settings.appdata_initialized != 0) { - application_id = tag_data.application_id; - app_area_version = - static_cast(application_id >> application_id_version_offset & 0xf); - - // Restore application id to original value - if (application_id >> 0x38 != 0) { - const u8 application_byte = tag_data.application_id_byte & 0xf; - application_id = RemoveVersionByte(application_id) | - (static_cast(application_byte) << application_id_version_offset); - } - - application_area_id = tag_data.application_area_id; - } - - // TODO: Validate this data - admin_info = { - .application_id = application_id, - .application_area_id = application_area_id, - .crc_change_counter = tag_data.settings.crc_counter, - .flags = flags, - .tag_type = PackedTagType::Type2, - .app_area_version = app_area_version, - }; - - return ResultSuccess; -} - -Result NfpDevice::DeleteRegisterInfo() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.amiibo_initialized == 0) { - return RegistrationIsNotInitialized; - } - - Common::TinyMT rng{}; - rng.GenerateRandomBytes(&tag_data.owner_mii, sizeof(tag_data.owner_mii)); - rng.GenerateRandomBytes(&tag_data.settings.amiibo_name, sizeof(tag_data.settings.amiibo_name)); - rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8)); - rng.GenerateRandomBytes(&tag_data.unknown2[0], sizeof(u32)); - rng.GenerateRandomBytes(&tag_data.unknown2[1], sizeof(u32)); - rng.GenerateRandomBytes(&tag_data.register_info_crc, sizeof(u32)); - rng.GenerateRandomBytes(&tag_data.settings.init_date, sizeof(u32)); - tag_data.settings.settings.font_region.Assign(0); - tag_data.settings.settings.amiibo_initialized.Assign(0); - - return Flush(); -} - -Result NfpDevice::SetRegisterInfoPrivate(const AmiiboName& amiibo_name) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - Service::Mii::MiiManager manager; - const auto mii = manager.BuildDefault(0); - auto& settings = tag_data.settings; - - if (tag_data.settings.settings.amiibo_initialized == 0) { - settings.init_date = GetAmiiboDate(current_posix_time); - settings.write_date.raw_date = 0; - } - - SetAmiiboName(settings, amiibo_name); - tag_data.owner_mii = manager.BuildFromStoreData(mii); - tag_data.mii_extension = manager.SetFromStoreData(mii); - tag_data.unknown = 0; - tag_data.unknown2 = {}; - settings.country_code_id = 0; - settings.settings.font_region.Assign(0); - settings.settings.amiibo_initialized.Assign(1); - - UpdateRegisterInfoCrc(); - - return Flush(); -} - -Result NfpDevice::RestoreAmiibo() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - // TODO: Load amiibo from backup on system - LOG_ERROR(Service_NFP, "Not Implemented"); - return ResultSuccess; -} - -Result NfpDevice::Format() { - auto result1 = DeleteApplicationArea(); - auto result2 = DeleteRegisterInfo(); - - if (result1.IsError()) { - return result1; - } - - if (result2.IsError()) { - return result2; - } - - return Flush(); -} - -Result NfpDevice::OpenApplicationArea(u32 access_id) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_WARNING(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - if (tag_data.application_area_id != access_id) { - LOG_WARNING(Service_NFP, "Wrong application area id"); - return WrongApplicationAreaId; - } - - is_app_area_open = true; - - return ResultSuccess; -} - -Result NfpDevice::GetApplicationAreaId(u32& application_area_id) const { - application_area_id = {}; - - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_WARNING(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - application_area_id = tag_data.application_area_id; - - return ResultSuccess; -} - -Result NfpDevice::GetApplicationArea(std::vector& data) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (!is_app_area_open) { - LOG_ERROR(Service_NFP, "Application area is not open"); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_ERROR(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - if (data.size() > sizeof(ApplicationArea)) { - data.resize(sizeof(ApplicationArea)); - } - - memcpy(data.data(), tag_data.application_area.data(), data.size()); - - return ResultSuccess; -} - -Result NfpDevice::SetApplicationArea(std::span data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (!is_app_area_open) { - LOG_ERROR(Service_NFP, "Application area is not open"); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() == 0) { - LOG_ERROR(Service_NFP, "Application area is not initialized"); - return ApplicationAreaIsNotInitialized; - } - - if (data.size() > sizeof(ApplicationArea)) { - LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); - return ResultUnknown; - } - - Common::TinyMT rng{}; - std::memcpy(tag_data.application_area.data(), data.data(), data.size()); - // Fill remaining data with random numbers - rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), - sizeof(ApplicationArea) - data.size()); - - if (tag_data.application_write_counter != counter_limit) { - tag_data.application_write_counter++; - } - - is_data_moddified = true; - - return ResultSuccess; -} - -Result NfpDevice::CreateApplicationArea(u32 access_id, std::span data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized.Value() != 0) { - LOG_ERROR(Service_NFP, "Application area already exist"); - return ApplicationAreaExist; - } - - return RecreateApplicationArea(access_id, data); -} - -Result NfpDevice::RecreateApplicationArea(u32 access_id, std::span data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (is_app_area_open) { - LOG_ERROR(Service_NFP, "Application area is open"); - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (data.size() > sizeof(ApplicationArea)) { - LOG_ERROR(Service_NFP, "Wrong data size {}", data.size()); - return WrongApplicationAreaSize; - } - - Common::TinyMT rng{}; - std::memcpy(tag_data.application_area.data(), data.data(), data.size()); - // Fill remaining data with random numbers - rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(), - sizeof(ApplicationArea) - data.size()); - - if (tag_data.application_write_counter != counter_limit) { - tag_data.application_write_counter++; - } - - const u64 application_id = system.GetApplicationProcessProgramID(); - - tag_data.application_id_byte = - static_cast(application_id >> application_id_version_offset & 0xf); - tag_data.application_id = - RemoveVersionByte(application_id) | - (static_cast(AppAreaVersion::NintendoSwitch) << application_id_version_offset); - tag_data.settings.settings.appdata_initialized.Assign(1); - tag_data.application_area_id = access_id; - tag_data.unknown = {}; - tag_data.unknown2 = {}; - - UpdateRegisterInfoCrc(); - - return Flush(); -} - -Result NfpDevice::DeleteApplicationArea() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFP, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - if (tag_data.settings.settings.appdata_initialized == 0) { - return ApplicationAreaIsNotInitialized; - } - - if (tag_data.application_write_counter != counter_limit) { - tag_data.application_write_counter++; - } - - Common::TinyMT rng{}; - rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(ApplicationArea)); - rng.GenerateRandomBytes(&tag_data.application_id, sizeof(u64)); - rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32)); - rng.GenerateRandomBytes(&tag_data.application_id_byte, sizeof(u8)); - tag_data.settings.settings.appdata_initialized.Assign(0); - tag_data.unknown = {}; - tag_data.unknown2 = {}; - is_app_area_open = false; - - UpdateRegisterInfoCrc(); - - return Flush(); -} - -Result NfpDevice::ExistApplicationArea(bool& has_application_area) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - has_application_area = tag_data.settings.settings.appdata_initialized.Value() != 0; - - return ResultSuccess; -} - -Result NfpDevice::GetAll(NfpData& data) const { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - CommonInfo common_info{}; - Service::Mii::MiiManager manager; - const u64 application_id = tag_data.application_id; - - GetCommonInfo(common_info); - - data = { - .magic = tag_data.constant_value, - .write_counter = tag_data.write_counter, - .settings_crc = tag_data.settings.crc, - .common_info = common_info, - .mii_char_info = tag_data.owner_mii, - .mii_store_data_extension = tag_data.mii_extension, - .creation_date = tag_data.settings.init_date.GetWriteDate(), - .amiibo_name = tag_data.settings.amiibo_name, - .amiibo_name_null_terminated = 0, - .settings = tag_data.settings.settings, - .unknown1 = tag_data.unknown, - .register_info_crc = tag_data.register_info_crc, - .unknown2 = tag_data.unknown2, - .application_id = application_id, - .access_id = tag_data.application_area_id, - .settings_crc_counter = tag_data.settings.crc_counter, - .font_region = tag_data.settings.settings.font_region, - .tag_type = PackedTagType::Type2, - .console_type = - static_cast(application_id >> application_id_version_offset & 0xf), - .application_id_byte = tag_data.application_id_byte, - .application_area = tag_data.application_area, - }; - - return ResultSuccess; -} - -Result NfpDevice::SetAll(const NfpData& data) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - tag_data.constant_value = data.magic; - tag_data.write_counter = data.write_counter; - tag_data.settings.crc = data.settings_crc; - tag_data.settings.write_date.SetWriteDate(data.common_info.last_write_date); - tag_data.write_counter = data.common_info.write_counter; - tag_data.amiibo_version = data.common_info.version; - tag_data.owner_mii = data.mii_char_info; - tag_data.mii_extension = data.mii_store_data_extension; - tag_data.settings.init_date.SetWriteDate(data.creation_date); - tag_data.settings.amiibo_name = data.amiibo_name; - tag_data.settings.settings = data.settings; - tag_data.unknown = data.unknown1; - tag_data.register_info_crc = data.register_info_crc; - tag_data.unknown2 = data.unknown2; - tag_data.application_id = data.application_id; - tag_data.application_area_id = data.access_id; - tag_data.settings.crc_counter = data.settings_crc_counter; - tag_data.settings.settings.font_region.Assign(data.font_region); - tag_data.application_id_byte = data.application_id_byte; - tag_data.application_area = data.application_area; - - return ResultSuccess; -} - -Result NfpDevice::BreakTag(BreakType break_type) { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - // TODO: Complete this implementation - - return FlushWithBreak(break_type); -} - -Result NfpDevice::ReadBackupData() { - // Not implemented - return ResultSuccess; -} - -Result NfpDevice::WriteBackupData() { - // Not implemented - return ResultSuccess; -} - -Result NfpDevice::WriteNtf() { - if (device_state != DeviceState::TagMounted) { - LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); - if (device_state == DeviceState::TagRemoved) { - return TagRemoved; - } - return WrongDeviceState; - } - - if (mount_target == MountTarget::None || mount_target == MountTarget::Rom) { - LOG_ERROR(Service_NFC, "Amiibo is read only", device_state); - return WrongDeviceState; - } - - // Not implemented - - return ResultSuccess; -} - -u64 NfpDevice::GetHandle() const { - // Generate a handle based of the npad id - return static_cast(npad_id); -} - -u32 NfpDevice::GetApplicationAreaSize() const { - return sizeof(ApplicationArea); -} - -DeviceState NfpDevice::GetCurrentState() const { - return device_state; -} - -Core::HID::NpadIdType NfpDevice::GetNpadId() const { - return npad_id; -} - -AmiiboName NfpDevice::GetAmiiboName(const AmiiboSettings& settings) const { - std::array settings_amiibo_name{}; - AmiiboName amiibo_name{}; - - // Convert from big endian to little endian - for (std::size_t i = 0; i < amiibo_name_length; i++) { - settings_amiibo_name[i] = static_cast(settings.amiibo_name[i]); - } - - // Convert from utf16 to utf8 - const auto amiibo_name_utf8 = Common::UTF16ToUTF8(settings_amiibo_name.data()); - memcpy(amiibo_name.data(), amiibo_name_utf8.data(), amiibo_name_utf8.size()); - - return amiibo_name; -} - -void NfpDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name) { - std::array settings_amiibo_name{}; - - // Convert from utf8 to utf16 - const auto amiibo_name_utf16 = Common::UTF8ToUTF16(amiibo_name.data()); - memcpy(settings_amiibo_name.data(), amiibo_name_utf16.data(), - amiibo_name_utf16.size() * sizeof(char16_t)); - - // Convert from little endian to big endian - for (std::size_t i = 0; i < amiibo_name_length; i++) { - settings.amiibo_name[i] = static_cast(settings_amiibo_name[i]); - } -} - -AmiiboDate NfpDevice::GetAmiiboDate(s64 posix_time) const { - const auto& time_zone_manager = - system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager(); - Time::TimeZone::CalendarInfo calendar_info{}; - AmiiboDate amiibo_date{}; - - amiibo_date.SetYear(2000); - amiibo_date.SetMonth(1); - amiibo_date.SetDay(1); - - if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) { - amiibo_date.SetYear(calendar_info.time.year); - amiibo_date.SetMonth(calendar_info.time.month); - amiibo_date.SetDay(calendar_info.time.day); - } - - return amiibo_date; -} - -u64 NfpDevice::RemoveVersionByte(u64 application_id) const { - return application_id & ~(0xfULL << application_id_version_offset); -} - -void NfpDevice::UpdateSettingsCrc() { - auto& settings = tag_data.settings; - - if (settings.crc_counter != counter_limit) { - settings.crc_counter++; - } - - // TODO: this reads data from a global, find what it is - std::array unknown_input{}; - boost::crc_32_type crc; - crc.process_bytes(&unknown_input, sizeof(unknown_input)); - settings.crc = crc.checksum(); -} - -void NfpDevice::UpdateRegisterInfoCrc() { -#pragma pack(push, 1) - struct CrcData { - Mii::Ver3StoreData mii; - u8 application_id_byte; - u8 unknown; - Mii::NfpStoreDataExtension mii_extension; - std::array unknown2; - }; - static_assert(sizeof(CrcData) == 0x7e, "CrcData is an invalid size"); -#pragma pack(pop) - - const CrcData crc_data{ - .mii = tag_data.owner_mii, - .application_id_byte = tag_data.application_id_byte, - .unknown = tag_data.unknown, - .mii_extension = tag_data.mii_extension, - .unknown2 = tag_data.unknown2, - }; - - boost::crc_32_type crc; - crc.process_bytes(&crc_data, sizeof(CrcData)); - tag_data.register_info_crc = crc.checksum(); -} - -} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h deleted file mode 100755 index 2a0d9be38..000000000 --- a/src/core/hle/service/nfp/nfp_device.h +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nfp/nfp_types.h" -#include "core/hle/service/service.h" - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Core { -class System; -} // namespace Core - -namespace Core::HID { -class EmulatedController; -enum class ControllerTriggerType; -enum class NpadIdType : u32; -} // namespace Core::HID - -namespace Service::NFP { -class NfpDevice { -public: - NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, - KernelHelpers::ServiceContext& service_context_, - Kernel::KEvent* availability_change_event_); - ~NfpDevice(); - - void Initialize(); - void Finalize(); - - Result StartDetection(TagProtocol allowed_protocol); - Result StopDetection(); - Result Mount(MountTarget mount_target); - Result Unmount(); - - Result Flush(); - Result FlushDebug(); - Result FlushWithBreak(BreakType break_type); - - Result GetTagInfo(TagInfo& tag_info) const; - Result GetCommonInfo(CommonInfo& common_info) const; - Result GetModelInfo(ModelInfo& model_info) const; - Result GetRegisterInfo(RegisterInfo& register_info) const; - Result GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const; - Result GetAdminInfo(AdminInfo& admin_info) const; - - Result DeleteRegisterInfo(); - Result SetRegisterInfoPrivate(const AmiiboName& amiibo_name); - Result RestoreAmiibo(); - Result Format(); - - Result OpenApplicationArea(u32 access_id); - Result GetApplicationAreaId(u32& application_area_id) const; - Result GetApplicationArea(std::vector& data) const; - Result SetApplicationArea(std::span data); - Result CreateApplicationArea(u32 access_id, std::span data); - Result RecreateApplicationArea(u32 access_id, std::span data); - Result DeleteApplicationArea(); - Result ExistApplicationArea(bool& has_application_area); - - Result GetAll(NfpData& data) const; - Result SetAll(const NfpData& data); - Result BreakTag(BreakType break_type); - Result ReadBackupData(); - Result WriteBackupData(); - Result WriteNtf(); - - u64 GetHandle() const; - u32 GetApplicationAreaSize() const; - DeviceState GetCurrentState() const; - Core::HID::NpadIdType GetNpadId() const; - - Kernel::KReadableEvent& GetActivateEvent() const; - Kernel::KReadableEvent& GetDeactivateEvent() const; - -private: - void NpadUpdate(Core::HID::ControllerTriggerType type); - bool LoadAmiibo(std::span data); - void CloseAmiibo(); - - AmiiboName GetAmiiboName(const AmiiboSettings& settings) const; - void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name); - AmiiboDate GetAmiiboDate(s64 posix_time) const; - u64 RemoveVersionByte(u64 application_id) const; - void UpdateSettingsCrc(); - void UpdateRegisterInfoCrc(); - - bool is_controller_set{}; - int callback_key; - const Core::HID::NpadIdType npad_id; - Core::System& system; - Core::HID::EmulatedController* npad_device = nullptr; - KernelHelpers::ServiceContext& service_context; - Kernel::KEvent* activate_event = nullptr; - Kernel::KEvent* deactivate_event = nullptr; - Kernel::KEvent* availability_change_event = nullptr; - - bool is_initalized{}; - bool is_data_moddified{}; - bool is_app_area_open{}; - bool is_plain_amiibo{}; - TagProtocol allowed_protocols{}; - s64 current_posix_time{}; - MountTarget mount_target{MountTarget::None}; - DeviceState device_state{DeviceState::Unavailable}; - - NTAG215File tag_data{}; - EncryptedNTAG215File encrypted_tag_data{}; -}; - -} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp deleted file mode 100755 index 353557628..000000000 --- a/src/core/hle/service/nfp/nfp_user.cpp +++ /dev/null @@ -1,672 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nfp/nfp_device.h" -#include "core/hle/service/nfp/nfp_result.h" -#include "core/hle/service/nfp/nfp_user.h" - -namespace Service::NFP { - -IUser::IUser(Core::System& system_) - : ServiceFramework{system_, "NFP::IUser"}, service_context{system_, service_name} { - static const FunctionInfo functions[] = { - {0, &IUser::Initialize, "Initialize"}, - {1, &IUser::Finalize, "Finalize"}, - {2, &IUser::ListDevices, "ListDevices"}, - {3, &IUser::StartDetection, "StartDetection"}, - {4, &IUser::StopDetection, "StopDetection"}, - {5, &IUser::Mount, "Mount"}, - {6, &IUser::Unmount, "Unmount"}, - {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, - {8, &IUser::GetApplicationArea, "GetApplicationArea"}, - {9, &IUser::SetApplicationArea, "SetApplicationArea"}, - {10, &IUser::Flush, "Flush"}, - {11, &IUser::Restore, "Restore"}, - {12, &IUser::CreateApplicationArea, "CreateApplicationArea"}, - {13, &IUser::GetTagInfo, "GetTagInfo"}, - {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, - {15, &IUser::GetCommonInfo, "GetCommonInfo"}, - {16, &IUser::GetModelInfo, "GetModelInfo"}, - {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, - {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, - {19, &IUser::GetState, "GetState"}, - {20, &IUser::GetDeviceState, "GetDeviceState"}, - {21, &IUser::GetNpadId, "GetNpadId"}, - {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, - {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, - {24, &IUser::RecreateApplicationArea, "RecreateApplicationArea"}, - }; - RegisterHandlers(functions); - - availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent"); - - for (u32 device_index = 0; device_index < 10; device_index++) { - devices[device_index] = - std::make_shared(Core::HID::IndexToNpadIdType(device_index), system, - service_context, availability_change_event); - } -} - -IUser ::~IUser() { - availability_change_event->Close(); -} - -void IUser::Initialize(HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - state = State::Initialized; - - for (auto& device : devices) { - device->Initialize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IUser::Finalize(HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - state = State::NonInitialized; - - for (auto& device : devices) { - device->Finalize(); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IUser::ListDevices(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFP, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - if (ctx.GetWriteBufferSize() == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - std::vector nfp_devices; - const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements(); - - for (const auto& device : devices) { - if (nfp_devices.size() >= max_allowed_devices) { - continue; - } - if (device->GetCurrentState() != DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); - } - } - - if (nfp_devices.empty()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - ctx.WriteBuffer(nfp_devices); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast(nfp_devices.size())); -} - -void IUser::StartDetection(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto nfp_protocol{rp.PopEnum()}; - LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StartDetection(nfp_protocol); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::StopDetection(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->StopDetection(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Mount(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto model_type{rp.PopEnum()}; - const auto mount_target{rp.PopEnum()}; - LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle, - model_type, mount_target); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->Mount(mount_target); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Unmount(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->Unmount(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::OpenApplicationArea(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto access_id{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->OpenApplicationArea(access_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetApplicationArea(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto data_size = ctx.GetWriteBufferSize(); - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanWriteBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - std::vector data(data_size); - const auto result = device.value()->GetApplicationArea(data); - ctx.WriteBuffer(data); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(static_cast(data_size)); -} - -void IUser::SetApplicationArea(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto data{ctx.ReadBuffer()}; - LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanReadBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->SetApplicationArea(data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Flush(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->Flush(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::Restore(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->RestoreAmiibo(); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::CreateApplicationArea(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto access_id{rp.Pop()}; - const auto data{ctx.ReadBuffer()}; - LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, - access_id, data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - if (!ctx.CanReadBuffer()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InvalidArgument); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->CreateApplicationArea(access_id, data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetTagInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - TagInfo tag_info{}; - const auto result = device.value()->GetTagInfo(tag_info); - ctx.WriteBuffer(tag_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetRegisterInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - RegisterInfo register_info{}; - const auto result = device.value()->GetRegisterInfo(register_info); - ctx.WriteBuffer(register_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetCommonInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - CommonInfo common_info{}; - const auto result = device.value()->GetCommonInfo(common_info); - ctx.WriteBuffer(common_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::GetModelInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_INFO(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - ModelInfo model_info{}; - const auto result = device.value()->GetModelInfo(model_info); - ctx.WriteBuffer(model_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void IUser::AttachActivateEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetActivateEvent()); -} - -void IUser::AttachDeactivateEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device.value()->GetDeactivateEvent()); -} - -void IUser::GetState(HLERequestContext& ctx) { - LOG_DEBUG(Service_NFP, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); -} - -void IUser::GetDeviceState(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetCurrentState()); -} - -void IUser::GetNpadId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(device.value()->GetNpadId()); -} - -void IUser::GetApplicationAreaSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle); - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(device.value()->GetApplicationAreaSize()); -} - -void IUser::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { - LOG_INFO(Service_NFP, "called"); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(availability_change_event->GetReadableEvent()); -} - -void IUser::RecreateApplicationArea(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto device_handle{rp.Pop()}; - const auto access_id{rp.Pop()}; - const auto data{ctx.ReadBuffer()}; - LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle, - access_id, data.size()); - - if (state == State::NonInitialized) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(NfcDisabled); - return; - } - - auto device = GetNfpDevice(device_handle); - - if (!device.has_value()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(DeviceNotFound); - return; - } - - const auto result = device.value()->RecreateApplicationArea(access_id, data); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -std::optional> IUser::GetNfpDevice(u64 handle) { - for (auto& device : devices) { - if (device->GetHandle() == handle) { - return device; - } - } - return std::nullopt; -} - -} // namespace Service::NFP diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h deleted file mode 100755 index 762e3a9ef..000000000 --- a/src/core/hle/service/nfp/nfp_user.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::NFP { -class NfpDevice; - -class IUser final : public ServiceFramework { -public: - explicit IUser(Core::System& system_); - ~IUser(); - -private: - enum class State : u32 { - NonInitialized, - Initialized, - }; - - void Initialize(HLERequestContext& ctx); - void Finalize(HLERequestContext& ctx); - void ListDevices(HLERequestContext& ctx); - void StartDetection(HLERequestContext& ctx); - void StopDetection(HLERequestContext& ctx); - void Mount(HLERequestContext& ctx); - void Unmount(HLERequestContext& ctx); - void OpenApplicationArea(HLERequestContext& ctx); - void GetApplicationArea(HLERequestContext& ctx); - void SetApplicationArea(HLERequestContext& ctx); - void Flush(HLERequestContext& ctx); - void Restore(HLERequestContext& ctx); - void CreateApplicationArea(HLERequestContext& ctx); - void GetTagInfo(HLERequestContext& ctx); - void GetRegisterInfo(HLERequestContext& ctx); - void GetCommonInfo(HLERequestContext& ctx); - void GetModelInfo(HLERequestContext& ctx); - void AttachActivateEvent(HLERequestContext& ctx); - void AttachDeactivateEvent(HLERequestContext& ctx); - void GetState(HLERequestContext& ctx); - void GetDeviceState(HLERequestContext& ctx); - void GetNpadId(HLERequestContext& ctx); - void GetApplicationAreaSize(HLERequestContext& ctx); - void AttachAvailabilityChangeEvent(HLERequestContext& ctx); - void RecreateApplicationArea(HLERequestContext& ctx); - - std::optional> GetNfpDevice(u64 handle); - - KernelHelpers::ServiceContext service_context; - - std::array, 10> devices{}; - - State state{State::NonInitialized}; - Kernel::KEvent* availability_change_event; -}; - -} // namespace Service::NFP diff --git a/src/core/hle/service/nvflinger/binder.h b/src/core/hle/service/nvflinger/binder.h deleted file mode 100755 index fe82c1616..000000000 --- a/src/core/hle/service/nvflinger/binder.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/binder/IBinder.h - -#pragma once - -#include "common/common_types.h" - -namespace Kernel { -class HLERequestContext; -class KReadableEvent; -} // namespace Kernel - -namespace Service::android { - -enum class TransactionId { - RequestBuffer = 1, - SetBufferCount = 2, - DequeueBuffer = 3, - DetachBuffer = 4, - DetachNextBuffer = 5, - AttachBuffer = 6, - QueueBuffer = 7, - CancelBuffer = 8, - Query = 9, - Connect = 10, - Disconnect = 11, - AllocateBuffers = 13, - SetPreallocatedBuffer = 14, - GetBufferHistory = 17, -}; - -class IBinder { -public: - virtual ~IBinder() = default; - virtual void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, - u32 flags) = 0; - virtual Kernel::KReadableEvent& GetNativeHandle() = 0; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_item.h b/src/core/hle/service/nvflinger/buffer_item.h deleted file mode 100755 index 658b98594..000000000 --- a/src/core/hle/service/nvflinger/buffer_item.h +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferItem.h - -#pragma once - -#include - -#include "common/common_types.h" -#include "common/math_util.h" -#include "core/hle/service/nvflinger/ui/fence.h" -#include "core/hle/service/nvflinger/window.h" - -namespace Service::android { - -class GraphicBuffer; - -class BufferItem final { -public: - constexpr BufferItem() = default; - - std::shared_ptr graphic_buffer; - Fence fence; - Common::Rectangle crop; - NativeWindowTransform transform{}; - u32 scaling_mode{}; - s64 timestamp{}; - bool is_auto_timestamp{}; - u64 frame_number{}; - - // The default value for buf, used to indicate this doesn't correspond to a slot. - static constexpr s32 INVALID_BUFFER_SLOT = -1; - union { - s32 slot{INVALID_BUFFER_SLOT}; - s32 buf; - }; - - bool is_droppable{}; - bool acquire_called{}; - bool transform_to_display_inverse{}; - s32 swap_interval{}; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp deleted file mode 100755 index 07d3f6da7..000000000 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2012 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferItemConsumer.cpp - -#include "common/assert.h" -#include "common/logging/log.h" -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_item_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" - -namespace Service::android { - -BufferItemConsumer::BufferItemConsumer(std::unique_ptr consumer_) - : ConsumerBase{std::move(consumer_)} {} - -Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, - bool wait_for_fence) { - if (!item) { - return Status::BadValue; - } - - std::scoped_lock lock{mutex}; - - if (const auto status = AcquireBufferLocked(item, present_when); status != Status::NoError) { - if (status != Status::NoBufferAvailable) { - LOG_ERROR(Service_NVFlinger, "Failed to acquire buffer: {}", status); - } - return status; - } - - if (wait_for_fence) { - UNIMPLEMENTED(); - } - - item->graphic_buffer = slots[item->slot].graphic_buffer; - - return Status::NoError; -} - -Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, const Fence& release_fence) { - std::scoped_lock lock{mutex}; - - if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence); - status != Status::NoError) { - LOG_ERROR(Service_NVFlinger, "Failed to add fence: {}", status); - } - - if (const auto status = ReleaseBufferLocked(item.buf, item.graphic_buffer); - status != Status::NoError) { - LOG_WARNING(Service_NVFlinger, "Failed to release buffer: {}", status); - return status; - } - - return Status::NoError; -} - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.h b/src/core/hle/service/nvflinger/buffer_item_consumer.h deleted file mode 100755 index a47ae6756..000000000 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2012 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferItemConsumer.h - -#pragma once - -#include -#include - -#include "common/common_types.h" -#include "core/hle/service/nvflinger/consumer_base.h" -#include "core/hle/service/nvflinger/status.h" - -namespace Service::android { - -class BufferItem; - -class BufferItemConsumer final : public ConsumerBase { -public: - explicit BufferItemConsumer(std::unique_ptr consumer); - Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, - bool wait_for_fence = true); - Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence); -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp deleted file mode 100755 index f42382de1..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp - -#include "common/logging/log.h" -#include "core/hle/service/nvdrv/core/nvmap.h" -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/producer_listener.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" - -namespace Service::android { - -BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr core_, - Service::Nvidia::NvCore::NvMap& nvmap_) - : core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {} - -BufferQueueConsumer::~BufferQueueConsumer() = default; - -Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, - std::chrono::nanoseconds expected_present) { - std::scoped_lock lock{core->mutex}; - - // Check that the consumer doesn't currently have the maximum number of buffers acquired. - const s32 num_acquired_buffers{ - static_cast(std::count_if(slots.begin(), slots.end(), [](const auto& slot) { - return slot.buffer_state == BufferState::Acquired; - }))}; - - if (num_acquired_buffers >= core->max_acquired_buffer_count + 1) { - LOG_ERROR(Service_NVFlinger, "max acquired buffer count reached: {} (max {})", - num_acquired_buffers, core->max_acquired_buffer_count); - return Status::InvalidOperation; - } - - // Check if the queue is empty. - if (core->queue.empty()) { - return Status::NoBufferAvailable; - } - - auto front(core->queue.begin()); - - // If expected_present is specified, we may not want to return a buffer yet. - if (expected_present.count() != 0) { - constexpr auto MAX_REASONABLE_NSEC = 1000000000LL; // 1 second - - // The expected_present argument indicates when the buffer is expected to be presented - // on-screen. - while (core->queue.size() > 1 && !core->queue[0].is_auto_timestamp) { - const auto& buffer_item{core->queue[1]}; - - // If entry[1] is timely, drop entry[0] (and repeat). - const auto desired_present = buffer_item.timestamp; - if (desired_present < expected_present.count() - MAX_REASONABLE_NSEC || - desired_present > expected_present.count()) { - // This buffer is set to display in the near future, or desired_present is garbage. - LOG_DEBUG(Service_NVFlinger, "nodrop desire={} expect={}", desired_present, - expected_present.count()); - break; - } - - LOG_DEBUG(Service_NVFlinger, "drop desire={} expect={} size={}", desired_present, - expected_present.count(), core->queue.size()); - - if (core->StillTracking(*front)) { - // Front buffer is still in mSlots, so mark the slot as free - slots[front->slot].buffer_state = BufferState::Free; - } - - core->queue.erase(front); - front = core->queue.begin(); - } - - // See if the front buffer is ready to be acquired. - const auto desired_present = front->timestamp; - if (desired_present > expected_present.count() && - desired_present < expected_present.count() + MAX_REASONABLE_NSEC) { - LOG_DEBUG(Service_NVFlinger, "defer desire={} expect={}", desired_present, - expected_present.count()); - return Status::PresentLater; - } - - LOG_DEBUG(Service_NVFlinger, "accept desire={} expect={}", desired_present, - expected_present.count()); - } - - const auto slot = front->slot; - *out_buffer = *front; - - LOG_DEBUG(Service_NVFlinger, "acquiring slot={}", slot); - - // If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to - // avoid unnecessarily remapping this buffer on the consumer side. - if (out_buffer->acquire_called) { - out_buffer->graphic_buffer = nullptr; - } - - core->queue.erase(front); - - // We might have freed a slot while dropping old buffers, or the producer may be blocked - // waiting for the number of buffers in the queue to decrease. - core->SignalDequeueCondition(); - - return Status::NoError; -} - -Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence) { - if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot {} out of range", slot); - return Status::BadValue; - } - - std::shared_ptr listener; - { - std::scoped_lock lock{core->mutex}; - - // If the frame number has changed because the buffer has been reallocated, we can ignore - // this ReleaseBuffer for the old buffer. - if (frame_number != slots[slot].frame_number) { - return Status::StaleBufferSlot; - } - - // Make sure this buffer hasn't been queued while acquired by the consumer. - auto current(core->queue.begin()); - while (current != core->queue.end()) { - if (current->slot == slot) { - LOG_ERROR(Service_NVFlinger, "buffer slot {} pending release is currently queued", - slot); - return Status::BadValue; - } - ++current; - } - - slots[slot].buffer_state = BufferState::Free; - - nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true); - - listener = core->connected_producer_listener; - - LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot); - - core->SignalDequeueCondition(); - } - - // Call back without lock held - if (listener != nullptr) { - listener->OnBufferReleased(); - } - - return Status::NoError; -} - -Status BufferQueueConsumer::Connect(std::shared_ptr consumer_listener, - bool controlled_by_app) { - if (consumer_listener == nullptr) { - LOG_ERROR(Service_NVFlinger, "consumer_listener may not be nullptr"); - return Status::BadValue; - } - - LOG_DEBUG(Service_NVFlinger, "controlled_by_app={}", controlled_by_app); - - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - core->consumer_listener = std::move(consumer_listener); - core->consumer_controlled_by_app = controlled_by_app; - - return Status::NoError; -} - -Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { - if (out_slot_mask == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_slot_mask may not be nullptr"); - return Status::BadValue; - } - - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - u64 mask = 0; - for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (!slots[s].acquire_called) { - mask |= (1ULL << s); - } - } - - // Remove from the mask queued buffers for which acquire has been called, since the consumer - // will not receive their buffer addresses and so must retain their cached information - auto current(core->queue.begin()); - while (current != core->queue.end()) { - if (current->acquire_called) { - mask &= ~(1ULL << current->slot); - } - ++current; - } - - LOG_DEBUG(Service_NVFlinger, "returning mask {}", mask); - *out_slot_mask = mask; - return Status::NoError; -} - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.h b/src/core/hle/service/nvflinger/buffer_queue_consumer.h deleted file mode 100755 index cf8a9e211..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueConsumer.h - -#pragma once - -#include -#include - -#include "common/common_types.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/status.h" - -namespace Service::Nvidia::NvCore { -class NvMap; -} // namespace Service::Nvidia::NvCore - -namespace Service::android { - -class BufferItem; -class BufferQueueCore; -class IConsumerListener; - -class BufferQueueConsumer final { -public: - explicit BufferQueueConsumer(std::shared_ptr core_, - Service::Nvidia::NvCore::NvMap& nvmap_); - ~BufferQueueConsumer(); - - Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); - Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); - Status Connect(std::shared_ptr consumer_listener, bool controlled_by_app); - Status GetReleasedBuffers(u64* out_slot_mask); - -private: - std::shared_ptr core; - BufferQueueDefs::SlotsType& slots; - Service::Nvidia::NvCore::NvMap& nvmap; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp deleted file mode 100755 index d8580ff14..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueCore.cpp - -#include "common/assert.h" - -#include "core/hle/service/nvflinger/buffer_queue_core.h" - -namespace Service::android { - -BufferQueueCore::BufferQueueCore() = default; - -BufferQueueCore::~BufferQueueCore() = default; - -void BufferQueueCore::NotifyShutdown() { - std::scoped_lock lock{mutex}; - - is_shutting_down = true; - - SignalDequeueCondition(); -} - -void BufferQueueCore::SignalDequeueCondition() { - dequeue_possible.store(true); - dequeue_condition.notify_all(); -} - -bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock& lk) { - if (is_shutting_down) { - return false; - } - - dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); - dequeue_possible.store(false); - - return true; -} - -s32 BufferQueueCore::GetMinUndequeuedBufferCountLocked(bool async) const { - // If DequeueBuffer is allowed to error out, we don't have to add an extra buffer. - if (!use_async_buffer) { - return max_acquired_buffer_count; - } - - if (dequeue_buffer_cannot_block || async) { - return max_acquired_buffer_count + 1; - } - - return max_acquired_buffer_count; -} - -s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const { - return GetMinUndequeuedBufferCountLocked(async) + 1; -} - -s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const { - const auto min_buffer_count = GetMinMaxBufferCountLocked(async); - auto max_buffer_count = std::max(default_max_buffer_count, min_buffer_count); - - if (override_max_buffer_count != 0) { - ASSERT(override_max_buffer_count >= min_buffer_count); - max_buffer_count = override_max_buffer_count; - } - - // Any buffers that are dequeued by the producer or sitting in the queue waiting to be consumed - // need to have their slots preserved. - for (s32 slot = max_buffer_count; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { - const auto state = slots[slot].buffer_state; - if (state == BufferState::Queued || state == BufferState::Dequeued) { - max_buffer_count = slot + 1; - } - } - - return max_buffer_count; -} - -s32 BufferQueueCore::GetPreallocatedBufferCountLocked() const { - return static_cast(std::count_if(slots.begin(), slots.end(), - [](const auto& slot) { return slot.is_preallocated; })); -} - -void BufferQueueCore::FreeBufferLocked(s32 slot) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); - - slots[slot].graphic_buffer.reset(); - - slots[slot].buffer_state = BufferState::Free; - slots[slot].frame_number = UINT32_MAX; - slots[slot].acquire_called = false; - slots[slot].fence = Fence::NoFence(); -} - -void BufferQueueCore::FreeAllBuffersLocked() { - buffer_has_been_queued = false; - - for (s32 slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { - FreeBufferLocked(slot); - } -} - -bool BufferQueueCore::StillTracking(const BufferItem& item) const { - const BufferSlot& slot = slots[item.slot]; - - return (slot.graphic_buffer != nullptr) && (item.graphic_buffer == slot.graphic_buffer); -} - -void BufferQueueCore::WaitWhileAllocatingLocked() const { - while (is_allocating) { - is_allocating_condition.wait(mutex); - } -} - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvflinger/buffer_queue_core.h deleted file mode 100755 index 02089440f..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_core.h +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueCore.h - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/pixel_format.h" -#include "core/hle/service/nvflinger/status.h" -#include "core/hle/service/nvflinger/window.h" - -namespace Service::android { - -class IConsumerListener; -class IProducerListener; - -class BufferQueueCore final { - friend class BufferQueueProducer; - friend class BufferQueueConsumer; - -public: - static constexpr s32 INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT; - - BufferQueueCore(); - ~BufferQueueCore(); - - void NotifyShutdown(); - -private: - void SignalDequeueCondition(); - bool WaitForDequeueCondition(std::unique_lock& lk); - - s32 GetMinUndequeuedBufferCountLocked(bool async) const; - s32 GetMinMaxBufferCountLocked(bool async) const; - s32 GetMaxBufferCountLocked(bool async) const; - s32 GetPreallocatedBufferCountLocked() const; - void FreeBufferLocked(s32 slot); - void FreeAllBuffersLocked(); - bool StillTracking(const BufferItem& item) const; - void WaitWhileAllocatingLocked() const; - -private: - mutable std::mutex mutex; - bool is_abandoned{}; - bool consumer_controlled_by_app{}; - std::shared_ptr consumer_listener; - u32 consumer_usage_bit{}; - NativeWindowApi connected_api{NativeWindowApi::NoConnectedApi}; - std::shared_ptr connected_producer_listener; - BufferQueueDefs::SlotsType slots{}; - std::vector queue; - s32 override_max_buffer_count{}; - std::condition_variable dequeue_condition; - std::atomic dequeue_possible{}; - const bool use_async_buffer{}; // This is always disabled on HOS - bool dequeue_buffer_cannot_block{}; - PixelFormat default_buffer_format{PixelFormat::Rgba8888}; - u32 default_width{1}; - u32 default_height{1}; - s32 default_max_buffer_count{2}; - const s32 max_acquired_buffer_count{}; // This is always zero on HOS - bool buffer_has_been_queued{}; - u64 frame_counter{}; - u32 transform_hint{}; - bool is_allocating{}; - mutable std::condition_variable_any is_allocating_condition; - bool is_shutting_down{}; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_defs.h b/src/core/hle/service/nvflinger/buffer_queue_defs.h deleted file mode 100755 index ae079deb8..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_defs.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueDefs.h - -#pragma once - -#include - -#include "common/common_types.h" -#include "core/hle/service/nvflinger/buffer_slot.h" - -namespace Service::android::BufferQueueDefs { - -// BufferQueue will keep track of at most this value of buffers. -constexpr s32 NUM_BUFFER_SLOTS = 64; - -using SlotsType = std::array; - -} // namespace Service::android::BufferQueueDefs diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp deleted file mode 100755 index 9ae0553bc..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ /dev/null @@ -1,933 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueProducer.cpp - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/core.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvdrv/core/nvmap.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/buffer_queue_producer.h" -#include "core/hle/service/nvflinger/consumer_listener.h" -#include "core/hle/service/nvflinger/parcel.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" -#include "core/hle/service/nvflinger/window.h" -#include "core/hle/service/vi/vi.h" - -namespace Service::android { - -BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, - std::shared_ptr buffer_queue_core_, - Service::Nvidia::NvCore::NvMap& nvmap_) - : service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots), - nvmap(nvmap_) { - buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent"); -} - -BufferQueueProducer::~BufferQueueProducer() { - service_context.CloseEvent(buffer_wait_event); -} - -Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr* buf) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); - - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot, - BufferQueueDefs::NUM_BUFFER_SLOTS); - return Status::BadValue; - } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot, - slots[slot].buffer_state); - return Status::BadValue; - } - - slots[slot].request_buffer_called = true; - *buf = slots[slot].graphic_buffer; - - return Status::NoError; -} - -Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { - LOG_DEBUG(Service_NVFlinger, "count = {}", buffer_count); - - std::shared_ptr listener; - { - std::scoped_lock lock{core->mutex}; - core->WaitWhileAllocatingLocked(); - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - if (buffer_count > BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "buffer_count {} too large (max {})", buffer_count, - BufferQueueDefs::NUM_BUFFER_SLOTS); - return Status::BadValue; - } - - // There must be no dequeued buffers when changing the buffer count. - for (s32 s{}; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (slots[s].buffer_state == BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "buffer owned by producer"); - return Status::BadValue; - } - } - - if (buffer_count == 0) { - core->override_max_buffer_count = 0; - core->SignalDequeueCondition(); - return Status::NoError; - } - - const s32 min_buffer_slots = core->GetMinMaxBufferCountLocked(false); - if (buffer_count < min_buffer_slots) { - LOG_ERROR(Service_NVFlinger, "requested buffer count {} is less than minimum {}", - buffer_count, min_buffer_slots); - return Status::BadValue; - } - - // Here we are guaranteed that the producer doesn't have any dequeued buffers and will - // release all of its buffer references. - if (core->GetPreallocatedBufferCountLocked() <= 0) { - core->FreeAllBuffersLocked(); - } - - core->override_max_buffer_count = buffer_count; - core->SignalDequeueCondition(); - buffer_wait_event->Signal(); - listener = core->consumer_listener; - } - - // Call back without lock held - if (listener != nullptr) { - listener->OnBuffersReleased(); - } - - return Status::NoError; -} - -Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, - std::unique_lock& lk) const { - bool try_again = true; - - while (try_again) { - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - const s32 max_buffer_count = core->GetMaxBufferCountLocked(async); - if (async && core->override_max_buffer_count) { - if (core->override_max_buffer_count < max_buffer_count) { - LOG_ERROR(Service_NVFlinger, "async mode is invalid with buffer count override"); - return Status::BadValue; - } - } - - // Free up any buffers that are in slots beyond the max buffer count - for (s32 s = max_buffer_count; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - ASSERT(slots[s].buffer_state == BufferState::Free); - if (slots[s].graphic_buffer != nullptr) { - core->FreeBufferLocked(s); - *return_flags |= Status::ReleaseAllBuffers; - } - } - - // Look for a free buffer to give to the client - *found = BufferQueueCore::INVALID_BUFFER_SLOT; - s32 dequeued_count{}; - s32 acquired_count{}; - for (s32 s{}; s < max_buffer_count; ++s) { - switch (slots[s].buffer_state) { - case BufferState::Dequeued: - ++dequeued_count; - break; - case BufferState::Acquired: - ++acquired_count; - break; - case BufferState::Free: - // We return the oldest of the free buffers to avoid stalling the producer if - // possible, since the consumer may still have pending reads of in-flight buffers - if (*found == BufferQueueCore::INVALID_BUFFER_SLOT || - slots[s].frame_number < slots[*found].frame_number) { - *found = s; - } - break; - default: - break; - } - } - - // Producers are not allowed to dequeue more than one buffer if they did not set a buffer - // count - if (!core->override_max_buffer_count && dequeued_count) { - LOG_ERROR(Service_NVFlinger, - "can't dequeue multiple buffers without setting the buffer count"); - return Status::InvalidOperation; - } - - // See whether a buffer has been queued since the last SetBufferCount so we know whether to - // perform the min undequeued buffers check below - if (core->buffer_has_been_queued) { - // Make sure the producer is not trying to dequeue more buffers than allowed - const s32 new_undequeued_count = max_buffer_count - (dequeued_count + 1); - const s32 min_undequeued_count = core->GetMinUndequeuedBufferCountLocked(async); - if (new_undequeued_count < min_undequeued_count) { - LOG_ERROR(Service_NVFlinger, - "min undequeued buffer count({}) exceeded (dequeued={} undequeued={})", - min_undequeued_count, dequeued_count, new_undequeued_count); - return Status::InvalidOperation; - } - } - - // If we disconnect and reconnect quickly, we can be in a state where our slots are empty - // but we have many buffers in the queue. This can cause us to run out of memory if we - // outrun the consumer. Wait here if it looks like we have too many buffers queued up. - const bool too_many_buffers = core->queue.size() > static_cast(max_buffer_count); - if (too_many_buffers) { - LOG_ERROR(Service_NVFlinger, "queue size is {}, waiting", core->queue.size()); - } - - // If no buffer is found, or if the queue has too many buffers outstanding, wait for a - // buffer to be acquired or released, or for the max buffer count to change. - try_again = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) || too_many_buffers; - if (try_again) { - // Return an error if we're in non-blocking mode (producer and consumer are controlled - // by the application). - if (core->dequeue_buffer_cannot_block && - (acquired_count <= core->max_acquired_buffer_count)) { - return Status::WouldBlock; - } - - if (!core->WaitForDequeueCondition(lk)) { - // We are no longer running - return Status::NoError; - } - } - } - - return Status::NoError; -} - -Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool async, u32 width, - u32 height, PixelFormat format, u32 usage) { - LOG_DEBUG(Service_NVFlinger, "async={} w={} h={} format={}, usage={}", async ? "true" : "false", - width, height, format, usage); - - if ((width != 0 && height == 0) || (width == 0 && height != 0)) { - LOG_ERROR(Service_NVFlinger, "invalid size: w={} h={}", width, height); - return Status::BadValue; - } - - Status return_flags = Status::NoError; - bool attached_by_consumer = false; - { - std::unique_lock lock{core->mutex}; - core->WaitWhileAllocatingLocked(); - - if (format == PixelFormat::NoFormat) { - format = core->default_buffer_format; - } - - // Enable the usage bits the consumer requested - usage |= core->consumer_usage_bit; - - s32 found{}; - Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags, lock); - if (status != Status::NoError) { - return status; - } - - // This should not happen - if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { - LOG_ERROR(Service_NVFlinger, "no available buffer slots"); - return Status::Busy; - } - - *out_slot = found; - - attached_by_consumer = slots[found].attached_by_consumer; - - const bool use_default_size = !width && !height; - if (use_default_size) { - width = core->default_width; - height = core->default_height; - } - - slots[found].buffer_state = BufferState::Dequeued; - - const std::shared_ptr& buffer(slots[found].graphic_buffer); - if ((buffer == nullptr) || (buffer->Width() != width) || (buffer->Height() != height) || - (buffer->Format() != format) || ((buffer->Usage() & usage) != usage)) { - slots[found].acquire_called = false; - slots[found].graphic_buffer = nullptr; - slots[found].request_buffer_called = false; - slots[found].fence = Fence::NoFence(); - - return_flags |= Status::BufferNeedsReallocation; - } - - *out_fence = slots[found].fence; - slots[found].fence = Fence::NoFence(); - } - - if ((return_flags & Status::BufferNeedsReallocation) != Status::None) { - LOG_DEBUG(Service_NVFlinger, "allocating a new buffer for slot {}", *out_slot); - - auto graphic_buffer = std::make_shared(width, height, format, usage); - if (graphic_buffer == nullptr) { - LOG_ERROR(Service_NVFlinger, "creating GraphicBuffer failed"); - return Status::NoMemory; - } - - { - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - slots[*out_slot].frame_number = UINT32_MAX; - slots[*out_slot].graphic_buffer = graphic_buffer; - } - } - - if (attached_by_consumer) { - return_flags |= Status::BufferNeedsReallocation; - } - - LOG_DEBUG(Service_NVFlinger, "returning slot={} frame={}, flags={}", *out_slot, - slots[*out_slot].frame_number, return_flags); - - return return_flags; -} - -Status BufferQueueProducer::DetachBuffer(s32 slot) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); - - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot {} out of range [0, {})", slot, - BufferQueueDefs::NUM_BUFFER_SLOTS); - return Status::BadValue; - } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot, - slots[slot].buffer_state); - return Status::BadValue; - } else if (!slots[slot].request_buffer_called) { - LOG_ERROR(Service_NVFlinger, "buffer in slot {} has not been requested", slot); - return Status::BadValue; - } - - core->FreeBufferLocked(slot); - core->SignalDequeueCondition(); - - return Status::NoError; -} - -Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr* out_buffer, - Fence* out_fence) { - if (out_buffer == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_buffer must not be nullptr"); - return Status::BadValue; - } else if (out_fence == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_fence must not be nullptr"); - return Status::BadValue; - } - - std::scoped_lock lock{core->mutex}; - core->WaitWhileAllocatingLocked(); - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - // Find the oldest valid slot - int found = BufferQueueCore::INVALID_BUFFER_SLOT; - for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { - if (slots[s].buffer_state == BufferState::Free && slots[s].graphic_buffer != nullptr) { - if (found == BufferQueueCore::INVALID_BUFFER_SLOT || - slots[s].frame_number < slots[found].frame_number) { - found = s; - } - } - } - - if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { - return Status::NoMemory; - } - - LOG_DEBUG(Service_NVFlinger, "Detached slot {}", found); - - *out_buffer = slots[found].graphic_buffer; - *out_fence = slots[found].fence; - - core->FreeBufferLocked(found); - - return Status::NoError; -} - -Status BufferQueueProducer::AttachBuffer(s32* out_slot, - const std::shared_ptr& buffer) { - if (out_slot == nullptr) { - LOG_ERROR(Service_NVFlinger, "out_slot must not be nullptr"); - return Status::BadValue; - } else if (buffer == nullptr) { - LOG_ERROR(Service_NVFlinger, "Cannot attach nullptr buffer"); - return Status::BadValue; - } - - std::unique_lock lock{core->mutex}; - core->WaitWhileAllocatingLocked(); - - Status return_flags = Status::NoError; - s32 found{}; - - const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags, lock); - if (status != Status::NoError) { - return status; - } - - // This should not happen - if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { - LOG_ERROR(Service_NVFlinger, "No available buffer slots"); - return Status::Busy; - } - - *out_slot = found; - - LOG_DEBUG(Service_NVFlinger, "Returning slot {} flags={}", *out_slot, return_flags); - - slots[*out_slot].graphic_buffer = buffer; - slots[*out_slot].buffer_state = BufferState::Dequeued; - slots[*out_slot].fence = Fence::NoFence(); - slots[*out_slot].request_buffer_called = true; - - return return_flags; -} - -Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, - QueueBufferOutput* output) { - s64 timestamp{}; - bool is_auto_timestamp{}; - Common::Rectangle crop; - NativeWindowScalingMode scaling_mode{}; - NativeWindowTransform transform; - u32 sticky_transform_{}; - bool async{}; - s32 swap_interval{}; - Fence fence{}; - - input.Deflate(×tamp, &is_auto_timestamp, &crop, &scaling_mode, &transform, - &sticky_transform_, &async, &swap_interval, &fence); - - switch (scaling_mode) { - case NativeWindowScalingMode::Freeze: - case NativeWindowScalingMode::ScaleToWindow: - case NativeWindowScalingMode::ScaleCrop: - case NativeWindowScalingMode::NoScaleCrop: - break; - default: - LOG_ERROR(Service_NVFlinger, "unknown scaling mode {}", scaling_mode); - return Status::BadValue; - } - - std::shared_ptr frame_available_listener; - std::shared_ptr frame_replaced_listener; - s32 callback_ticket{}; - BufferItem item; - - { - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - const s32 max_buffer_count = core->GetMaxBufferCountLocked(async); - if (async && core->override_max_buffer_count) { - if (core->override_max_buffer_count < max_buffer_count) { - LOG_ERROR(Service_NVFlinger, "async mode is invalid with " - "buffer count override"); - return Status::BadValue; - } - } - - if (slot < 0 || slot >= max_buffer_count) { - LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot, - max_buffer_count); - return Status::BadValue; - } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, - "slot {} is not owned by the producer " - "(state = {})", - slot, slots[slot].buffer_state); - return Status::BadValue; - } else if (!slots[slot].request_buffer_called) { - LOG_ERROR(Service_NVFlinger, - "slot {} was queued without requesting " - "a buffer", - slot); - return Status::BadValue; - } - - LOG_DEBUG(Service_NVFlinger, - "slot={} frame={} time={} crop=[{},{},{},{}] transform={} scale={}", slot, - core->frame_counter + 1, timestamp, crop.Left(), crop.Top(), crop.Right(), - crop.Bottom(), transform, scaling_mode); - - const std::shared_ptr& graphic_buffer(slots[slot].graphic_buffer); - Common::Rectangle buffer_rect(graphic_buffer->Width(), graphic_buffer->Height()); - Common::Rectangle cropped_rect; - [[maybe_unused]] const bool unused = crop.Intersect(buffer_rect, &cropped_rect); - - if (cropped_rect != crop) { - LOG_ERROR(Service_NVFlinger, "crop rect is not contained within the buffer in slot {}", - slot); - return Status::BadValue; - } - - slots[slot].fence = fence; - slots[slot].buffer_state = BufferState::Queued; - ++core->frame_counter; - slots[slot].frame_number = core->frame_counter; - - item.acquire_called = slots[slot].acquire_called; - item.graphic_buffer = slots[slot].graphic_buffer; - item.crop = crop; - item.transform = transform & ~NativeWindowTransform::InverseDisplay; - item.transform_to_display_inverse = - (transform & NativeWindowTransform::InverseDisplay) != NativeWindowTransform::None; - item.scaling_mode = static_cast(scaling_mode); - item.timestamp = timestamp; - item.is_auto_timestamp = is_auto_timestamp; - item.frame_number = core->frame_counter; - item.slot = slot; - item.fence = fence; - item.is_droppable = core->dequeue_buffer_cannot_block || async; - item.swap_interval = swap_interval; - - nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true); - - sticky_transform = sticky_transform_; - - if (core->queue.empty()) { - // When the queue is empty, we can simply queue this buffer - core->queue.push_back(item); - frame_available_listener = core->consumer_listener; - } else { - // When the queue is not empty, we need to look at the front buffer - // state to see if we need to replace it - auto front(core->queue.begin()); - - if (front->is_droppable) { - // If the front queued buffer is still being tracked, we first - // mark it as freed - if (core->StillTracking(*front)) { - slots[front->slot].buffer_state = BufferState::Free; - // Reset the frame number of the freed buffer so that it is the first in line to - // be dequeued again - slots[front->slot].frame_number = 0; - } - // Overwrite the droppable buffer with the incoming one - *front = item; - frame_replaced_listener = core->consumer_listener; - } else { - core->queue.push_back(item); - frame_available_listener = core->consumer_listener; - } - } - - core->buffer_has_been_queued = true; - core->SignalDequeueCondition(); - output->Inflate(core->default_width, core->default_height, core->transform_hint, - static_cast(core->queue.size())); - - // Take a ticket for the callback functions - callback_ticket = next_callback_ticket++; - } - - // Don't send the GraphicBuffer through the callback, and don't send the slot number, since the - // consumer shouldn't need it - item.graphic_buffer.reset(); - item.slot = BufferItem::INVALID_BUFFER_SLOT; - - // Call back without the main BufferQueue lock held, but with the callback lock held so we can - // ensure that callbacks occur in order - { - std::scoped_lock lock{callback_mutex}; - while (callback_ticket != current_callback_ticket) { - callback_condition.wait(callback_mutex); - } - - if (frame_available_listener != nullptr) { - frame_available_listener->OnFrameAvailable(item); - } else if (frame_replaced_listener != nullptr) { - frame_replaced_listener->OnFrameReplaced(item); - } - - ++current_callback_ticket; - callback_condition.notify_all(); - } - - return Status::NoError; -} - -void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); - - std::scoped_lock lock{core->mutex}; - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return; - } - - if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot, - BufferQueueDefs::NUM_BUFFER_SLOTS); - return; - } else if (slots[slot].buffer_state != BufferState::Dequeued) { - LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot, - slots[slot].buffer_state); - return; - } - - slots[slot].buffer_state = BufferState::Free; - slots[slot].frame_number = 0; - slots[slot].fence = fence; - - core->SignalDequeueCondition(); - buffer_wait_event->Signal(); -} - -Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { - std::scoped_lock lock{core->mutex}; - - if (out_value == nullptr) { - LOG_ERROR(Service_NVFlinger, "outValue was nullptr"); - return Status::BadValue; - } - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - u32 value{}; - switch (what) { - case NativeWindow::Width: - value = core->default_width; - break; - case NativeWindow::Height: - value = core->default_height; - break; - case NativeWindow::Format: - value = static_cast(core->default_buffer_format); - break; - case NativeWindow::MinUndequeedBuffers: - value = core->GetMinUndequeuedBufferCountLocked(false); - break; - case NativeWindow::StickyTransform: - value = sticky_transform; - break; - case NativeWindow::ConsumerRunningBehind: - value = (core->queue.size() > 1); - break; - case NativeWindow::ConsumerUsageBits: - value = core->consumer_usage_bit; - break; - default: - ASSERT(false); - return Status::BadValue; - } - - LOG_DEBUG(Service_NVFlinger, "what = {}, value = {}", what, value); - - *out_value = static_cast(value); - - return Status::NoError; -} - -Status BufferQueueProducer::Connect(const std::shared_ptr& listener, - NativeWindowApi api, bool producer_controlled_by_app, - QueueBufferOutput* output) { - std::scoped_lock lock{core->mutex}; - - LOG_DEBUG(Service_NVFlinger, "api = {} producer_controlled_by_app = {}", api, - producer_controlled_by_app); - - if (core->is_abandoned) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); - return Status::NoInit; - } - - if (core->consumer_listener == nullptr) { - LOG_ERROR(Service_NVFlinger, "BufferQueue has no consumer"); - return Status::NoInit; - } - - if (output == nullptr) { - LOG_ERROR(Service_NVFlinger, "output was nullptr"); - return Status::BadValue; - } - - if (core->connected_api != NativeWindowApi::NoConnectedApi) { - LOG_ERROR(Service_NVFlinger, "already connected (cur = {} req = {})", core->connected_api, - api); - return Status::BadValue; - } - - Status status = Status::NoError; - switch (api) { - case NativeWindowApi::Egl: - case NativeWindowApi::Cpu: - case NativeWindowApi::Media: - case NativeWindowApi::Camera: - core->connected_api = api; - output->Inflate(core->default_width, core->default_height, core->transform_hint, - static_cast(core->queue.size())); - core->connected_producer_listener = listener; - break; - default: - LOG_ERROR(Service_NVFlinger, "unknown api = {}", api); - status = Status::BadValue; - break; - } - - core->buffer_has_been_queued = false; - core->dequeue_buffer_cannot_block = - core->consumer_controlled_by_app && producer_controlled_by_app; - - return status; -} - -Status BufferQueueProducer::Disconnect(NativeWindowApi api) { - LOG_DEBUG(Service_NVFlinger, "api = {}", api); - - Status status = Status::NoError; - std::shared_ptr listener; - - { - std::scoped_lock lock{core->mutex}; - - core->WaitWhileAllocatingLocked(); - - if (core->is_abandoned) { - // Disconnecting after the surface has been abandoned is a no-op. - return Status::NoError; - } - - // HACK: We are not Android. Remove handle for items in queue, and clear queue. - // Allows synchronous destruction of nvmap handles. - for (auto& item : core->queue) { - nvmap.FreeHandle(item.graphic_buffer->BufferId(), true); - } - core->queue.clear(); - - switch (api) { - case NativeWindowApi::Egl: - case NativeWindowApi::Cpu: - case NativeWindowApi::Media: - case NativeWindowApi::Camera: - if (core->connected_api == api) { - core->FreeAllBuffersLocked(); - core->connected_producer_listener = nullptr; - core->connected_api = NativeWindowApi::NoConnectedApi; - core->SignalDequeueCondition(); - buffer_wait_event->Signal(); - listener = core->consumer_listener; - } else { - LOG_ERROR(Service_NVFlinger, "still connected to another api (cur = {} req = {})", - core->connected_api, api); - status = Status::BadValue; - } - break; - default: - LOG_ERROR(Service_NVFlinger, "unknown api = {}", api); - status = Status::BadValue; - break; - } - } - - // Call back without lock held - if (listener != nullptr) { - listener->OnBuffersReleased(); - } - - return status; -} - -Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, - const std::shared_ptr& buffer) { - LOG_DEBUG(Service_NVFlinger, "slot {}", slot); - - if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - return Status::BadValue; - } - - std::scoped_lock lock{core->mutex}; - - slots[slot] = {}; - slots[slot].graphic_buffer = buffer; - slots[slot].frame_number = 0; - - // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for - // this to be called with an empty buffer, Naruto Ultimate Ninja Storm is a game that does this. - if (buffer) { - slots[slot].is_preallocated = true; - - core->override_max_buffer_count = core->GetPreallocatedBufferCountLocked(); - core->default_width = buffer->Width(); - core->default_height = buffer->Height(); - core->default_buffer_format = buffer->Format(); - } - - core->SignalDequeueCondition(); - buffer_wait_event->Signal(); - - return Status::NoError; -} - -void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) { - Status status{Status::NoError}; - InputParcel parcel_in{ctx.ReadBuffer()}; - OutputParcel parcel_out{}; - - switch (code) { - case TransactionId::Connect: { - const auto enable_listener = parcel_in.Read(); - const auto api = parcel_in.Read(); - const auto producer_controlled_by_app = parcel_in.Read(); - - UNIMPLEMENTED_IF_MSG(enable_listener, "Listener is unimplemented!"); - - std::shared_ptr listener; - QueueBufferOutput output{}; - - status = Connect(listener, api, producer_controlled_by_app, &output); - - parcel_out.Write(output); - break; - } - case TransactionId::SetPreallocatedBuffer: { - const auto slot = parcel_in.Read(); - const auto buffer = parcel_in.ReadObject(); - - status = SetPreallocatedBuffer(slot, buffer); - break; - } - case TransactionId::DequeueBuffer: { - const auto is_async = parcel_in.Read(); - const auto width = parcel_in.Read(); - const auto height = parcel_in.Read(); - const auto pixel_format = parcel_in.Read(); - const auto usage = parcel_in.Read(); - - s32 slot{}; - Fence fence{}; - - status = DequeueBuffer(&slot, &fence, is_async, width, height, pixel_format, usage); - - parcel_out.Write(slot); - parcel_out.WriteObject(&fence); - break; - } - case TransactionId::RequestBuffer: { - const auto slot = parcel_in.Read(); - - std::shared_ptr buf; - - status = RequestBuffer(slot, &buf); - - parcel_out.WriteObject(buf); - break; - } - case TransactionId::QueueBuffer: { - const auto slot = parcel_in.Read(); - - QueueBufferInput input{parcel_in}; - QueueBufferOutput output; - - status = QueueBuffer(slot, input, &output); - - parcel_out.Write(output); - break; - } - case TransactionId::Query: { - const auto what = parcel_in.Read(); - - s32 value{}; - - status = Query(what, &value); - - parcel_out.Write(value); - break; - } - case TransactionId::CancelBuffer: { - const auto slot = parcel_in.Read(); - const auto fence = parcel_in.ReadFlattened(); - - CancelBuffer(slot, fence); - break; - } - case TransactionId::Disconnect: { - const auto api = parcel_in.Read(); - - status = Disconnect(api); - break; - } - case TransactionId::DetachBuffer: { - const auto slot = parcel_in.Read(); - - status = DetachBuffer(slot); - break; - } - case TransactionId::SetBufferCount: { - const auto buffer_count = parcel_in.Read(); - - status = SetBufferCount(buffer_count); - break; - } - case TransactionId::GetBufferHistory: - LOG_WARNING(Service_NVFlinger, "(STUBBED) called, transaction=GetBufferHistory"); - break; - default: - ASSERT_MSG(false, "Unimplemented TransactionId {}", code); - break; - } - - parcel_out.Write(status); - - ctx.WriteBuffer(parcel_out.Serialize()); -} - -Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { - return buffer_wait_event->GetReadableEvent(); -} - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h deleted file mode 100755 index e99c51e1a..000000000 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.h +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueProducer.h - -#pragma once - -#include -#include -#include - -#include "common/common_funcs.h" -#include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvflinger/binder.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/buffer_slot.h" -#include "core/hle/service/nvflinger/graphic_buffer_producer.h" -#include "core/hle/service/nvflinger/pixel_format.h" -#include "core/hle/service/nvflinger/status.h" -#include "core/hle/service/nvflinger/window.h" - -namespace Kernel { -class KernelCore; -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Service::KernelHelpers { -class ServiceContext; -} // namespace Service::KernelHelpers - -namespace Service::Nvidia::NvCore { -class NvMap; -} // namespace Service::Nvidia::NvCore - -namespace Service::android { - -class BufferQueueCore; -class IProducerListener; - -class BufferQueueProducer final : public IBinder { -public: - explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, - std::shared_ptr buffer_queue_core_, - Service::Nvidia::NvCore::NvMap& nvmap_); - ~BufferQueueProducer(); - - void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override; - - Kernel::KReadableEvent& GetNativeHandle() override; - -public: - Status RequestBuffer(s32 slot, std::shared_ptr* buf); - Status SetBufferCount(s32 buffer_count); - Status DequeueBuffer(s32* out_slot, android::Fence* out_fence, bool async, u32 width, - u32 height, PixelFormat format, u32 usage); - Status DetachBuffer(s32 slot); - Status DetachNextBuffer(std::shared_ptr* out_buffer, Fence* out_fence); - Status AttachBuffer(s32* outSlot, const std::shared_ptr& buffer); - Status QueueBuffer(s32 slot, const QueueBufferInput& input, QueueBufferOutput* output); - void CancelBuffer(s32 slot, const Fence& fence); - Status Query(NativeWindow what, s32* out_value); - Status Connect(const std::shared_ptr& listener, NativeWindowApi api, - bool producer_controlled_by_app, QueueBufferOutput* output); - - Status Disconnect(NativeWindowApi api); - Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr& buffer); - -private: - BufferQueueProducer(const BufferQueueProducer&) = delete; - - Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, - std::unique_lock& lk) const; - - Kernel::KEvent* buffer_wait_event{}; - Service::KernelHelpers::ServiceContext& service_context; - - std::shared_ptr core; - BufferQueueDefs::SlotsType& slots; - u32 sticky_transform{}; - std::mutex callback_mutex; - s32 next_callback_ticket{}; - s32 current_callback_ticket{}; - std::condition_variable_any callback_condition; - - Service::Nvidia::NvCore::NvMap& nvmap; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_slot.h b/src/core/hle/service/nvflinger/buffer_slot.h deleted file mode 100755 index 8ee416be7..000000000 --- a/src/core/hle/service/nvflinger/buffer_slot.h +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferSlot.h - -#pragma once - -#include - -#include "common/common_types.h" -#include "core/hle/service/nvflinger/ui/fence.h" - -namespace Service::android { - -class GraphicBuffer; - -enum class BufferState : u32 { - Free = 0, - Dequeued = 1, - Queued = 2, - Acquired = 3, -}; - -struct BufferSlot final { - constexpr BufferSlot() = default; - - std::shared_ptr graphic_buffer; - BufferState buffer_state{BufferState::Free}; - bool request_buffer_called{}; - u64 frame_number{}; - Fence fence; - bool acquire_called{}; - bool attached_by_consumer{}; - bool is_preallocated{}; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_transform_flags.h b/src/core/hle/service/nvflinger/buffer_transform_flags.h deleted file mode 100755 index ce058cda2..000000000 --- a/src/core/hle/service/nvflinger/buffer_transform_flags.h +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" - -namespace Service::android { - -enum class BufferTransformFlags : u32 { - /// No transform flags are set - Unset = 0x00, - /// Flip source image horizontally (around the vertical axis) - FlipH = 0x01, - /// Flip source image vertically (around the horizontal axis) - FlipV = 0x02, - /// Rotate source image 90 degrees clockwise - Rotate90 = 0x04, - /// Rotate source image 180 degrees - Rotate180 = 0x03, - /// Rotate source image 270 degrees clockwise - Rotate270 = 0x07, -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvflinger/consumer_base.cpp deleted file mode 100755 index a55bae146..000000000 --- a/src/core/hle/service/nvflinger/consumer_base.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2010 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/ConsumerBase.cpp - -#include "common/assert.h" -#include "common/logging/log.h" -#include "core/hle/service/nvflinger/buffer_item.h" -#include "core/hle/service/nvflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/consumer_base.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" - -namespace Service::android { - -ConsumerBase::ConsumerBase(std::unique_ptr consumer_) - : consumer{std::move(consumer_)} {} - -ConsumerBase::~ConsumerBase() { - std::scoped_lock lock{mutex}; - - ASSERT_MSG(is_abandoned, "consumer is not abandoned!"); -} - -void ConsumerBase::Connect(bool controlled_by_app) { - consumer->Connect(shared_from_this(), controlled_by_app); -} - -void ConsumerBase::FreeBufferLocked(s32 slot_index) { - LOG_DEBUG(Service_NVFlinger, "slot_index={}", slot_index); - - slots[slot_index].graphic_buffer = nullptr; - slots[slot_index].fence = Fence::NoFence(); - slots[slot_index].frame_number = 0; -} - -void ConsumerBase::OnFrameAvailable(const BufferItem& item) { - LOG_DEBUG(Service_NVFlinger, "called"); -} - -void ConsumerBase::OnFrameReplaced(const BufferItem& item) { - LOG_DEBUG(Service_NVFlinger, "called"); -} - -void ConsumerBase::OnBuffersReleased() { - std::scoped_lock lock{mutex}; - - LOG_DEBUG(Service_NVFlinger, "called"); - - if (is_abandoned) { - // Nothing to do if we're already abandoned. - return; - } - - u64 mask = 0; - consumer->GetReleasedBuffers(&mask); - for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) { - if (mask & (1ULL << i)) { - FreeBufferLocked(i); - } - } -} - -void ConsumerBase::OnSidebandStreamChanged() {} - -Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when) { - Status err = consumer->AcquireBuffer(item, present_when); - if (err != Status::NoError) { - return err; - } - - if (item->graphic_buffer != nullptr) { - slots[item->slot].graphic_buffer = item->graphic_buffer; - } - - slots[item->slot].frame_number = item->frame_number; - slots[item->slot].fence = item->fence; - - LOG_DEBUG(Service_NVFlinger, "slot={}", item->slot); - - return Status::NoError; -} - -Status ConsumerBase::AddReleaseFenceLocked(s32 slot, - const std::shared_ptr& graphic_buffer, - const Fence& fence) { - LOG_DEBUG(Service_NVFlinger, "slot={}", slot); - - // If consumer no longer tracks this graphic_buffer, we can safely - // drop this fence, as it will never be received by the producer. - - if (!StillTracking(slot, graphic_buffer)) { - return Status::NoError; - } - - slots[slot].fence = fence; - - return Status::NoError; -} - -Status ConsumerBase::ReleaseBufferLocked(s32 slot, - const std::shared_ptr& graphic_buffer) { - // If consumer no longer tracks this graphic_buffer (we received a new - // buffer on the same slot), the buffer producer is definitely no longer - // tracking it. - - if (!StillTracking(slot, graphic_buffer)) { - return Status::NoError; - } - - LOG_DEBUG(Service_NVFlinger, "slot={}", slot); - Status err = consumer->ReleaseBuffer(slot, slots[slot].frame_number, slots[slot].fence); - if (err == Status::StaleBufferSlot) { - FreeBufferLocked(slot); - } - - slots[slot].fence = Fence::NoFence(); - - return err; -} - -bool ConsumerBase::StillTracking(s32 slot, - const std::shared_ptr& graphic_buffer) const { - if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { - return false; - } - - return (slots[slot].graphic_buffer != nullptr && - slots[slot].graphic_buffer->Handle() == graphic_buffer->Handle()); -} - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/consumer_base.h b/src/core/hle/service/nvflinger/consumer_base.h deleted file mode 100755 index df6251d9b..000000000 --- a/src/core/hle/service/nvflinger/consumer_base.h +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2010 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/ConsumerBase.h - -#pragma once - -#include -#include -#include -#include - -#include "common/common_types.h" -#include "core/hle/service/nvflinger/buffer_queue_defs.h" -#include "core/hle/service/nvflinger/consumer_listener.h" -#include "core/hle/service/nvflinger/status.h" - -namespace Service::android { - -class BufferItem; -class BufferQueueConsumer; - -class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this { -public: - void Connect(bool controlled_by_app); - -protected: - explicit ConsumerBase(std::unique_ptr consumer_); - ~ConsumerBase() override; - - void OnFrameAvailable(const BufferItem& item) override; - void OnFrameReplaced(const BufferItem& item) override; - void OnBuffersReleased() override; - void OnSidebandStreamChanged() override; - - void FreeBufferLocked(s32 slot_index); - Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); - Status ReleaseBufferLocked(s32 slot, const std::shared_ptr& graphic_buffer); - bool StillTracking(s32 slot, const std::shared_ptr& graphic_buffer) const; - Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr& graphic_buffer, - const Fence& fence); - - struct Slot final { - std::shared_ptr graphic_buffer; - Fence fence; - u64 frame_number{}; - }; - -protected: - std::array slots; - - bool is_abandoned{}; - - std::unique_ptr consumer; - - mutable std::mutex mutex; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/consumer_listener.h b/src/core/hle/service/nvflinger/consumer_listener.h deleted file mode 100755 index 1fb30350d..000000000 --- a/src/core/hle/service/nvflinger/consumer_listener.h +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/IConsumerListener.h - -#pragma once - -namespace Service::android { - -class BufferItem; - -/// ConsumerListener is the interface through which the BufferQueue notifies the consumer of events -/// that the consumer may wish to react to. -class IConsumerListener { -public: - IConsumerListener() = default; - virtual ~IConsumerListener() = default; - - virtual void OnFrameAvailable(const BufferItem& item) = 0; - virtual void OnFrameReplaced(const BufferItem& item) = 0; - virtual void OnBuffersReleased() = 0; - virtual void OnSidebandStreamChanged() = 0; -}; - -}; // namespace Service::android diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp deleted file mode 100755 index 9a9f7ec2b..000000000 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2010 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/IGraphicBufferProducer.cpp - -#include "core/hle/service/nvflinger/graphic_buffer_producer.h" -#include "core/hle/service/nvflinger/parcel.h" - -namespace Service::android { - -QueueBufferInput::QueueBufferInput(InputParcel& parcel) { - parcel.ReadFlattened(*this); -} - -QueueBufferOutput::QueueBufferOutput() = default; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.h b/src/core/hle/service/nvflinger/graphic_buffer_producer.h deleted file mode 100755 index 6ea8cb971..000000000 --- a/src/core/hle/service/nvflinger/graphic_buffer_producer.h +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2010 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/IGraphicBufferProducer.h - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/math_util.h" -#include "core/hle/service/nvflinger/ui/fence.h" -#include "core/hle/service/nvflinger/window.h" - -namespace Service::android { - -class InputParcel; - -#pragma pack(push, 1) -struct QueueBufferInput final { - explicit QueueBufferInput(InputParcel& parcel); - - void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle* crop_, - NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, - u32* sticky_transform_, bool* async_, s32* swap_interval_, Fence* fence_) const { - *timestamp_ = timestamp; - *is_auto_timestamp_ = static_cast(is_auto_timestamp); - *crop_ = crop; - *scaling_mode_ = scaling_mode; - *transform_ = transform; - *sticky_transform_ = sticky_transform; - *async_ = static_cast(async); - *swap_interval_ = swap_interval; - *fence_ = fence; - } - -private: - s64 timestamp{}; - s32 is_auto_timestamp{}; - Common::Rectangle crop{}; - NativeWindowScalingMode scaling_mode{}; - NativeWindowTransform transform{}; - u32 sticky_transform{}; - s32 async{}; - s32 swap_interval{}; - Fence fence{}; -}; -#pragma pack(pop) -static_assert(sizeof(QueueBufferInput) == 84, "QueueBufferInput has wrong size"); - -struct QueueBufferOutput final { - QueueBufferOutput(); - - void Deflate(u32* width_, u32* height_, u32* transform_hint_, u32* num_pending_buffers_) const { - *width_ = width; - *height_ = height; - *transform_hint_ = transform_hint; - *num_pending_buffers_ = num_pending_buffers; - } - - void Inflate(u32 width_, u32 height_, u32 transform_hint_, u32 num_pending_buffers_) { - width = width_; - height = height_; - transform_hint = transform_hint_; - num_pending_buffers = num_pending_buffers_; - } - -private: - u32 width{}; - u32 height{}; - u32 transform_hint{}; - u32 num_pending_buffers{}; -}; -static_assert(sizeof(QueueBufferOutput) == 16, "QueueBufferOutput has wrong size"); - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp deleted file mode 100755 index 1a7264cb2..000000000 --- a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include - -#include "common/common_types.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" - -namespace Service::NVFlinger { - -HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) - : service_context(system_, "HosBinderDriverServer") {} - -HosBinderDriverServer::~HosBinderDriverServer() {} - -u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr&& binder) { - std::scoped_lock lk{lock}; - - last_id++; - - producers[last_id] = std::move(binder); - - return last_id; -} - -android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { - std::scoped_lock lk{lock}; - - if (auto search = producers.find(id); search != producers.end()) { - return search->second.get(); - } - - return {}; -} - -} // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.h b/src/core/hle/service/nvflinger/hos_binder_driver_server.h deleted file mode 100755 index 01265295e..000000000 --- a/src/core/hle/service/nvflinger/hos_binder_driver_server.h +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include -#include -#include - -#include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvflinger/binder.h" - -namespace Core { -class System; -} - -namespace Service::NVFlinger { - -class HosBinderDriverServer final { -public: - explicit HosBinderDriverServer(Core::System& system_); - ~HosBinderDriverServer(); - - u64 RegisterProducer(std::unique_ptr&& binder); - - android::IBinder* TryGetProducer(u64 id); - -private: - KernelHelpers::ServiceContext service_context; - - std::unordered_map> producers; - std::mutex lock; - u64 last_id{}; -}; - -} // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp deleted file mode 100755 index 20c54200d..000000000 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ /dev/null @@ -1,335 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include -#include - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/microprofile.h" -#include "common/scope_exit.h" -#include "common/settings.h" -#include "common/thread.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvflinger/buffer_item_consumer.h" -#include "core/hle/service/nvflinger/buffer_queue_core.h" -#include "core/hle/service/nvflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvflinger/nvflinger.h" -#include "core/hle/service/nvflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h" -#include "core/hle/service/vi/vi_results.h" -#include "video_core/gpu.h" -#include "video_core/host1x/host1x.h" -#include "video_core/host1x/syncpoint_manager.h" - -namespace Service::NVFlinger { - -constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; - -void NVFlinger::SplitVSync(std::stop_token stop_token) { - system.RegisterHostThread(); - std::string name = "VSyncThread"; - MicroProfileOnThreadCreate(name.c_str()); - - // Cleanup - SCOPE_EXIT({ MicroProfileOnThreadExit(); }); - - Common::SetCurrentThreadName(name.c_str()); - Common::SetCurrentThreadPriority(Common::ThreadPriority::High); - - while (!stop_token.stop_requested()) { - vsync_signal.wait(false); - vsync_signal.store(false); - - guard->lock(); - - Compose(); - - guard->unlock(); - } -} - -NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_) - : system(system_), service_context(system_, "nvflinger"), - hos_binder_driver_server(hos_binder_driver_server_) { - displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system); - displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system); - displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system); - displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system); - displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system); - guard = std::make_shared(); - - // Schedule the screen composition events - multi_composition_event = Core::Timing::CreateEvent( - "ScreenComposition", - [this](std::uintptr_t, s64 time, - std::chrono::nanoseconds ns_late) -> std::optional { - vsync_signal.store(true); - vsync_signal.notify_all(); - return std::chrono::nanoseconds(GetNextTicks()); - }); - - single_composition_event = Core::Timing::CreateEvent( - "ScreenComposition", - [this](std::uintptr_t, s64 time, - std::chrono::nanoseconds ns_late) -> std::optional { - const auto lock_guard = Lock(); - Compose(); - - return std::chrono::nanoseconds(GetNextTicks()); - }); - - if (system.IsMulticore()) { - system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event); - vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); - } else { - system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event); - } -} - -NVFlinger::~NVFlinger() { - if (system.IsMulticore()) { - system.CoreTiming().UnscheduleEvent(multi_composition_event, {}); - vsync_thread.request_stop(); - vsync_signal.store(true); - vsync_signal.notify_all(); - } else { - system.CoreTiming().UnscheduleEvent(single_composition_event, {}); - } - - ShutdownLayers(); - - if (nvdrv) { - nvdrv->Close(disp_fd); - } -} - -void NVFlinger::ShutdownLayers() { - for (auto& display : displays) { - for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { - display.GetLayer(layer).Core().NotifyShutdown(); - } - } -} - -void NVFlinger::SetNVDrvInstance(std::shared_ptr instance) { - nvdrv = std::move(instance); - disp_fd = nvdrv->Open("/dev/nvdisp_disp0"); -} - -std::optional NVFlinger::OpenDisplay(std::string_view name) { - const auto lock_guard = Lock(); - - LOG_DEBUG(Service_NVFlinger, "Opening \"{}\" display", name); - - const auto itr = - std::find_if(displays.begin(), displays.end(), - [&](const VI::Display& display) { return display.GetName() == name; }); - - if (itr == displays.end()) { - return std::nullopt; - } - - return itr->GetID(); -} - -bool NVFlinger::CloseDisplay(u64 display_id) { - const auto lock_guard = Lock(); - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return false; - } - - display->Reset(); - - return true; -} - -std::optional NVFlinger::CreateLayer(u64 display_id) { - const auto lock_guard = Lock(); - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return std::nullopt; - } - - const u64 layer_id = next_layer_id++; - CreateLayerAtId(*display, layer_id); - return layer_id; -} - -void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { - const auto buffer_id = next_buffer_queue_id++; - display.CreateLayer(layer_id, buffer_id, nvdrv->container); -} - -void NVFlinger::CloseLayer(u64 layer_id) { - const auto lock_guard = Lock(); - - for (auto& display : displays) { - display.CloseLayer(layer_id); - } -} - -std::optional NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) { - const auto lock_guard = Lock(); - const auto* const layer = FindOrCreateLayer(display_id, layer_id); - - if (layer == nullptr) { - return std::nullopt; - } - - return layer->GetBinderId(); -} - -ResultVal NVFlinger::FindVsyncEvent(u64 display_id) { - const auto lock_guard = Lock(); - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return VI::ResultNotFound; - } - - return display->GetVSyncEvent(); -} - -VI::Display* NVFlinger::FindDisplay(u64 display_id) { - const auto itr = - std::find_if(displays.begin(), displays.end(), - [&](const VI::Display& display) { return display.GetID() == display_id; }); - - if (itr == displays.end()) { - return nullptr; - } - - return &*itr; -} - -const VI::Display* NVFlinger::FindDisplay(u64 display_id) const { - const auto itr = - std::find_if(displays.begin(), displays.end(), - [&](const VI::Display& display) { return display.GetID() == display_id; }); - - if (itr == displays.end()) { - return nullptr; - } - - return &*itr; -} - -VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) { - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return nullptr; - } - - return display->FindLayer(layer_id); -} - -const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { - const auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return nullptr; - } - - return display->FindLayer(layer_id); -} - -VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return nullptr; - } - - auto* layer = display->FindLayer(layer_id); - - if (layer == nullptr) { - LOG_DEBUG(Service_NVFlinger, "Layer at id {} not found. Trying to create it.", layer_id); - CreateLayerAtId(*display, layer_id); - return display->FindLayer(layer_id); - } - - return layer; -} - -void NVFlinger::Compose() { - for (auto& display : displays) { - // Trigger vsync for this display at the end of drawing - SCOPE_EXIT({ display.SignalVSyncEvent(); }); - - // Don't do anything for displays without layers. - if (!display.HasLayers()) - continue; - - // TODO(Subv): Support more than 1 layer. - VI::Layer& layer = display.GetLayer(0); - - android::BufferItem buffer{}; - const auto status = layer.GetConsumer().AcquireBuffer(&buffer, {}, false); - - if (status != android::Status::NoError) { - continue; - } - - const auto& igbp_buffer = *buffer.graphic_buffer; - - if (!system.IsPoweredOn()) { - return; // We are likely shutting down - } - - // Now send the buffer to the GPU for drawing. - // TODO(Subv): Support more than just disp0. The display device selection is probably based - // on which display we're drawing (Default, Internal, External, etc) - auto nvdisp = nvdrv->GetDevice(disp_fd); - ASSERT(nvdisp); - - guard->unlock(); - Common::Rectangle crop_rect{ - static_cast(buffer.crop.Left()), static_cast(buffer.crop.Top()), - static_cast(buffer.crop.Right()), static_cast(buffer.crop.Bottom())}; - - nvdisp->flip(igbp_buffer.BufferId(), igbp_buffer.Offset(), igbp_buffer.ExternalFormat(), - igbp_buffer.Width(), igbp_buffer.Height(), igbp_buffer.Stride(), - static_cast(buffer.transform), crop_rect, - buffer.fence.fences, buffer.fence.num_fences); - - MicroProfileFlip(); - guard->lock(); - - swap_interval = buffer.swap_interval; - - layer.GetConsumer().ReleaseBuffer(buffer, android::Fence::NoFence()); - } -} - -s64 NVFlinger::GetNextTicks() const { - const auto& settings = Settings::values; - auto speed_scale = 1.f; - if (settings.use_multi_core.GetValue()) { - if (settings.use_speed_limit.GetValue()) { - // Scales the speed based on speed_limit setting on MC. SC is handled by - // SpeedLimiter::DoSpeedLimiting. - speed_scale = 100.f / settings.speed_limit.GetValue(); - } else { - // Run at unlocked framerate. - speed_scale = 0.01f; - } - } - - // As an extension, treat nonpositive swap interval as framerate multiplier. - const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast(1 - swap_interval) - : 60.f / static_cast(swap_interval); - - return static_cast(speed_scale * (1000000000.f / effective_fps)); -} - -} // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h deleted file mode 100755 index 5e4ca42a9..000000000 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "common/common_types.h" -#include "common/polyfill_thread.h" -#include "core/hle/result.h" -#include "core/hle/service/kernel_helpers.h" - -namespace Common { -class Event; -} // namespace Common - -namespace Core::Timing { -class CoreTiming; -struct EventType; -} // namespace Core::Timing - -namespace Kernel { -class KReadableEvent; -} // namespace Kernel - -namespace Service::Nvidia { -class Module; -} // namespace Service::Nvidia - -namespace Service::VI { -class Display; -class Layer; -} // namespace Service::VI - -namespace Service::android { -class BufferQueueCore; -class BufferQueueProducer; -} // namespace Service::android - -namespace Service::NVFlinger { - -class NVFlinger final { -public: - explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); - ~NVFlinger(); - - void ShutdownLayers(); - - /// Sets the NVDrv module instance to use to send buffers to the GPU. - void SetNVDrvInstance(std::shared_ptr instance); - - /// Opens the specified display and returns the ID. - /// - /// If an invalid display name is provided, then an empty optional is returned. - [[nodiscard]] std::optional OpenDisplay(std::string_view name); - - /// Closes the specified display by its ID. - /// - /// Returns false if an invalid display ID is provided. - [[nodiscard]] bool CloseDisplay(u64 display_id); - - /// Creates a layer on the specified display and returns the layer ID. - /// - /// If an invalid display ID is specified, then an empty optional is returned. - [[nodiscard]] std::optional CreateLayer(u64 display_id); - - /// Closes a layer on all displays for the given layer ID. - void CloseLayer(u64 layer_id); - - /// Finds the buffer queue ID of the specified layer in the specified display. - /// - /// If an invalid display ID or layer ID is provided, then an empty optional is returned. - [[nodiscard]] std::optional FindBufferQueueId(u64 display_id, u64 layer_id); - - /// Gets the vsync event for the specified display. - /// - /// If an invalid display ID is provided, then VI::ResultNotFound is returned. - /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. - [[nodiscard]] ResultVal FindVsyncEvent(u64 display_id); - - /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when - /// finished. - void Compose(); - - [[nodiscard]] s64 GetNextTicks() const; - -private: - struct Layer { - std::unique_ptr core; - std::unique_ptr producer; - }; - -private: - [[nodiscard]] std::unique_lock Lock() const { - return std::unique_lock{*guard}; - } - - /// Finds the display identified by the specified ID. - [[nodiscard]] VI::Display* FindDisplay(u64 display_id); - - /// Finds the display identified by the specified ID. - [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; - - /// Finds the layer identified by the specified ID in the desired display. - [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); - - /// Finds the layer identified by the specified ID in the desired display. - [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; - - /// Finds the layer identified by the specified ID in the desired display, - /// or creates the layer if it is not found. - /// To be used when the system expects the specified ID to already exist. - [[nodiscard]] VI::Layer* FindOrCreateLayer(u64 display_id, u64 layer_id); - - /// Creates a layer with the specified layer ID in the desired display. - void CreateLayerAtId(VI::Display& display, u64 layer_id); - - void SplitVSync(std::stop_token stop_token); - - std::shared_ptr nvdrv; - s32 disp_fd; - - std::list displays; - - /// Id to use for the next layer that is created, this counter is shared among all displays. - u64 next_layer_id = 1; - /// Id to use for the next buffer queue that is created, this counter is shared among all - /// layers. - u32 next_buffer_queue_id = 1; - - s32 swap_interval = 1; - - /// Event that handles screen composition. - std::shared_ptr multi_composition_event; - std::shared_ptr single_composition_event; - - std::shared_ptr guard; - - Core::System& system; - - std::atomic vsync_signal; - - std::jthread vsync_thread; - - KernelHelpers::ServiceContext service_context; - - HosBinderDriverServer& hos_binder_driver_server; -}; - -} // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/parcel.h b/src/core/hle/service/nvflinger/parcel.h deleted file mode 100755 index 82cae203d..000000000 --- a/src/core/hle/service/nvflinger/parcel.h +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include -#include -#include - -#include "common/alignment.h" -#include "common/assert.h" -#include "common/common_types.h" - -namespace Service::android { - -struct ParcelHeader { - u32 data_size; - u32 data_offset; - u32 objects_size; - u32 objects_offset; -}; -static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size"); - -class InputParcel final { -public: - explicit InputParcel(std::span in_data) : read_buffer(std::move(in_data)) { - DeserializeHeader(); - [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); - } - - template - void Read(T& val) { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - ASSERT(read_index + sizeof(T) <= read_buffer.size()); - - std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); - read_index += sizeof(T); - read_index = Common::AlignUp(read_index, 4); - } - - template - T Read() { - T val; - Read(val); - return val; - } - - template - void ReadFlattened(T& val) { - const auto flattened_size = Read(); - ASSERT(sizeof(T) == flattened_size); - Read(val); - } - - template - T ReadFlattened() { - T val; - ReadFlattened(val); - return val; - } - - template - T ReadUnaligned() { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - ASSERT(read_index + sizeof(T) <= read_buffer.size()); - - T val; - std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); - read_index += sizeof(T); - return val; - } - - template - const std::shared_ptr ReadObject() { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - - const auto is_valid{Read()}; - - if (is_valid) { - auto result = std::make_shared(); - ReadFlattened(*result); - return result; - } - - return {}; - } - - std::u16string ReadInterfaceToken() { - [[maybe_unused]] const u32 unknown = Read(); - const u32 length = Read(); - - std::u16string token; - token.reserve(length + 1); - - for (u32 ch = 0; ch < length + 1; ++ch) { - token.push_back(ReadUnaligned()); - } - - read_index = Common::AlignUp(read_index, 4); - - return token; - } - - void DeserializeHeader() { - ASSERT(read_buffer.size() > sizeof(ParcelHeader)); - - ParcelHeader header{}; - std::memcpy(&header, read_buffer.data(), sizeof(ParcelHeader)); - - read_index = header.data_offset; - } - -private: - std::span read_buffer; - std::size_t read_index = 0; -}; - -class OutputParcel final { -public: - static constexpr std::size_t DefaultBufferSize = 0x40; - - OutputParcel() : buffer(DefaultBufferSize) {} - - template - explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) { - Write(out_data); - } - - template - void Write(const T& val) { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - - if (buffer.size() < write_index + sizeof(T)) { - buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize); - } - - std::memcpy(buffer.data() + write_index, &val, sizeof(T)); - write_index += sizeof(T); - write_index = Common::AlignUp(write_index, 4); - } - - template - void WriteObject(const T* ptr) { - static_assert(std::is_trivially_copyable_v, "T must be trivially copyable."); - - if (!ptr) { - Write(0); - return; - } - - Write(1); - Write(sizeof(T)); - Write(*ptr); - } - - template - void WriteObject(const std::shared_ptr ptr) { - WriteObject(ptr.get()); - } - - std::vector Serialize() const { - ParcelHeader header{}; - header.data_size = static_cast(write_index - sizeof(ParcelHeader)); - header.data_offset = sizeof(ParcelHeader); - header.objects_size = 4; - header.objects_offset = static_cast(sizeof(ParcelHeader) + header.data_size); - std::memcpy(buffer.data(), &header, sizeof(ParcelHeader)); - - return buffer; - } - -private: - mutable std::vector buffer; - std::size_t write_index = sizeof(ParcelHeader); -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/pixel_format.h b/src/core/hle/service/nvflinger/pixel_format.h deleted file mode 100755 index bd5fdc998..000000000 --- a/src/core/hle/service/nvflinger/pixel_format.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" - -namespace Service::android { - -enum class PixelFormat : u32 { - NoFormat = 0, - Rgba8888 = 1, - Rgbx8888 = 2, - Rgb888 = 3, - Rgb565 = 4, - Bgra8888 = 5, - Rgba5551 = 6, - Rgba4444 = 7, -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/producer_listener.h b/src/core/hle/service/nvflinger/producer_listener.h deleted file mode 100755 index 449b859a2..000000000 --- a/src/core/hle/service/nvflinger/producer_listener.h +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/IProducerListener.h - -#pragma once - -namespace Service::android { - -class IProducerListener { -public: - virtual ~IProducerListener() = default; - virtual void OnBufferReleased() = 0; -}; - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/status.h b/src/core/hle/service/nvflinger/status.h deleted file mode 100755 index 9014a71de..000000000 --- a/src/core/hle/service/nvflinger/status.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" - -namespace Service::android { - -enum class Status : s32 { - None = 0, - NoError = 0, - StaleBufferSlot = 1, - NoBufferAvailable = 2, - PresentLater = 3, - WouldBlock = -11, - NoMemory = -12, - Busy = -16, - NoInit = -19, - BadValue = -22, - InvalidOperation = -37, - BufferNeedsReallocation = 1, - ReleaseAllBuffers = 2, -}; -DECLARE_ENUM_FLAG_OPERATORS(Status); - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/ui/fence.h b/src/core/hle/service/nvflinger/ui/fence.h deleted file mode 100755 index 38b1d1d9a..000000000 --- a/src/core/hle/service/nvflinger/ui/fence.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2012 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/ui/Fence.h - -#pragma once - -#include - -#include "common/common_types.h" -#include "core/hle/service/nvdrv/nvdata.h" - -namespace Service::android { - -class Fence { -public: - constexpr Fence() = default; - - static constexpr Fence NoFence() { - Fence fence; - fence.fences[0].id = -1; - return fence; - } - -public: - u32 num_fences{}; - std::array fences{}; -}; -static_assert(sizeof(Fence) == 36, "Fence has wrong size"); - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/ui/graphic_buffer.h b/src/core/hle/service/nvflinger/ui/graphic_buffer.h deleted file mode 100755 index 91f558ec8..000000000 --- a/src/core/hle/service/nvflinger/ui/graphic_buffer.h +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2007 The Android Open Source Project -// SPDX-License-Identifier: GPL-3.0-or-later -// Parts of this implementation were based on: -// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/ui/GraphicBuffer.h - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hle/service/nvflinger/pixel_format.h" - -namespace Service::android { - -class GraphicBuffer final { -public: - constexpr GraphicBuffer() = default; - - constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) - : width{static_cast(width_)}, height{static_cast(height_)}, format{format_}, - usage{static_cast(usage_)} {} - - constexpr u32 Width() const { - return static_cast(width); - } - - constexpr u32 Height() const { - return static_cast(height); - } - - constexpr u32 Stride() const { - return static_cast(stride); - } - - constexpr u32 Usage() const { - return static_cast(usage); - } - - constexpr PixelFormat Format() const { - return format; - } - - constexpr u32 BufferId() const { - return buffer_id; - } - - constexpr PixelFormat ExternalFormat() const { - return external_format; - } - - constexpr u32 Handle() const { - return handle; - } - - constexpr u32 Offset() const { - return offset; - } - - constexpr bool NeedsReallocation(u32 width_, u32 height_, PixelFormat format_, - u32 usage_) const { - if (static_cast(width_) != width) { - return true; - } - - if (static_cast(height_) != height) { - return true; - } - - if (format_ != format) { - return true; - } - - if ((static_cast(usage) & usage_) != usage_) { - return true; - } - - return false; - } - -private: - u32 magic{}; - s32 width{}; - s32 height{}; - s32 stride{}; - PixelFormat format{}; - s32 usage{}; - INSERT_PADDING_WORDS(1); - u32 index{}; - INSERT_PADDING_WORDS(3); - u32 buffer_id{}; - INSERT_PADDING_WORDS(6); - PixelFormat external_format{}; - INSERT_PADDING_WORDS(10); - u32 handle{}; - u32 offset{}; - INSERT_PADDING_WORDS(60); -}; -static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size"); - -} // namespace Service::android diff --git a/src/core/hle/service/nvflinger/window.h b/src/core/hle/service/nvflinger/window.h deleted file mode 100755 index b230103d6..000000000 --- a/src/core/hle/service/nvflinger/window.h +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" - -namespace Service::android { - -/// Attributes queryable with Query -enum class NativeWindow : s32 { - Width = 0, - Height = 1, - Format = 2, - MinUndequeedBuffers = 3, - QueuesToWindowComposer = 4, - ConcreteType = 5, - DefaultWidth = 6, - DefaultHeight = 7, - TransformHint = 8, - ConsumerRunningBehind = 9, - ConsumerUsageBits = 10, - StickyTransform = 11, - DefaultDataSpace = 12, - BufferAge = 13, -}; - -/// Parameter for Connect/Disconnect -enum class NativeWindowApi : s32 { - NoConnectedApi = 0, - Egl = 1, - Cpu = 2, - Media = 3, - Camera = 4, -}; - -/// Scaling mode parameter for QueueBuffer -enum class NativeWindowScalingMode : s32 { - Freeze = 0, - ScaleToWindow = 1, - ScaleCrop = 2, - NoScaleCrop = 3, -}; - -/// Transform parameter for QueueBuffer -enum class NativeWindowTransform : u32 { - None = 0x0, - InverseDisplay = 0x08, -}; -DECLARE_ENUM_FLAG_OPERATORS(NativeWindowTransform); - -} // namespace Service::android diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp deleted file mode 100755 index 040274121..000000000 --- a/src/core/hle/service/sockets/ethc.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/sockets/ethc.h" - -namespace Service::Sockets { - -ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {1, nullptr, "Cancel"}, - {2, nullptr, "GetResult"}, - {3, nullptr, "GetMediaList"}, - {4, nullptr, "SetMediaType"}, - {5, nullptr, "GetMediaType"}, - {6, nullptr, "Unknown6"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ETHC_C::~ETHC_C() = default; - -ETHC_I::ETHC_I(Core::System& system_) : ServiceFramework{system_, "ethc:i"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetReadableHandle"}, - {1, nullptr, "Cancel"}, - {2, nullptr, "GetResult"}, - {3, nullptr, "GetInterfaceList"}, - {4, nullptr, "GetInterfaceCount"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ETHC_I::~ETHC_I() = default; - -} // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h deleted file mode 100755 index 693e88289..000000000 --- a/src/core/hle/service/sockets/ethc.h +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Sockets { - -class ETHC_C final : public ServiceFramework { -public: - explicit ETHC_C(Core::System& system_); - ~ETHC_C() override; -}; - -class ETHC_I final : public ServiceFramework { -public: - explicit ETHC_I(Core::System& system_); - ~ETHC_I() override; -}; - -} // namespace Service::Sockets diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp deleted file mode 100755 index c64a03cac..000000000 --- a/src/core/hle/service/wlan/wlan.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" -#include "core/hle/service/wlan/wlan.h" - -namespace Service::WLAN { - -class WLANInfra final : public ServiceFramework { -public: - explicit WLANInfra(Core::System& system_) : ServiceFramework{system_, "wlan:inf"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "OpenMode"}, - {1, nullptr, "CloseMode"}, - {2, nullptr, "GetMacAddress"}, - {3, nullptr, "StartScan"}, - {4, nullptr, "StopScan"}, - {5, nullptr, "Connect"}, - {6, nullptr, "CancelConnect"}, - {7, nullptr, "Disconnect"}, - {8, nullptr, "GetConnectionEvent"}, - {9, nullptr, "GetConnectionStatus"}, - {10, nullptr, "GetState"}, - {11, nullptr, "GetScanResult"}, - {12, nullptr, "GetRssi"}, - {13, nullptr, "ChangeRxAntenna"}, - {14, nullptr, "GetFwVersion"}, - {15, nullptr, "RequestSleep"}, - {16, nullptr, "RequestWakeUp"}, - {17, nullptr, "RequestIfUpDown"}, - {18, nullptr, "Unknown18"}, - {19, nullptr, "Unknown19"}, - {20, nullptr, "Unknown20"}, - {21, nullptr, "Unknown21"}, - {22, nullptr, "Unknown22"}, - {23, nullptr, "Unknown23"}, - {24, nullptr, "Unknown24"}, - {25, nullptr, "Unknown25"}, - {26, nullptr, "Unknown26"}, - {27, nullptr, "Unknown27"}, - {28, nullptr, "Unknown28"}, - {29, nullptr, "Unknown29"}, - {30, nullptr, "Unknown30"}, - {31, nullptr, "Unknown31"}, - {32, nullptr, "Unknown32"}, - {33, nullptr, "Unknown33"}, - {34, nullptr, "Unknown34"}, - {35, nullptr, "Unknown35"}, - {36, nullptr, "Unknown36"}, - {37, nullptr, "Unknown37"}, - {38, nullptr, "Unknown38"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANLocal final : public ServiceFramework { -public: - explicit WLANLocal(Core::System& system_) : ServiceFramework{system_, "wlan:lcl"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown0"}, - {1, nullptr, "Unknown1"}, - {2, nullptr, "Unknown2"}, - {3, nullptr, "Unknown3"}, - {4, nullptr, "Unknown4"}, - {5, nullptr, "Unknown5"}, - {6, nullptr, "GetMacAddress"}, - {7, nullptr, "CreateBss"}, - {8, nullptr, "DestroyBss"}, - {9, nullptr, "StartScan"}, - {10, nullptr, "StopScan"}, - {11, nullptr, "Connect"}, - {12, nullptr, "CancelConnect"}, - {13, nullptr, "Join"}, - {14, nullptr, "CancelJoin"}, - {15, nullptr, "Disconnect"}, - {16, nullptr, "SetBeaconLostCount"}, - {17, nullptr, "Unknown17"}, - {18, nullptr, "Unknown18"}, - {19, nullptr, "Unknown19"}, - {20, nullptr, "GetBssIndicationEvent"}, - {21, nullptr, "GetBssIndicationInfo"}, - {22, nullptr, "GetState"}, - {23, nullptr, "GetAllowedChannels"}, - {24, nullptr, "AddIe"}, - {25, nullptr, "DeleteIe"}, - {26, nullptr, "Unknown26"}, - {27, nullptr, "Unknown27"}, - {28, nullptr, "CreateRxEntry"}, - {29, nullptr, "DeleteRxEntry"}, - {30, nullptr, "Unknown30"}, - {31, nullptr, "Unknown31"}, - {32, nullptr, "AddMatchingDataToRxEntry"}, - {33, nullptr, "RemoveMatchingDataFromRxEntry"}, - {34, nullptr, "GetScanResult"}, - {35, nullptr, "Unknown35"}, - {36, nullptr, "SetActionFrameWithBeacon"}, - {37, nullptr, "CancelActionFrameWithBeacon"}, - {38, nullptr, "CreateRxEntryForActionFrame"}, - {39, nullptr, "DeleteRxEntryForActionFrame"}, - {40, nullptr, "Unknown40"}, - {41, nullptr, "Unknown41"}, - {42, nullptr, "CancelGetActionFrame"}, - {43, nullptr, "GetRssi"}, - {44, nullptr, "Unknown44"}, - {45, nullptr, "Unknown45"}, - {46, nullptr, "Unknown46"}, - {47, nullptr, "Unknown47"}, - {48, nullptr, "Unknown48"}, - {49, nullptr, "Unknown49"}, - {50, nullptr, "Unknown50"}, - {51, nullptr, "Unknown51"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANLocalGetFrame final : public ServiceFramework { -public: - explicit WLANLocalGetFrame(Core::System& system_) : ServiceFramework{system_, "wlan:lg"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANSocketGetFrame final : public ServiceFramework { -public: - explicit WLANSocketGetFrame(Core::System& system_) : ServiceFramework{system_, "wlan:sg"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class WLANSocketManager final : public ServiceFramework { -public: - explicit WLANSocketManager(Core::System& system_) : ServiceFramework{system_, "wlan:soc"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Unknown0"}, - {1, nullptr, "Unknown1"}, - {2, nullptr, "Unknown2"}, - {3, nullptr, "Unknown3"}, - {4, nullptr, "Unknown4"}, - {5, nullptr, "Unknown5"}, - {6, nullptr, "GetMacAddress"}, - {7, nullptr, "SwitchTsfTimerFunction"}, - {8, nullptr, "Unknown8"}, - {9, nullptr, "Unknown9"}, - {10, nullptr, "Unknown10"}, - {11, nullptr, "Unknown11"}, - {12, nullptr, "Unknown12"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared(system)->InstallAsService(sm); - std::make_shared(system)->InstallAsService(sm); - std::make_shared(system)->InstallAsService(sm); - std::make_shared(system)->InstallAsService(sm); - std::make_shared(system)->InstallAsService(sm); -} - -} // namespace Service::WLAN diff --git a/src/core/hle/service/wlan/wlan.h b/src/core/hle/service/wlan/wlan.h deleted file mode 100755 index 1f02ef637..000000000 --- a/src/core/hle/service/wlan/wlan.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace Core { -class System; -} - -namespace Service::SM { -class ServiceManager; -} - -namespace Service::WLAN { - -void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); - -} // namespace Service::WLAN diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp deleted file mode 100755 index 5fb0b64d1..000000000 --- a/src/tests/tests.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#define CATCH_CONFIG_MAIN -#include - -// Catch provides the main function since we've given it the -// CATCH_CONFIG_MAIN preprocessor directive. diff --git a/src/tests/video_core/buffer_base.cpp b/src/tests/video_core/buffer_base.cpp deleted file mode 100755 index 305af8f25..000000000 --- a/src/tests/video_core/buffer_base.cpp +++ /dev/null @@ -1,549 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include - -#include - -#include "common/alignment.h" -#include "common/common_types.h" -#include "video_core/buffer_cache/buffer_base.h" - -namespace { -using VideoCommon::BufferBase; -using Range = std::pair; - -constexpr u64 PAGE = 4096; -constexpr u64 WORD = 4096 * 64; - -constexpr VAddr c = 0x1328914000; - -class RasterizerInterface { -public: - void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { - const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS}; - const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >> - Core::Memory::YUZU_PAGEBITS}; - for (u64 page = page_start; page < page_end; ++page) { - int& value = page_table[page]; - value += delta; - if (value < 0) { - throw std::logic_error{"negative page"}; - } - if (value == 0) { - page_table.erase(page); - } - } - } - - [[nodiscard]] int Count(VAddr addr) const noexcept { - const auto it = page_table.find(addr >> Core::Memory::YUZU_PAGEBITS); - return it == page_table.end() ? 0 : it->second; - } - - [[nodiscard]] unsigned Count() const noexcept { - unsigned count = 0; - for (const auto& [index, value] : page_table) { - count += value; - } - return count; - } - -private: - std::unordered_map page_table; -}; -} // Anonymous namespace - -TEST_CASE("BufferBase: Small buffer", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - REQUIRE(rasterizer.Count() == 0); - buffer.UnmarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == WORD / PAGE); - REQUIRE(buffer.ModifiedCpuRegion(c, WORD) == Range{0, 0}); - - buffer.MarkRegionAsCpuModified(c + PAGE, 1); - REQUIRE(buffer.ModifiedCpuRegion(c, WORD) == Range{PAGE * 1, PAGE * 2}); -} - -TEST_CASE("BufferBase: Large buffer", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 32); - buffer.UnmarkRegionAsCpuModified(c, WORD * 32); - buffer.MarkRegionAsCpuModified(c + 4096, WORD * 4); - REQUIRE(buffer.ModifiedCpuRegion(c, WORD + PAGE * 2) == Range{PAGE, WORD + PAGE * 2}); - REQUIRE(buffer.ModifiedCpuRegion(c + PAGE * 2, PAGE * 6) == Range{PAGE * 2, PAGE * 8}); - REQUIRE(buffer.ModifiedCpuRegion(c, WORD * 32) == Range{PAGE, WORD * 4 + PAGE}); - REQUIRE(buffer.ModifiedCpuRegion(c + WORD * 4, PAGE) == Range{WORD * 4, WORD * 4 + PAGE}); - REQUIRE(buffer.ModifiedCpuRegion(c + WORD * 3 + PAGE * 63, PAGE) == - Range{WORD * 3 + PAGE * 63, WORD * 4}); - - buffer.MarkRegionAsCpuModified(c + WORD * 5 + PAGE * 6, PAGE); - buffer.MarkRegionAsCpuModified(c + WORD * 5 + PAGE * 8, PAGE); - REQUIRE(buffer.ModifiedCpuRegion(c + WORD * 5, WORD) == - Range{WORD * 5 + PAGE * 6, WORD * 5 + PAGE * 9}); - - buffer.UnmarkRegionAsCpuModified(c + WORD * 5 + PAGE * 8, PAGE); - REQUIRE(buffer.ModifiedCpuRegion(c + WORD * 5, WORD) == - Range{WORD * 5 + PAGE * 6, WORD * 5 + PAGE * 7}); - - buffer.MarkRegionAsCpuModified(c + PAGE, WORD * 31 + PAGE * 63); - REQUIRE(buffer.ModifiedCpuRegion(c, WORD * 32) == Range{PAGE, WORD * 32}); - - buffer.UnmarkRegionAsCpuModified(c + PAGE * 4, PAGE); - buffer.UnmarkRegionAsCpuModified(c + PAGE * 6, PAGE); - - buffer.UnmarkRegionAsCpuModified(c, WORD * 32); - REQUIRE(buffer.ModifiedCpuRegion(c, WORD * 32) == Range{0, 0}); -} - -TEST_CASE("BufferBase: Rasterizer counting", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, PAGE * 2); - REQUIRE(rasterizer.Count() == 0); - buffer.UnmarkRegionAsCpuModified(c, PAGE); - REQUIRE(rasterizer.Count() == 1); - buffer.MarkRegionAsCpuModified(c, PAGE * 2); - REQUIRE(rasterizer.Count() == 0); - buffer.UnmarkRegionAsCpuModified(c, PAGE); - buffer.UnmarkRegionAsCpuModified(c + PAGE, PAGE); - REQUIRE(rasterizer.Count() == 2); - buffer.MarkRegionAsCpuModified(c, PAGE * 2); - REQUIRE(rasterizer.Count() == 0); -} - -TEST_CASE("BufferBase: Basic range", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.MarkRegionAsCpuModified(c, PAGE); - int num = 0; - buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { - REQUIRE(offset == 0U); - REQUIRE(size == PAGE); - ++num; - }); - REQUIRE(num == 1U); -} - -TEST_CASE("BufferBase: Border upload", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 2); - buffer.UnmarkRegionAsCpuModified(c, WORD * 2); - buffer.MarkRegionAsCpuModified(c + WORD - PAGE, PAGE * 2); - buffer.ForEachUploadRange(c, WORD * 2, [](u64 offset, u64 size) { - REQUIRE(offset == WORD - PAGE); - REQUIRE(size == PAGE * 2); - }); -} - -TEST_CASE("BufferBase: Border upload range", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 2); - buffer.UnmarkRegionAsCpuModified(c, WORD * 2); - buffer.MarkRegionAsCpuModified(c + WORD - PAGE, PAGE * 2); - buffer.ForEachUploadRange(c + WORD - PAGE, PAGE * 2, [](u64 offset, u64 size) { - REQUIRE(offset == WORD - PAGE); - REQUIRE(size == PAGE * 2); - }); - buffer.MarkRegionAsCpuModified(c + WORD - PAGE, PAGE * 2); - buffer.ForEachUploadRange(c + WORD - PAGE, PAGE, [](u64 offset, u64 size) { - REQUIRE(offset == WORD - PAGE); - REQUIRE(size == PAGE); - }); - buffer.ForEachUploadRange(c + WORD, PAGE, [](u64 offset, u64 size) { - REQUIRE(offset == WORD); - REQUIRE(size == PAGE); - }); -} - -TEST_CASE("BufferBase: Border upload partial range", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 2); - buffer.UnmarkRegionAsCpuModified(c, WORD * 2); - buffer.MarkRegionAsCpuModified(c + WORD - PAGE, PAGE * 2); - buffer.ForEachUploadRange(c + WORD - 1, 2, [](u64 offset, u64 size) { - REQUIRE(offset == WORD - PAGE); - REQUIRE(size == PAGE * 2); - }); - buffer.MarkRegionAsCpuModified(c + WORD - PAGE, PAGE * 2); - buffer.ForEachUploadRange(c + WORD - 1, 1, [](u64 offset, u64 size) { - REQUIRE(offset == WORD - PAGE); - REQUIRE(size == PAGE); - }); - buffer.ForEachUploadRange(c + WORD + 50, 1, [](u64 offset, u64 size) { - REQUIRE(offset == WORD); - REQUIRE(size == PAGE); - }); -} - -TEST_CASE("BufferBase: Partial word uploads", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, 0x9d000); - int num = 0; - buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { - REQUIRE(offset == 0U); - REQUIRE(size == WORD); - ++num; - }); - REQUIRE(num == 1); - buffer.ForEachUploadRange(c + WORD, WORD, [&](u64 offset, u64 size) { - REQUIRE(offset == WORD); - REQUIRE(size == WORD); - ++num; - }); - REQUIRE(num == 2); - buffer.ForEachUploadRange(c + 0x79000, 0x24000, [&](u64 offset, u64 size) { - REQUIRE(offset == WORD * 2); - REQUIRE(size == PAGE * 0x1d); - ++num; - }); - REQUIRE(num == 3); -} - -TEST_CASE("BufferBase: Partial page upload", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - int num = 0; - buffer.MarkRegionAsCpuModified(c + PAGE * 2, PAGE); - buffer.MarkRegionAsCpuModified(c + PAGE * 9, PAGE); - buffer.ForEachUploadRange(c, PAGE * 3, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 2); - REQUIRE(size == PAGE); - ++num; - }); - REQUIRE(num == 1); - buffer.ForEachUploadRange(c + PAGE * 7, PAGE * 3, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 9); - REQUIRE(size == PAGE); - ++num; - }); - REQUIRE(num == 2); -} - -TEST_CASE("BufferBase: Partial page upload with multiple words on the right") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 8); - buffer.UnmarkRegionAsCpuModified(c, WORD * 8); - buffer.MarkRegionAsCpuModified(c + PAGE * 13, WORD * 7); - int num = 0; - buffer.ForEachUploadRange(c + PAGE * 10, WORD * 7, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 13); - REQUIRE(size == WORD * 7 - PAGE * 3); - ++num; - }); - REQUIRE(num == 1); - buffer.ForEachUploadRange(c + PAGE, WORD * 8, [&](u64 offset, u64 size) { - REQUIRE(offset == WORD * 7 + PAGE * 10); - REQUIRE(size == PAGE * 3); - ++num; - }); - REQUIRE(num == 2); -} - -TEST_CASE("BufferBase: Partial page upload with multiple words on the left", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 8); - buffer.UnmarkRegionAsCpuModified(c, WORD * 8); - buffer.MarkRegionAsCpuModified(c + PAGE * 13, WORD * 7); - int num = 0; - buffer.ForEachUploadRange(c + PAGE * 16, WORD * 7, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 16); - REQUIRE(size == WORD * 7 - PAGE * 3); - ++num; - }); - REQUIRE(num == 1); - buffer.ForEachUploadRange(c + PAGE, WORD, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 13); - REQUIRE(size == PAGE * 3); - ++num; - }); - REQUIRE(num == 2); -} - -TEST_CASE("BufferBase: Partial page upload with multiple words in the middle", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 8); - buffer.UnmarkRegionAsCpuModified(c, WORD * 8); - buffer.MarkRegionAsCpuModified(c + PAGE * 13, PAGE * 140); - int num = 0; - buffer.ForEachUploadRange(c + PAGE * 16, WORD, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 16); - REQUIRE(size == WORD); - ++num; - }); - REQUIRE(num == 1); - buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { - REQUIRE(offset == PAGE * 13); - REQUIRE(size == PAGE * 3); - ++num; - }); - REQUIRE(num == 2); - buffer.ForEachUploadRange(c, WORD * 8, [&](u64 offset, u64 size) { - REQUIRE(offset == WORD + PAGE * 16); - REQUIRE(size == PAGE * 73); - ++num; - }); - REQUIRE(num == 3); -} - -TEST_CASE("BufferBase: Empty right bits", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 2048); - buffer.UnmarkRegionAsCpuModified(c, WORD * 2048); - buffer.MarkRegionAsCpuModified(c + WORD - PAGE, PAGE * 2); - buffer.ForEachUploadRange(c, WORD * 2048, [](u64 offset, u64 size) { - REQUIRE(offset == WORD - PAGE); - REQUIRE(size == PAGE * 2); - }); -} - -TEST_CASE("BufferBase: Out of bound ranges 1", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.MarkRegionAsCpuModified(c, PAGE); - int num = 0; - buffer.ForEachUploadRange(c - WORD, WORD, [&](u64 offset, u64 size) { ++num; }); - buffer.ForEachUploadRange(c + WORD, WORD, [&](u64 offset, u64 size) { ++num; }); - buffer.ForEachUploadRange(c - PAGE, PAGE, [&](u64 offset, u64 size) { ++num; }); - REQUIRE(num == 0); - buffer.ForEachUploadRange(c - PAGE, PAGE * 2, [&](u64 offset, u64 size) { ++num; }); - REQUIRE(num == 1); - buffer.MarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 0); -} - -TEST_CASE("BufferBase: Out of bound ranges 2", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, 0x22000); - REQUIRE_NOTHROW(buffer.UnmarkRegionAsCpuModified(c + 0x22000, PAGE)); - REQUIRE_NOTHROW(buffer.UnmarkRegionAsCpuModified(c + 0x28000, PAGE)); - REQUIRE(rasterizer.Count() == 0); - REQUIRE_NOTHROW(buffer.UnmarkRegionAsCpuModified(c + 0x21100, PAGE - 0x100)); - REQUIRE(rasterizer.Count() == 1); - REQUIRE_NOTHROW(buffer.UnmarkRegionAsCpuModified(c - 0x1000, PAGE * 2)); - buffer.UnmarkRegionAsCpuModified(c - 0x3000, PAGE * 2); - buffer.UnmarkRegionAsCpuModified(c - 0x2000, PAGE * 2); - REQUIRE(rasterizer.Count() == 2); -} - -TEST_CASE("BufferBase: Out of bound ranges 3", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, 0x310720); - buffer.UnmarkRegionAsCpuModified(c, 0x310720); - REQUIRE(rasterizer.Count(c) == 1); - REQUIRE(rasterizer.Count(c + PAGE) == 1); - REQUIRE(rasterizer.Count(c + WORD) == 1); - REQUIRE(rasterizer.Count(c + WORD + PAGE) == 1); -} - -TEST_CASE("BufferBase: Sparse regions 1", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.MarkRegionAsCpuModified(c + PAGE * 1, PAGE); - buffer.MarkRegionAsCpuModified(c + PAGE * 3, PAGE * 4); - buffer.ForEachUploadRange(c, WORD, [i = 0](u64 offset, u64 size) mutable { - static constexpr std::array offsets{PAGE, PAGE * 3}; - static constexpr std::array sizes{PAGE, PAGE * 4}; - REQUIRE(offset == offsets.at(i)); - REQUIRE(size == sizes.at(i)); - ++i; - }); -} - -TEST_CASE("BufferBase: Sparse regions 2", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, 0x22000); - buffer.UnmarkRegionAsCpuModified(c, 0x22000); - REQUIRE(rasterizer.Count() == 0x22); - buffer.MarkRegionAsCpuModified(c + PAGE * 0x1B, PAGE); - buffer.MarkRegionAsCpuModified(c + PAGE * 0x21, PAGE); - buffer.ForEachUploadRange(c, WORD, [i = 0](u64 offset, u64 size) mutable { - static constexpr std::array offsets{PAGE * 0x1B, PAGE * 0x21}; - static constexpr std::array sizes{PAGE, PAGE}; - REQUIRE(offset == offsets.at(i)); - REQUIRE(size == sizes.at(i)); - ++i; - }); -} - -TEST_CASE("BufferBase: Single page modified range", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, PAGE); - REQUIRE(buffer.IsRegionCpuModified(c, PAGE)); - buffer.UnmarkRegionAsCpuModified(c, PAGE); - REQUIRE(!buffer.IsRegionCpuModified(c, PAGE)); -} - -TEST_CASE("BufferBase: Two page modified range", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, PAGE * 2); - REQUIRE(buffer.IsRegionCpuModified(c, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c, PAGE * 2)); - buffer.UnmarkRegionAsCpuModified(c, PAGE); - REQUIRE(!buffer.IsRegionCpuModified(c, PAGE)); -} - -TEST_CASE("BufferBase: Multi word modified ranges", "[video_core]") { - for (int offset = 0; offset < 4; ++offset) { - const VAddr address = c + WORD * offset; - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, address, WORD * 4); - REQUIRE(buffer.IsRegionCpuModified(address, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE * 48, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE * 56, PAGE)); - - buffer.UnmarkRegionAsCpuModified(address + PAGE * 32, PAGE); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE, WORD)); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE * 31, PAGE)); - REQUIRE(!buffer.IsRegionCpuModified(address + PAGE * 32, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE * 33, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE * 31, PAGE * 2)); - REQUIRE(buffer.IsRegionCpuModified(address + PAGE * 32, PAGE * 2)); - - buffer.UnmarkRegionAsCpuModified(address + PAGE * 33, PAGE); - REQUIRE(!buffer.IsRegionCpuModified(address + PAGE * 32, PAGE * 2)); - } -} - -TEST_CASE("BufferBase: Single page in large buffer", "[video_core]") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 16); - buffer.UnmarkRegionAsCpuModified(c, WORD * 16); - REQUIRE(!buffer.IsRegionCpuModified(c, WORD * 16)); - - buffer.MarkRegionAsCpuModified(c + WORD * 12 + PAGE * 8, PAGE); - REQUIRE(buffer.IsRegionCpuModified(c, WORD * 16)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 10, WORD * 2)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 11, WORD * 2)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 12, WORD * 2)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 12 + PAGE * 4, PAGE * 8)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 12 + PAGE * 6, PAGE * 8)); - REQUIRE(!buffer.IsRegionCpuModified(c + WORD * 12 + PAGE * 6, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 12 + PAGE * 7, PAGE * 2)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 12 + PAGE * 8, PAGE * 2)); -} - -TEST_CASE("BufferBase: Out of bounds region query") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 16); - REQUIRE(!buffer.IsRegionCpuModified(c - PAGE, PAGE)); - REQUIRE(!buffer.IsRegionCpuModified(c - PAGE * 2, PAGE)); - REQUIRE(!buffer.IsRegionCpuModified(c + WORD * 16, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + WORD * 16 - PAGE, WORD * 64)); - REQUIRE(!buffer.IsRegionCpuModified(c + WORD * 16, WORD * 64)); -} - -TEST_CASE("BufferBase: Wrap word regions") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD * 2); - buffer.UnmarkRegionAsCpuModified(c, WORD * 2); - buffer.MarkRegionAsCpuModified(c + PAGE * 63, PAGE * 2); - REQUIRE(buffer.IsRegionCpuModified(c, WORD * 2)); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE * 62, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 63, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 64, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 63, PAGE * 2)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 63, PAGE * 8)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 60, PAGE * 8)); - - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE * 127, WORD * 16)); - buffer.MarkRegionAsCpuModified(c + PAGE * 127, PAGE); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 127, WORD * 16)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 127, PAGE)); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE * 126, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 126, PAGE * 2)); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE * 128, WORD * 16)); -} - -TEST_CASE("BufferBase: Unaligned page region query") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.MarkRegionAsCpuModified(c + 4000, 1000); - REQUIRE(buffer.IsRegionCpuModified(c, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + 4000, 1000)); - REQUIRE(buffer.IsRegionCpuModified(c + 4000, 1)); -} - -TEST_CASE("BufferBase: Cached write") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.CachedCpuWrite(c + PAGE, PAGE); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); - buffer.FlushCachedWrites(); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - buffer.MarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 0); -} - -TEST_CASE("BufferBase: Multiple cached write") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.CachedCpuWrite(c + PAGE, PAGE); - buffer.CachedCpuWrite(c + PAGE * 3, PAGE); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE * 3, PAGE)); - buffer.FlushCachedWrites(); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE * 3, PAGE)); - buffer.MarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 0); -} - -TEST_CASE("BufferBase: Cached write unmarked") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.CachedCpuWrite(c + PAGE, PAGE); - buffer.UnmarkRegionAsCpuModified(c + PAGE, PAGE); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); - buffer.FlushCachedWrites(); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - buffer.MarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 0); -} - -TEST_CASE("BufferBase: Cached write iterated") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - buffer.CachedCpuWrite(c + PAGE, PAGE); - int num = 0; - buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { ++num; }); - REQUIRE(num == 0); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); - buffer.FlushCachedWrites(); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - buffer.MarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 0); -} - -TEST_CASE("BufferBase: Cached write downloads") { - RasterizerInterface rasterizer; - BufferBase buffer(rasterizer, c, WORD); - buffer.UnmarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 64); - buffer.CachedCpuWrite(c + PAGE, PAGE); - REQUIRE(rasterizer.Count() == 63); - buffer.MarkRegionAsGpuModified(c + PAGE, PAGE); - int num = 0; - buffer.ForEachDownloadRangeAndClear(c, WORD, [&](u64 offset, u64 size) { ++num; }); - buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { ++num; }); - REQUIRE(num == 0); - REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); - REQUIRE(!buffer.IsRegionGpuModified(c + PAGE, PAGE)); - buffer.FlushCachedWrites(); - REQUIRE(buffer.IsRegionCpuModified(c + PAGE, PAGE)); - REQUIRE(!buffer.IsRegionGpuModified(c + PAGE, PAGE)); - buffer.MarkRegionAsCpuModified(c, WORD); - REQUIRE(rasterizer.Count() == 0); -} diff --git a/src/video_core/host_shaders/vulkan_blit_color_float.frag b/src/video_core/host_shaders/vulkan_blit_color_float.frag deleted file mode 100755 index 32636284e..000000000 --- a/src/video_core/host_shaders/vulkan_blit_color_float.frag +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#version 450 - -layout(binding = 0) uniform sampler2D tex; - -layout(location = 0) in vec2 texcoord; -layout(location = 0) out vec4 color; - -void main() { - color = textureLod(tex, texcoord, 0); -}