From d8a783a368cf2df4a2c7143cabd33cc134d6d79b Mon Sep 17 00:00:00 2001 From: Adam Heinermann Date: Wed, 17 Nov 2021 15:00:55 -0800 Subject: Fix crash on exit due to static scoped dummy threads --- src/core/hle/kernel/kernel.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e42a6d36f..45e86a677 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -300,15 +300,16 @@ struct KernelCore::Impl { // Gets the dummy KThread for the caller, allocating a new one if this is the first time KThread* GetHostDummyThread() { auto make_thread = [this]() { - std::unique_ptr thread = std::make_unique(system.Kernel()); + std::lock_guard lk(dummy_thread_lock); + auto& thread = dummy_threads.emplace_back(std::make_unique(system.Kernel())); KAutoObject::Create(thread.get()); ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess()); thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); - return thread; + return thread.get(); }; - thread_local auto thread = make_thread(); - return thread.get(); + thread_local KThread* saved_thread = make_thread(); + return saved_thread; } /// Registers a CPU core thread by allocating a host thread ID for it @@ -695,6 +696,12 @@ struct KernelCore::Impl { return port; } + std::mutex server_ports_lock; + std::mutex server_sessions_lock; + std::mutex registered_objects_lock; + std::mutex registered_in_use_objects_lock; + std::mutex dummy_thread_lock; + std::atomic next_object_id{0}; std::atomic next_kernel_process_id{KProcess::InitialKIPIDMin}; std::atomic next_user_process_id{KProcess::ProcessIDMin}; @@ -725,10 +732,6 @@ struct KernelCore::Impl { std::unordered_set server_sessions; std::unordered_set registered_objects; std::unordered_set registered_in_use_objects; - std::mutex server_ports_lock; - std::mutex server_sessions_lock; - std::mutex registered_objects_lock; - std::mutex registered_in_use_objects_lock; std::unique_ptr exclusive_monitor; std::vector cores; @@ -753,6 +756,9 @@ struct KernelCore::Impl { std::array interrupts{}; std::array, Core::Hardware::NUM_CPU_CORES> schedulers{}; + // Specifically tracked to be automatically destroyed with kernel + std::vector> dummy_threads; + bool is_multicore{}; bool is_phantom_mode_for_singlecore{}; u32 single_core_thread_id{}; -- cgit v1.2.3 From fe1f06c856b768e9afcc9ba9ab8ef09b7152678c Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 20 Nov 2021 17:48:22 -0500 Subject: Fix screenshot dimensions when at 1x scale This was regressed by ART. Prior to ART, the screenshots were saved at the title's framebuffer resolution. A misunderstanding of the existing logic led to screenshot dimensions becoming dependent on the host render window size. This changes the behavior to match how it was prior to ART at 1x, with screenshots now always being the title's framebuffer dimensions scaled by the resolution scaling factor. --- src/core/frontend/framebuffer_layout.cpp | 7 ++++++- src/core/frontend/framebuffer_layout.h | 11 +---------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'src/core') diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 4b58b672a..26a5b12aa 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -25,7 +25,12 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { ASSERT(height > 0); // The drawing code needs at least somewhat valid values for both screens // so just calculate them both even if the other isn't showing. - FramebufferLayout res{width, height, false, {}}; + FramebufferLayout res{ + .width = width, + .height = height, + .screen = {}, + .is_srgb = false, + }; const float window_aspect_ratio = static_cast(height) / static_cast(width); const float emulation_aspect_ratio = EmulationAspectRatio( diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 2e36c0163..8e341e4e2 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -35,17 +35,8 @@ enum class AspectRatio { struct FramebufferLayout { u32 width{ScreenUndocked::Width}; u32 height{ScreenUndocked::Height}; - bool is_srgb{}; - Common::Rectangle screen; - - /** - * Returns the ration of pixel size of the screen, compared to the native size of the undocked - * Switch screen. - */ - float GetScalingRatio() const { - return static_cast(screen.GetWidth()) / ScreenUndocked::Width; - } + bool is_srgb{}; }; /** -- cgit v1.2.3 From 40cd0bb97b3d6db6eba0e18fae6560c8e1b69794 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 19:39:26 -0500 Subject: service: pm: Rename title id to program id --- src/core/hle/service/pm/pm.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 88fc5b5cc..969300795 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -95,13 +95,13 @@ public: private: void GetProcessId(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto title_id = rp.PopRaw(); + const auto program_id = rp.PopRaw(); - LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); + LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); const auto process = - SearchProcessList(kernel.GetProcessList(), [title_id](const auto& proc) { - return proc->GetProgramID() == title_id; + SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { + return proc->GetProgramID() == program_id; }); if (!process.has_value()) { @@ -128,13 +128,13 @@ public: explicit Info(Core::System& system_, const std::vector& process_list_) : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { static const FunctionInfo functions[] = { - {0, &Info::GetTitleId, "GetTitleId"}, + {0, &Info::GetProgramId, "GetProgramId"}, }; RegisterHandlers(functions); } private: - void GetTitleId(Kernel::HLERequestContext& ctx) { + void GetProgramId(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto process_id = rp.PopRaw(); -- cgit v1.2.3 From 3dc38d185b595ef2cf1d539f7bc68554999cd1db Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 19:42:30 -0500 Subject: service: pm: Add all relevant result codes --- src/core/hle/service/pm/pm.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 969300795..b2e97a218 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -13,7 +13,12 @@ namespace Service::PM { namespace { -constexpr ResultCode ERROR_PROCESS_NOT_FOUND{ErrorModule::PM, 1}; +constexpr ResultCode ResultProcessNotFound{ErrorModule::PM, 1}; +[[maybe_unused]] constexpr ResultCode ResultAlreadyStarted{ErrorModule::PM, 2}; +[[maybe_unused]] constexpr ResultCode ResultNotTerminated{ErrorModule::PM, 3}; +[[maybe_unused]] constexpr ResultCode ResultDebugHookInUse{ErrorModule::PM, 4}; +[[maybe_unused]] constexpr ResultCode ResultApplicationRunning{ErrorModule::PM, 5}; +[[maybe_unused]] constexpr ResultCode ResultInvalidSize{ErrorModule::PM, 6}; constexpr u64 NO_PROCESS_FOUND_PID{0}; @@ -106,7 +111,7 @@ private: if (!process.has_value()) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERROR_PROCESS_NOT_FOUND); + rb.Push(ResultProcessNotFound); return; } @@ -146,7 +151,7 @@ private: if (!process.has_value()) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERROR_PROCESS_NOT_FOUND); + rb.Push(ResultProcessNotFound); return; } -- cgit v1.2.3 From 9173f07a51ee355d79c60fed21e7731868db5e6d Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 19:52:25 -0500 Subject: service: pm: Implement AtmosphereGetProcessId - Used by Skyline modding framework --- src/core/hle/service/pm/pm.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index b2e97a218..277abc17a 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -134,6 +134,9 @@ public: : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { static const FunctionInfo functions[] = { {0, &Info::GetProgramId, "GetProgramId"}, + {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, + {65001, nullptr, "AtmosphereHasLaunchedProgram"}, + {65002, nullptr, "AtmosphereGetProcessInfo"}, }; RegisterHandlers(functions); } @@ -160,6 +163,27 @@ private: rb.Push((*process)->GetProgramID()); } + void AtmosphereGetProcessId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto program_id = rp.PopRaw(); + + LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); + + const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { + return proc->GetProgramID() == program_id; + }); + + if (!process.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultProcessNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push((*process)->GetProcessID()); + } + const std::vector& process_list; }; -- cgit v1.2.3 From 281437c811847adbc38b69ef3638996c666f65c3 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 20:05:02 -0500 Subject: kernel: KPageTable: Rename SetCodeMemoryPermission to SetProcessMemoryPermission --- src/core/hle/kernel/k_page_table.cpp | 4 ++-- src/core/hle/kernel/k_page_table.h | 2 +- src/core/hle/kernel/k_process.cpp | 2 +- src/core/hle/service/ldr/ldr.cpp | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 526b87241..9bda5c5b2 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp @@ -685,8 +685,8 @@ ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, return ResultSuccess; } -ResultCode KPageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, - KMemoryPermission perm) { +ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size, + KMemoryPermission perm) { std::lock_guard lock{page_table_lock}; diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 770c4841c..b7ec38f06 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h @@ -41,7 +41,7 @@ public: ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, KMemoryPermission perm); ResultCode UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state); - ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm); + ResultCode SetProcessMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm); KMemoryInfo QueryInfo(VAddr addr); ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); ResultCode ResetTransferMemory(VAddr addr, std::size_t size); diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 76fd8c285..1aad061e1 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -528,7 +528,7 @@ void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { std::lock_guard lock{HLE::g_hle_lock}; const auto ReprotectSegment = [&](const CodeSet::Segment& segment, KMemoryPermission permission) { - page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); + page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); }; kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(), diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 32eff3b2a..3782703d2 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -396,12 +396,12 @@ public: CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, nro_header.segment_headers[DATA_INDEX].memory_size); - CASCADE_CODE(process->PageTable().SetCodeMemoryPermission( + CASCADE_CODE(process->PageTable().SetProcessMemoryPermission( text_start, ro_start - text_start, Kernel::KMemoryPermission::ReadAndExecute)); - CASCADE_CODE(process->PageTable().SetCodeMemoryPermission(ro_start, data_start - ro_start, - Kernel::KMemoryPermission::Read)); + CASCADE_CODE(process->PageTable().SetProcessMemoryPermission( + ro_start, data_start - ro_start, Kernel::KMemoryPermission::Read)); - return process->PageTable().SetCodeMemoryPermission( + return process->PageTable().SetProcessMemoryPermission( data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite); } -- cgit v1.2.3 From 2726d705f8dde6d8fcbcfcd55e065a0598e10969 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 20:23:59 -0500 Subject: kernel: svc: Implement SetProcessMemoryPermission - Used by Skyline modding framework --- src/core/hle/kernel/svc.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f9d99bc51..23dc44780 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1183,6 +1183,18 @@ constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; } +constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { + switch (perm) { + case Svc::MemoryPermission::None: + case Svc::MemoryPermission::Read: + case Svc::MemoryPermission::ReadWrite: + case Svc::MemoryPermission::ReadExecute: + return true; + default: + return false; + } +} + static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size, Svc::MemoryPermission map_perm) { LOG_TRACE(Kernel_SVC, @@ -1262,6 +1274,34 @@ static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, return UnmapSharedMemory(system, shmem_handle, address, size); } +static ResultCode SetProcessMemoryPermission(Core::System& system, Handle process_handle, + VAddr address, u64 size, Svc::MemoryPermission perm) { + LOG_TRACE(Kernel_SVC, + "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", + process_handle, address, size, perm); + + // Validate the address/size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); + + // Validate the memory permission. + R_UNLESS(IsValidProcessMemoryPermission(perm), ResultInvalidNewMemoryPermission); + + // Get the process from its handle. + KScopedAutoObject process = + system.CurrentProcess()->GetHandleTable().GetObject(process_handle); + R_UNLESS(process.IsNotNull(), ResultInvalidHandle); + + // Validate that the address is in range. + auto& page_table = process->PageTable(); + R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); + + // Set the memory permission. + return page_table.SetProcessMemoryPermission(address, size, ConvertToKMemoryPermission(perm)); +} + static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address, Handle process_handle, VAddr address) { @@ -2588,7 +2628,7 @@ static const FunctionDef SVC_Table_64[] = { {0x70, nullptr, "CreatePort"}, {0x71, nullptr, "ManageNamedPort"}, {0x72, nullptr, "ConnectToPort"}, - {0x73, nullptr, "SetProcessMemoryPermission"}, + {0x73, SvcWrap64, "SetProcessMemoryPermission"}, {0x74, nullptr, "MapProcessMemory"}, {0x75, nullptr, "UnmapProcessMemory"}, {0x76, SvcWrap64, "QueryProcessMemory"}, -- cgit v1.2.3 From 5cf93c134684f7548572ff27131901f5909725fa Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 21:54:46 -0500 Subject: kernel: svc: Move all IsValid functions to an anonymous namespace --- src/core/hle/kernel/svc.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 23dc44780..f0cd8471e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1169,6 +1169,8 @@ static u32 GetCurrentProcessorNumber32(Core::System& system) { return GetCurrentProcessorNumber(system); } +namespace { + constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { switch (perm) { case Svc::MemoryPermission::Read: @@ -1179,7 +1181,7 @@ constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { } } -constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { +[[maybe_unused]] constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; } @@ -1195,6 +1197,8 @@ constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { } } +} // Anonymous namespace + static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size, Svc::MemoryPermission map_perm) { LOG_TRACE(Kernel_SVC, @@ -1499,10 +1503,14 @@ static void ExitProcess32(Core::System& system) { ExitProcess(system); } -static constexpr bool IsValidVirtualCoreId(int32_t core_id) { +namespace { + +constexpr bool IsValidVirtualCoreId(int32_t core_id) { return (0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); } +} // Anonymous namespace + /// Creates a new thread static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_bottom, u32 priority, s32 core_id) { @@ -1886,7 +1894,9 @@ static ResultCode ResetSignal32(Core::System& system, Handle handle) { return ResetSignal(system, handle); } -static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { +namespace { + +constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { switch (perm) { case MemoryPermission::None: case MemoryPermission::Read: @@ -1897,6 +1907,8 @@ static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { } } +} // Anonymous namespace + /// Creates a TransferMemory object static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, MemoryPermission map_perm) { -- cgit v1.2.3 From 84eb3e7d02d386bc90eb4a6c6b6e33eea33a42e2 Mon Sep 17 00:00:00 2001 From: jam1garner <8260240+jam1garner@users.noreply.github.com> Date: Sun, 21 Nov 2021 21:10:14 -0500 Subject: arm: dynarmic: Implement icache op handling for 'ic ivau' instruction --- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/core') diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 4e73cc03a..587fffb34 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -86,6 +86,24 @@ public: num_instructions, MemoryReadCode(pc)); } + void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, + VAddr value) override { + constexpr u64 ICACHE_LINE_SIZE = 64; + u64 cache_line_start; + + switch (op) { + case Dynarmic::A64::InstructionCacheOperation::InvalidateByVAToPoU: + cache_line_start = value & ~(ICACHE_LINE_SIZE - 1); + parent.InvalidateCacheRange(cache_line_start, ICACHE_LINE_SIZE); + return; + + case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU: + case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable: + default: + LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation"); + } + } + void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { switch (exception) { case Dynarmic::A64::Exception::WaitForInterrupt: -- cgit v1.2.3 From c8a67a725de6481c891d5bfe1b83fcb6340c88a3 Mon Sep 17 00:00:00 2001 From: jam1garner <8260240+jam1garner@users.noreply.github.com> Date: Sun, 21 Nov 2021 21:18:56 -0500 Subject: arm: dynarmic: Implement icache op handling for 'ic iallu' instruction --- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 587fffb34..8fe83413c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -98,6 +98,9 @@ public: return; case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU: + parent.ClearInstructionCache(); + return; + case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable: default: LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation"); -- cgit v1.2.3 From 4d9c9e567ef6c44967b639471613a0328dcbf833 Mon Sep 17 00:00:00 2001 From: jam1garner <8260240+jam1garner@users.noreply.github.com> Date: Sun, 21 Nov 2021 21:24:07 -0500 Subject: arm: dynarmic: Cleanup icache op handling --- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 8fe83413c..56836bd05 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -88,22 +88,21 @@ public: void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, VAddr value) override { - constexpr u64 ICACHE_LINE_SIZE = 64; - u64 cache_line_start; - switch (op) { - case Dynarmic::A64::InstructionCacheOperation::InvalidateByVAToPoU: - cache_line_start = value & ~(ICACHE_LINE_SIZE - 1); - parent.InvalidateCacheRange(cache_line_start, ICACHE_LINE_SIZE); - return; + case Dynarmic::A64::InstructionCacheOperation::InvalidateByVAToPoU: { + static constexpr u64 ICACHE_LINE_SIZE = 64; + const u64 cache_line_start = value & ~(ICACHE_LINE_SIZE - 1); + parent.InvalidateCacheRange(cache_line_start, ICACHE_LINE_SIZE); + break; + } case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU: parent.ClearInstructionCache(); - return; - + break; case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable: default: - LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation"); + LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation: {}", op); + break; } } -- cgit v1.2.3 From bf71d18af99368d7658c9519086c40e73c6abfdd Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 15:02:01 -0500 Subject: core/hid: Move input_interpreter to hid --- src/core/CMakeLists.txt | 4 +- src/core/frontend/input_interpreter.cpp | 62 -------------- src/core/frontend/input_interpreter.h | 144 -------------------------------- src/core/hid/input_interpreter.cpp | 62 ++++++++++++++ src/core/hid/input_interpreter.h | 144 ++++++++++++++++++++++++++++++++ 5 files changed, 208 insertions(+), 208 deletions(-) delete mode 100644 src/core/frontend/input_interpreter.cpp delete mode 100644 src/core/frontend/input_interpreter.h create mode 100644 src/core/hid/input_interpreter.cpp create mode 100644 src/core/hid/input_interpreter.h (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9f0fbba2d..14ba986d3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -132,11 +132,11 @@ add_library(core STATIC frontend/emu_window.h frontend/framebuffer_layout.cpp frontend/framebuffer_layout.h - frontend/input_interpreter.cpp - frontend/input_interpreter.h frontend/input.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h + hid/input_interpreter.cpp + hid/input_interpreter.h hle/api_version.h hle/ipc.h hle/ipc_helpers.h diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/frontend/input_interpreter.cpp deleted file mode 100644 index 9f6a90e8f..000000000 --- a/src/core/frontend/input_interpreter.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2020 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/core.h" -#include "core/frontend/input_interpreter.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/hid.h" -#include "core/hle/service/sm/sm.h" - -InputInterpreter::InputInterpreter(Core::System& system) - : npad{system.ServiceManager() - .GetService("hid") - ->GetAppletResource() - ->GetController(Service::HID::HidController::NPad)} { - ResetButtonStates(); -} - -InputInterpreter::~InputInterpreter() = default; - -void InputInterpreter::PollInput() { - const u32 button_state = npad.GetAndResetPressState(); - - previous_index = current_index; - current_index = (current_index + 1) % button_states.size(); - - button_states[current_index] = button_state; -} - -void InputInterpreter::ResetButtonStates() { - previous_index = 0; - current_index = 0; - - button_states[0] = 0xFFFFFFFF; - - for (std::size_t i = 1; i < button_states.size(); ++i) { - button_states[i] = 0; - } -} - -bool InputInterpreter::IsButtonPressed(HIDButton button) const { - return (button_states[current_index] & (1U << static_cast(button))) != 0; -} - -bool InputInterpreter::IsButtonPressedOnce(HIDButton button) const { - const bool current_press = - (button_states[current_index] & (1U << static_cast(button))) != 0; - const bool previous_press = - (button_states[previous_index] & (1U << static_cast(button))) != 0; - - return current_press && !previous_press; -} - -bool InputInterpreter::IsButtonHeld(HIDButton button) const { - u32 held_buttons{button_states[0]}; - - for (std::size_t i = 1; i < button_states.size(); ++i) { - held_buttons &= button_states[i]; - } - - return (held_buttons & (1U << static_cast(button))) != 0; -} diff --git a/src/core/frontend/input_interpreter.h b/src/core/frontend/input_interpreter.h deleted file mode 100644 index 9495e3daf..000000000 --- a/src/core/frontend/input_interpreter.h +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2020 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include - -#include "common/common_types.h" - -namespace Core { -class System; -} - -namespace Service::HID { -class Controller_NPad; -} - -enum class HIDButton : u8 { - A, - B, - X, - Y, - LStick, - RStick, - L, - R, - ZL, - ZR, - Plus, - Minus, - - DLeft, - DUp, - DRight, - DDown, - - LStickLeft, - LStickUp, - LStickRight, - LStickDown, - - RStickLeft, - RStickUp, - RStickRight, - RStickDown, - - LeftSL, - LeftSR, - - RightSL, - RightSR, -}; - -/** - * The InputInterpreter class interfaces with HID to retrieve button press states. - * Input is intended to be polled every 50ms so that a button is considered to be - * held down after 400ms has elapsed since the initial button press and subsequent - * repeated presses occur every 50ms. - */ -class InputInterpreter { -public: - explicit InputInterpreter(Core::System& system); - virtual ~InputInterpreter(); - - /// Gets a button state from HID and inserts it into the array of button states. - void PollInput(); - - /// Resets all the button states to their defaults. - void ResetButtonStates(); - - /** - * Checks whether the button is pressed. - * - * @param button The button to check. - * - * @returns True when the button is pressed. - */ - [[nodiscard]] bool IsButtonPressed(HIDButton button) const; - - /** - * Checks whether any of the buttons in the parameter list is pressed. - * - * @tparam HIDButton The buttons to check. - * - * @returns True when at least one of the buttons is pressed. - */ - template - [[nodiscard]] bool IsAnyButtonPressed() { - return (IsButtonPressed(T) || ...); - } - - /** - * The specified button is considered to be pressed once - * if it is currently pressed and not pressed previously. - * - * @param button The button to check. - * - * @returns True when the button is pressed once. - */ - [[nodiscard]] bool IsButtonPressedOnce(HIDButton button) const; - - /** - * Checks whether any of the buttons in the parameter list is pressed once. - * - * @tparam T The buttons to check. - * - * @returns True when at least one of the buttons is pressed once. - */ - template - [[nodiscard]] bool IsAnyButtonPressedOnce() const { - return (IsButtonPressedOnce(T) || ...); - } - - /** - * The specified button is considered to be held down if it is pressed in all 9 button states. - * - * @param button The button to check. - * - * @returns True when the button is held down. - */ - [[nodiscard]] bool IsButtonHeld(HIDButton button) const; - - /** - * Checks whether any of the buttons in the parameter list is held down. - * - * @tparam T The buttons to check. - * - * @returns True when at least one of the buttons is held down. - */ - template - [[nodiscard]] bool IsAnyButtonHeld() const { - return (IsButtonHeld(T) || ...); - } - -private: - Service::HID::Controller_NPad& npad; - - /// Stores 9 consecutive button states polled from HID. - std::array button_states{}; - - std::size_t previous_index{}; - std::size_t current_index{}; -}; diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp new file mode 100644 index 000000000..c33d8a11a --- /dev/null +++ b/src/core/hid/input_interpreter.cpp @@ -0,0 +1,62 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/core.h" +#include "core/hid/input_interpreter.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/hid.h" +#include "core/hle/service/sm/sm.h" + +InputInterpreter::InputInterpreter(Core::System& system) + : npad{system.ServiceManager() + .GetService("hid") + ->GetAppletResource() + ->GetController(Service::HID::HidController::NPad)} { + ResetButtonStates(); +} + +InputInterpreter::~InputInterpreter() = default; + +void InputInterpreter::PollInput() { + const u32 button_state = npad.GetAndResetPressState(); + + previous_index = current_index; + current_index = (current_index + 1) % button_states.size(); + + button_states[current_index] = button_state; +} + +void InputInterpreter::ResetButtonStates() { + previous_index = 0; + current_index = 0; + + button_states[0] = 0xFFFFFFFF; + + for (std::size_t i = 1; i < button_states.size(); ++i) { + button_states[i] = 0; + } +} + +bool InputInterpreter::IsButtonPressed(HIDButton button) const { + return (button_states[current_index] & (1U << static_cast(button))) != 0; +} + +bool InputInterpreter::IsButtonPressedOnce(HIDButton button) const { + const bool current_press = + (button_states[current_index] & (1U << static_cast(button))) != 0; + const bool previous_press = + (button_states[previous_index] & (1U << static_cast(button))) != 0; + + return current_press && !previous_press; +} + +bool InputInterpreter::IsButtonHeld(HIDButton button) const { + u32 held_buttons{button_states[0]}; + + for (std::size_t i = 1; i < button_states.size(); ++i) { + held_buttons &= button_states[i]; + } + + return (held_buttons & (1U << static_cast(button))) != 0; +} diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h new file mode 100644 index 000000000..9495e3daf --- /dev/null +++ b/src/core/hid/input_interpreter.h @@ -0,0 +1,144 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/common_types.h" + +namespace Core { +class System; +} + +namespace Service::HID { +class Controller_NPad; +} + +enum class HIDButton : u8 { + A, + B, + X, + Y, + LStick, + RStick, + L, + R, + ZL, + ZR, + Plus, + Minus, + + DLeft, + DUp, + DRight, + DDown, + + LStickLeft, + LStickUp, + LStickRight, + LStickDown, + + RStickLeft, + RStickUp, + RStickRight, + RStickDown, + + LeftSL, + LeftSR, + + RightSL, + RightSR, +}; + +/** + * The InputInterpreter class interfaces with HID to retrieve button press states. + * Input is intended to be polled every 50ms so that a button is considered to be + * held down after 400ms has elapsed since the initial button press and subsequent + * repeated presses occur every 50ms. + */ +class InputInterpreter { +public: + explicit InputInterpreter(Core::System& system); + virtual ~InputInterpreter(); + + /// Gets a button state from HID and inserts it into the array of button states. + void PollInput(); + + /// Resets all the button states to their defaults. + void ResetButtonStates(); + + /** + * Checks whether the button is pressed. + * + * @param button The button to check. + * + * @returns True when the button is pressed. + */ + [[nodiscard]] bool IsButtonPressed(HIDButton button) const; + + /** + * Checks whether any of the buttons in the parameter list is pressed. + * + * @tparam HIDButton The buttons to check. + * + * @returns True when at least one of the buttons is pressed. + */ + template + [[nodiscard]] bool IsAnyButtonPressed() { + return (IsButtonPressed(T) || ...); + } + + /** + * The specified button is considered to be pressed once + * if it is currently pressed and not pressed previously. + * + * @param button The button to check. + * + * @returns True when the button is pressed once. + */ + [[nodiscard]] bool IsButtonPressedOnce(HIDButton button) const; + + /** + * Checks whether any of the buttons in the parameter list is pressed once. + * + * @tparam T The buttons to check. + * + * @returns True when at least one of the buttons is pressed once. + */ + template + [[nodiscard]] bool IsAnyButtonPressedOnce() const { + return (IsButtonPressedOnce(T) || ...); + } + + /** + * The specified button is considered to be held down if it is pressed in all 9 button states. + * + * @param button The button to check. + * + * @returns True when the button is held down. + */ + [[nodiscard]] bool IsButtonHeld(HIDButton button) const; + + /** + * Checks whether any of the buttons in the parameter list is held down. + * + * @tparam T The buttons to check. + * + * @returns True when at least one of the buttons is held down. + */ + template + [[nodiscard]] bool IsAnyButtonHeld() const { + return (IsButtonHeld(T) || ...); + } + +private: + Service::HID::Controller_NPad& npad; + + /// Stores 9 consecutive button states polled from HID. + std::array button_states{}; + + std::size_t previous_index{}; + std::size_t current_index{}; +}; -- cgit v1.2.3 From 449576df93f6beb70cff0e009ccb2dd8bce1e085 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 16:29:43 -0500 Subject: core/hid: Move motion_input, create input converter and hid_types --- src/core/CMakeLists.txt | 5 + src/core/hid/hid_types.h | 388 +++++++++++++++++++++++++++++++++++++++ src/core/hid/input_converter.cpp | 345 ++++++++++++++++++++++++++++++++++ src/core/hid/input_converter.h | 77 ++++++++ src/core/hid/motion_input.cpp | 278 ++++++++++++++++++++++++++++ src/core/hid/motion_input.h | 71 +++++++ 6 files changed, 1164 insertions(+) create mode 100644 src/core/hid/hid_types.h create mode 100644 src/core/hid/input_converter.cpp create mode 100644 src/core/hid/input_converter.h create mode 100644 src/core/hid/motion_input.cpp create mode 100644 src/core/hid/motion_input.h (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 14ba986d3..eddf455c0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -135,8 +135,13 @@ add_library(core STATIC frontend/input.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h + hid/hid_types.h + hid/input_converter.cpp + hid/input_converter.h hid/input_interpreter.cpp hid/input_interpreter.h + hid/motion_input.cpp + hid/motion_input.h hle/api_version.h hle/ipc.h hle/ipc_helpers.h diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h new file mode 100644 index 000000000..d3f7930c9 --- /dev/null +++ b/src/core/hid/hid_types.h @@ -0,0 +1,388 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/point.h" +#include "common/uuid.h" + +namespace Core::HID { + +// This is nn::hid::NpadIdType +enum class NpadIdType : u8 { + Player1 = 0x0, + Player2 = 0x1, + Player3 = 0x2, + Player4 = 0x3, + Player5 = 0x4, + Player6 = 0x5, + Player7 = 0x6, + Player8 = 0x7, + Other = 0x10, + Handheld = 0x20, + + Invalid = 0xFF, +}; + +/// Converts a NpadIdType to an array index. +constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { + switch (npad_id_type) { + case NpadIdType::Player1: + return 0; + case NpadIdType::Player2: + return 1; + case NpadIdType::Player3: + return 2; + case NpadIdType::Player4: + return 3; + case NpadIdType::Player5: + return 4; + case NpadIdType::Player6: + return 5; + case NpadIdType::Player7: + return 6; + case NpadIdType::Player8: + return 7; + case NpadIdType::Other: + return 8; + case NpadIdType::Handheld: + return 9; + default: + return 0; + } +} + +/// Converts an array index to a NpadIdType +constexpr NpadIdType IndexToNpadIdType(size_t index) { + switch (index) { + case 0: + return NpadIdType::Player1; + case 1: + return NpadIdType::Player2; + case 2: + return NpadIdType::Player3; + case 3: + return NpadIdType::Player4; + case 4: + return NpadIdType::Player5; + case 5: + return NpadIdType::Player6; + case 6: + return NpadIdType::Player7; + case 7: + return NpadIdType::Player8; + case 8: + return NpadIdType::Other; + case 9: + return NpadIdType::Handheld; + default: + return NpadIdType::Invalid; + } +} + +// This is nn::hid::NpadType +enum class NpadType : u8 { + None = 0, + ProController = 3, + Handheld = 4, + JoyconDual = 5, + JoyconLeft = 6, + JoyconRight = 7, + GameCube = 8, + Pokeball = 9, + MaxNpadType = 10, +}; + +// This is nn::hid::NpadStyleTag +struct NpadStyleTag { + union { + u32_le raw{}; + + BitField<0, 1, u32> fullkey; + BitField<1, 1, u32> handheld; + BitField<2, 1, u32> joycon_dual; + BitField<3, 1, u32> joycon_left; + BitField<4, 1, u32> joycon_right; + BitField<5, 1, u32> gamecube; + BitField<6, 1, u32> palma; + BitField<7, 1, u32> lark; + BitField<8, 1, u32> handheld_lark; + BitField<9, 1, u32> lucia; + BitField<29, 1, u32> system_ext; + BitField<30, 1, u32> system; + }; +}; +static_assert(sizeof(NpadStyleTag) == 4, "NpadStyleTag is an invalid size"); + +// This is nn::hid::TouchAttribute +struct TouchAttribute { + union { + u32 raw{}; + BitField<0, 1, u32> start_touch; + BitField<1, 1, u32> end_touch; + }; +}; +static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"); + +// This is nn::hid::TouchState +struct TouchState { + u64_le delta_time; + TouchAttribute attribute; + u32_le finger; + Common::Point position; + u32_le diameter_x; + u32_le diameter_y; + u32_le rotation_angle; +}; +static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); + +// This is nn::hid::NpadControllerColor +struct NpadControllerColor { + u32_le body; + u32_le button; +}; +static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); + +// This is nn::hid::AnalogStickState +struct AnalogStickState { + s32_le x; + s32_le y; +}; +static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); + +// This is nn::hid::server::NpadGcTriggerState +struct NpadGcTriggerState { + s64_le sampling_number{}; + s32_le left{}; + s32_le right{}; +}; +static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); + +// This is nn::hid::system::NpadBatteryLevel +using BatteryLevel = u32; +static_assert(sizeof(BatteryLevel) == 0x4, "BatteryLevel is an invalid size"); + +// This is nn::hid::system::NpadPowerInfo +struct NpadPowerInfo { + bool is_powered; + bool is_charging; + INSERT_PADDING_BYTES(0x6); + BatteryLevel battery_level; +}; +static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); + +// This is nn::hid::NpadButton +enum class NpadButton : u64 { + None = 0, + A = 1U << 0, + B = 1U << 1, + X = 1U << 2, + Y = 1U << 3, + StickL = 1U << 4, + StickR = 1U << 5, + L = 1U << 6, + R = 1U << 7, + ZL = 1U << 8, + ZR = 1U << 9, + Plus = 1U << 10, + Minus = 1U << 11, + + Left = 1U << 12, + Up = 1U << 13, + Right = 1U << 14, + Down = 1U << 15, + + StickLLeft = 1U << 16, + StickLUp = 1U << 17, + StickLRight = 1U << 18, + StickLDown = 1U << 19, + + StickRLeft = 1U << 20, + StickRUp = 1U << 21, + StickRRight = 1U << 22, + StickRDown = 1U << 23, + + LeftSL = 1U << 24, + LeftSR = 1U << 25, + + RightSL = 1U << 26, + RightSR = 1U << 27, + + Palma = 1U << 28, + HandheldLeftB = 1U << 30, +}; +DECLARE_ENUM_FLAG_OPERATORS(NpadButton); + +struct NpadButtonState { + union { + NpadButton raw{}; + + // Buttons + BitField<0, 1, u64> a; + BitField<1, 1, u64> b; + BitField<2, 1, u64> x; + BitField<3, 1, u64> y; + BitField<4, 1, u64> stick_l; + BitField<5, 1, u64> stick_r; + BitField<6, 1, u64> l; + BitField<7, 1, u64> r; + BitField<8, 1, u64> zl; + BitField<9, 1, u64> zr; + BitField<10, 1, u64> plus; + BitField<11, 1, u64> minus; + + // D-Pad + BitField<12, 1, u64> left; + BitField<13, 1, u64> up; + BitField<14, 1, u64> right; + BitField<15, 1, u64> down; + + // Left JoyStick + BitField<16, 1, u64> stick_l_left; + BitField<17, 1, u64> stick_l_up; + BitField<18, 1, u64> stick_l_right; + BitField<19, 1, u64> stick_l_down; + + // Right JoyStick + BitField<20, 1, u64> stick_r_left; + BitField<21, 1, u64> stick_r_up; + BitField<22, 1, u64> stick_r_right; + BitField<23, 1, u64> stick_r_down; + + BitField<24, 1, u64> left_sl; + BitField<25, 1, u64> left_sr; + + BitField<26, 1, u64> right_sl; + BitField<27, 1, u64> right_sr; + + BitField<28, 1, u64> palma; + BitField<30, 1, u64> handheld_left_b; + }; +}; +static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size."); + +// This is nn::hid::DebugPadButton +struct DebugPadButton { + union { + u32_le raw{}; + BitField<0, 1, u32> a; + BitField<1, 1, u32> b; + BitField<2, 1, u32> x; + BitField<3, 1, u32> y; + BitField<4, 1, u32> l; + BitField<5, 1, u32> r; + BitField<6, 1, u32> zl; + BitField<7, 1, u32> zr; + BitField<8, 1, u32> plus; + BitField<9, 1, u32> minus; + BitField<10, 1, u32> d_left; + BitField<11, 1, u32> d_up; + BitField<12, 1, u32> d_right; + BitField<13, 1, u32> d_down; + }; +}; +static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); + +// This is nn::hid::VibrationDeviceType +enum class VibrationDeviceType : u32 { + Unknown = 0, + LinearResonantActuator = 1, + GcErm = 2, +}; + +// This is nn::hid::VibrationDevicePosition +enum class VibrationDevicePosition : u32 { + None = 0, + Left = 1, + Right = 2, +}; + +// This is nn::hid::VibrationValue +struct VibrationValue { + f32 low_amplitude; + f32 low_frequency; + f32 high_amplitude; + f32 high_frequency; +}; +static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); + +// This is nn::hid::VibrationGcErmCommand +enum class VibrationGcErmCommand : u64 { + Stop = 0, + Start = 1, + StopHard = 2, +}; + +// This is nn::hid::VibrationDeviceInfo +struct VibrationDeviceInfo { + VibrationDeviceType type{}; + VibrationDevicePosition position{}; +}; +static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); + +// This is nn::hid::KeyboardModifier +struct KeyboardModifier { + union { + u32_le raw{}; + BitField<0, 1, u32> control; + BitField<1, 1, u32> shift; + BitField<2, 1, u32> left_alt; + BitField<3, 1, u32> right_alt; + BitField<4, 1, u32> gui; + BitField<8, 1, u32> caps_lock; + BitField<9, 1, u32> scroll_lock; + BitField<10, 1, u32> num_lock; + BitField<11, 1, u32> katakana; + BitField<12, 1, u32> hiragana; + }; +}; +static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size"); + +// This is nn::hid::KeyboardKey +struct KeyboardKey { + // This should be a 256 bit flag + std::array key; +}; +static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size"); + +// This is nn::hid::MouseButton +struct MouseButton { + union { + u32_le raw{}; + BitField<0, 1, u32> left; + BitField<1, 1, u32> right; + BitField<2, 1, u32> middle; + BitField<3, 1, u32> forward; + BitField<4, 1, u32> back; + }; +}; +static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size"); + +// This is nn::hid::MouseAttribute +struct MouseAttribute { + union { + u32_le raw{}; + BitField<0, 1, u32> transferable; + BitField<1, 1, u32> is_connected; + }; +}; +static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"); + +// This is nn::hid::detail::MouseState +struct MouseState { + s64_le sampling_number; + s32_le x; + s32_le y; + s32_le delta_x; + s32_le delta_y; + s32_le delta_wheel_x; + s32_le delta_wheel_y; + MouseButton button; + MouseAttribute attribute; +}; +static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); +} // namespace Core::HID diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp new file mode 100644 index 000000000..5834622e9 --- /dev/null +++ b/src/core/hid/input_converter.cpp @@ -0,0 +1,345 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include + +#include "common/input.h" +#include "core/hid/input_converter.h" + +namespace Core::HID { + +Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) { + Input::BatteryStatus battery{}; + switch (callback.type) { + case Input::InputType::Analog: + case Input::InputType::Trigger: { + const auto value = TransformToTrigger(callback).analog.value; + battery = Input::BatteryLevel::Empty; + if (value > 0.2f) { + battery = Input::BatteryLevel::Critical; + } + if (value > 0.4f) { + battery = Input::BatteryLevel::Low; + } + if (value > 0.6f) { + battery = Input::BatteryLevel::Medium; + } + if (value > 0.8f) { + battery = Input::BatteryLevel::Full; + } + if (value >= 1.0f) { + battery = Input::BatteryLevel::Charging; + } + break; + } + case Input::InputType::Battery: + battery = callback.battery_status; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to battery not implemented", callback.type); + break; + } + + return battery; +} + +Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback) { + Input::ButtonStatus status{}; + switch (callback.type) { + case Input::InputType::Analog: + case Input::InputType::Trigger: + status.value = TransformToTrigger(callback).pressed; + break; + case Input::InputType::Button: + status = callback.button_status; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to button not implemented", callback.type); + break; + } + + if (status.inverted) { + status.value = !status.value; + } + + return status; +} + +Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) { + Input::MotionStatus status{}; + switch (callback.type) { + case Input::InputType::Button: { + if (TransformToButton(callback).value) { + std::random_device device; + std::mt19937 gen(device()); + std::uniform_int_distribution distribution(-1000, 1000); + Input::AnalogProperties properties{ + .deadzone = 0.0, + .range = 1.0f, + .offset = 0.0, + }; + status.accel.x = { + .value = 0, + .raw_value = static_cast(distribution(gen)) * 0.001f, + .properties = properties, + }; + status.accel.y = { + .value = 0, + .raw_value = static_cast(distribution(gen)) * 0.001f, + .properties = properties, + }; + status.accel.z = { + .value = 0, + .raw_value = static_cast(distribution(gen)) * 0.001f, + .properties = properties, + }; + status.gyro.x = { + .value = 0, + .raw_value = static_cast(distribution(gen)) * 0.001f, + .properties = properties, + }; + status.gyro.y = { + .value = 0, + .raw_value = static_cast(distribution(gen)) * 0.001f, + .properties = properties, + }; + status.gyro.z = { + .value = 0, + .raw_value = static_cast(distribution(gen)) * 0.001f, + .properties = properties, + }; + } + break; + } + case Input::InputType::Motion: + status = callback.motion_status; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to motion not implemented", callback.type); + break; + } + SanitizeAnalog(status.accel.x, false); + SanitizeAnalog(status.accel.y, false); + SanitizeAnalog(status.accel.z, false); + SanitizeAnalog(status.gyro.x, false); + SanitizeAnalog(status.gyro.y, false); + SanitizeAnalog(status.gyro.z, false); + + return status; +} + +Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) { + Input::StickStatus status{}; + + switch (callback.type) { + case Input::InputType::Stick: + status = callback.stick_status; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to stick not implemented", callback.type); + break; + } + + SanitizeStick(status.x, status.y, true); + const Input::AnalogProperties& properties_x = status.x.properties; + const Input::AnalogProperties& properties_y = status.y.properties; + const float x = status.x.value; + const float y = status.y.value; + + // Set directional buttons + status.right = x > properties_x.threshold; + status.left = x < -properties_x.threshold; + status.up = y > properties_y.threshold; + status.down = y < -properties_y.threshold; + + return status; +} + +Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback) { + Input::TouchStatus status{}; + + switch (callback.type) { + case Input::InputType::Touch: + status = callback.touch_status; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type); + break; + } + + SanitizeAnalog(status.x, true); + SanitizeAnalog(status.y, true); + float& x = status.x.value; + float& y = status.y.value; + + // Adjust if value is inverted + x = status.x.properties.inverted ? 1.0f + x : x; + y = status.y.properties.inverted ? 1.0f + y : y; + + // clamp value + x = std::clamp(x, 0.0f, 1.0f); + y = std::clamp(y, 0.0f, 1.0f); + + if (status.pressed.inverted) { + status.pressed.value = !status.pressed.value; + } + + return status; +} + +Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) { + Input::TriggerStatus status{}; + float& raw_value = status.analog.raw_value; + bool calculate_button_value = true; + + switch (callback.type) { + case Input::InputType::Analog: + status.analog.properties = callback.analog_status.properties; + raw_value = callback.analog_status.raw_value; + break; + case Input::InputType::Button: + status.analog.properties.range = 1.0f; + status.analog.properties.inverted = callback.button_status.inverted; + raw_value = callback.button_status.value ? 1.0f : 0.0f; + break; + case Input::InputType::Trigger: + status = callback.trigger_status; + calculate_button_value = false; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to trigger not implemented", callback.type); + break; + } + + SanitizeAnalog(status.analog, true); + const Input::AnalogProperties& properties = status.analog.properties; + float& value = status.analog.value; + + // Set button status + if (calculate_button_value) { + status.pressed = value > properties.threshold; + } + + // Adjust if value is inverted + value = properties.inverted ? 1.0f + value : value; + + // clamp value + value = std::clamp(value, 0.0f, 1.0f); + + return status; +} + +void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) { + const Input::AnalogProperties& properties = analog.properties; + float& raw_value = analog.raw_value; + float& value = analog.value; + + if (!std::isnormal(raw_value)) { + raw_value = 0; + } + + // Apply center offset + raw_value -= properties.offset; + + // Set initial values to be formated + value = raw_value; + + // Calculate vector size + const float r = std::abs(value); + + // Return zero if value is smaller than the deadzone + if (r <= properties.deadzone || properties.deadzone == 1.0f) { + analog.value = 0; + return; + } + + // Adjust range of value + const float deadzone_factor = + 1.0f / r * (r - properties.deadzone) / (1.0f - properties.deadzone); + value = value * deadzone_factor / properties.range; + + // Invert direction if needed + if (properties.inverted) { + value = -value; + } + + // Clamp value + if (clamp_value) { + value = std::clamp(value, -1.0f, 1.0f); + } +} + +void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value) { + const Input::AnalogProperties& properties_x = analog_x.properties; + const Input::AnalogProperties& properties_y = analog_y.properties; + float& raw_x = analog_x.raw_value; + float& raw_y = analog_y.raw_value; + float& x = analog_x.value; + float& y = analog_y.value; + + if (!std::isnormal(raw_x)) { + raw_x = 0; + } + if (!std::isnormal(raw_y)) { + raw_y = 0; + } + + // Apply center offset + raw_x += properties_x.offset; + raw_y += properties_y.offset; + + // Apply X scale correction from offset + if (std::abs(properties_x.offset) < 0.5f) { + if (raw_x > 0) { + raw_x /= 1 + properties_x.offset; + } else { + raw_x /= 1 - properties_x.offset; + } + } + + // Apply Y scale correction from offset + if (std::abs(properties_y.offset) < 0.5f) { + if (raw_y > 0) { + raw_y /= 1 + properties_y.offset; + } else { + raw_y /= 1 - properties_y.offset; + } + } + + // Invert direction if needed + raw_x = properties_x.inverted ? -raw_x : raw_x; + raw_y = properties_y.inverted ? -raw_y : raw_y; + + // Set initial values to be formated + x = raw_x; + y = raw_y; + + // Calculate vector size + float r = x * x + y * y; + r = std::sqrt(r); + + // TODO(German77): Use deadzone and range of both axis + + // Return zero if values are smaller than the deadzone + if (r <= properties_x.deadzone || properties_x.deadzone >= 1.0f) { + x = 0; + y = 0; + return; + } + + // Adjust range of joystick + const float deadzone_factor = + 1.0f / r * (r - properties_x.deadzone) / (1.0f - properties_x.deadzone); + x = x * deadzone_factor / properties_x.range; + y = y * deadzone_factor / properties_x.range; + r = r * deadzone_factor / properties_x.range; + + // Normalize joystick + if (clamp_value && r > 1.0f) { + x /= r; + y /= r; + } +} + +} // namespace Core::HID diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h new file mode 100644 index 000000000..3cc32e26a --- /dev/null +++ b/src/core/hid/input_converter.h @@ -0,0 +1,77 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#pragma once + +namespace Input { +struct CallbackStatus; +}; + +namespace Core::HID { + +/** + * Converts raw input data into a valid battery status. + * + * @param Supported callbacks: Analog, Battery, Trigger. + * @return A valid BatteryStatus object. + */ +Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback); + +/** + * Converts raw input data into a valid button status. Applies invert properties to the output. + * + * @param Supported callbacks: Analog, Button, Trigger. + * @return A valid TouchStatus object. + */ +Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback); + +/** + * Converts raw input data into a valid motion status. + * + * @param Supported callbacks: Motion. + * @return A valid TouchStatus object. + */ +Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback); + +/** + * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert + * properties to the output. + * + * @param Supported callbacks: Stick. + * @return A valid StickStatus object. + */ +Input::StickStatus TransformToStick(const Input::CallbackStatus& callback); + +/** + * Converts raw input data into a valid touch status. + * + * @param Supported callbacks: Touch. + * @return A valid TouchStatus object. + */ +Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback); + +/** + * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and + * invert properties to the output. Button status uses the threshold property if necessary. + * + * @param Supported callbacks: Analog, Button, Trigger. + * @return A valid TriggerStatus object. + */ +Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback); + +/** + * Converts raw analog data into a valid analog value + * @param An analog object containing raw data and properties, bool that determines if the value + * needs to be clamped between -1.0f and 1.0f. + */ +void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value); + +/** + * Converts raw stick data into a valid stick value + * @param Two analog objects containing raw data and properties, bool that determines if the value + * needs to be clamped into the unit circle. + */ +void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value); + +} // namespace Core::HID diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp new file mode 100644 index 000000000..93f37b77b --- /dev/null +++ b/src/core/hid/motion_input.cpp @@ -0,0 +1,278 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include "common/math_util.h" +#include "core/hid/motion_input.h" + +namespace Core::HID { + +MotionInput::MotionInput() { + // Initialize PID constants with default values + SetPID(0.3f, 0.005f, 0.0f); +} + +void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { + kp = new_kp; + ki = new_ki; + kd = new_kd; +} + +void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { + accel = acceleration; +} + +void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { + gyro = gyroscope - gyro_drift; + + // Auto adjust drift to minimize drift + if (!IsMoving(0.1f)) { + gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f); + } + + if (gyro.Length2() < gyro_threshold) { + gyro = {}; + } else { + only_accelerometer = false; + } +} + +void MotionInput::SetQuaternion(const Common::Quaternion& quaternion) { + quat = quaternion; +} + +void MotionInput::SetGyroDrift(const Common::Vec3f& drift) { + gyro_drift = drift; +} + +void MotionInput::SetGyroThreshold(f32 threshold) { + gyro_threshold = threshold; +} + +void MotionInput::EnableReset(bool reset) { + reset_enabled = reset; +} + +void MotionInput::ResetRotations() { + rotations = {}; +} + +bool MotionInput::IsMoving(f32 sensitivity) const { + return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f; +} + +bool MotionInput::IsCalibrated(f32 sensitivity) const { + return real_error.Length() < sensitivity; +} + +void MotionInput::UpdateRotation(u64 elapsed_time) { + const auto sample_period = static_cast(elapsed_time) / 1000000.0f; + if (sample_period > 0.1f) { + return; + } + rotations += gyro * sample_period; +} + +void MotionInput::UpdateOrientation(u64 elapsed_time) { + if (!IsCalibrated(0.1f)) { + ResetOrientation(); + } + // Short name local variable for readability + f32 q1 = quat.w; + f32 q2 = quat.xyz[0]; + f32 q3 = quat.xyz[1]; + f32 q4 = quat.xyz[2]; + const auto sample_period = static_cast(elapsed_time) / 1000000.0f; + + // Ignore invalid elapsed time + if (sample_period > 0.1f) { + return; + } + + const auto normal_accel = accel.Normalized(); + auto rad_gyro = gyro * Common::PI * 2; + const f32 swap = rad_gyro.x; + rad_gyro.x = rad_gyro.y; + rad_gyro.y = -swap; + rad_gyro.z = -rad_gyro.z; + + // Clear gyro values if there is no gyro present + if (only_accelerometer) { + rad_gyro.x = 0; + rad_gyro.y = 0; + rad_gyro.z = 0; + } + + // Ignore drift correction if acceleration is not reliable + if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) { + const f32 ax = -normal_accel.x; + const f32 ay = normal_accel.y; + const f32 az = -normal_accel.z; + + // Estimated direction of gravity + const f32 vx = 2.0f * (q2 * q4 - q1 * q3); + const f32 vy = 2.0f * (q1 * q2 + q3 * q4); + const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; + + // Error is cross product between estimated direction and measured direction of gravity + const Common::Vec3f new_real_error = { + az * vx - ax * vz, + ay * vz - az * vy, + ax * vy - ay * vx, + }; + + derivative_error = new_real_error - real_error; + real_error = new_real_error; + + // Prevent integral windup + if (ki != 0.0f && !IsCalibrated(0.05f)) { + integral_error += real_error; + } else { + integral_error = {}; + } + + // Apply feedback terms + if (!only_accelerometer) { + rad_gyro += kp * real_error; + rad_gyro += ki * integral_error; + rad_gyro += kd * derivative_error; + } else { + // Give more weight to accelerometer values to compensate for the lack of gyro + rad_gyro += 35.0f * kp * real_error; + rad_gyro += 10.0f * ki * integral_error; + rad_gyro += 10.0f * kd * derivative_error; + + // Emulate gyro values for games that need them + gyro.x = -rad_gyro.y; + gyro.y = rad_gyro.x; + gyro.z = -rad_gyro.z; + UpdateRotation(elapsed_time); + } + } + + const f32 gx = rad_gyro.y; + const f32 gy = rad_gyro.x; + const f32 gz = rad_gyro.z; + + // Integrate rate of change of quaternion + const f32 pa = q2; + const f32 pb = q3; + const f32 pc = q4; + q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period); + q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period); + q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); + q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); + + quat.w = q1; + quat.xyz[0] = q2; + quat.xyz[1] = q3; + quat.xyz[2] = q4; + quat = quat.Normalized(); +} + +std::array MotionInput::GetOrientation() const { + const Common::Quaternion quad{ + .xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w}, + .w = -quat.xyz[2], + }; + const std::array matrix4x4 = quad.ToMatrix(); + + return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]), + Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]), + Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])}; +} + +Common::Vec3f MotionInput::GetAcceleration() const { + return accel; +} + +Common::Vec3f MotionInput::GetGyroscope() const { + return gyro; +} + +Common::Quaternion MotionInput::GetQuaternion() const { + return quat; +} + +Common::Vec3f MotionInput::GetRotations() const { + return rotations; +} + +void MotionInput::ResetOrientation() { + if (!reset_enabled || only_accelerometer) { + return; + } + if (!IsMoving(0.5f) && accel.z <= -0.9f) { + ++reset_counter; + if (reset_counter > 900) { + quat.w = 0; + quat.xyz[0] = 0; + quat.xyz[1] = 0; + quat.xyz[2] = -1; + SetOrientationFromAccelerometer(); + integral_error = {}; + reset_counter = 0; + } + } else { + reset_counter = 0; + } +} + +void MotionInput::SetOrientationFromAccelerometer() { + int iterations = 0; + const f32 sample_period = 0.015f; + + const auto normal_accel = accel.Normalized(); + + while (!IsCalibrated(0.01f) && ++iterations < 100) { + // Short name local variable for readability + f32 q1 = quat.w; + f32 q2 = quat.xyz[0]; + f32 q3 = quat.xyz[1]; + f32 q4 = quat.xyz[2]; + + Common::Vec3f rad_gyro; + const f32 ax = -normal_accel.x; + const f32 ay = normal_accel.y; + const f32 az = -normal_accel.z; + + // Estimated direction of gravity + const f32 vx = 2.0f * (q2 * q4 - q1 * q3); + const f32 vy = 2.0f * (q1 * q2 + q3 * q4); + const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; + + // Error is cross product between estimated direction and measured direction of gravity + const Common::Vec3f new_real_error = { + az * vx - ax * vz, + ay * vz - az * vy, + ax * vy - ay * vx, + }; + + derivative_error = new_real_error - real_error; + real_error = new_real_error; + + rad_gyro += 10.0f * kp * real_error; + rad_gyro += 5.0f * ki * integral_error; + rad_gyro += 10.0f * kd * derivative_error; + + const f32 gx = rad_gyro.y; + const f32 gy = rad_gyro.x; + const f32 gz = rad_gyro.z; + + // Integrate rate of change of quaternion + const f32 pa = q2; + const f32 pb = q3; + const f32 pc = q4; + q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period); + q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period); + q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); + q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); + + quat.w = q1; + quat.xyz[0] = q2; + quat.xyz[1] = q3; + quat.xyz[2] = q4; + quat = quat.Normalized(); + } +} +} // namespace Core::HID diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h new file mode 100644 index 000000000..3deef5ac3 --- /dev/null +++ b/src/core/hid/motion_input.h @@ -0,0 +1,71 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#pragma once + +#include "common/common_types.h" +#include "common/quaternion.h" +#include "common/vector_math.h" + +namespace Core::HID { + +class MotionInput { +public: + explicit MotionInput(); + + MotionInput(const MotionInput&) = default; + MotionInput& operator=(const MotionInput&) = default; + + MotionInput(MotionInput&&) = default; + MotionInput& operator=(MotionInput&&) = default; + + void SetPID(f32 new_kp, f32 new_ki, f32 new_kd); + void SetAcceleration(const Common::Vec3f& acceleration); + void SetGyroscope(const Common::Vec3f& gyroscope); + void SetQuaternion(const Common::Quaternion& quaternion); + void SetGyroDrift(const Common::Vec3f& drift); + void SetGyroThreshold(f32 threshold); + + void EnableReset(bool reset); + void ResetRotations(); + + void UpdateRotation(u64 elapsed_time); + void UpdateOrientation(u64 elapsed_time); + + [[nodiscard]] std::array GetOrientation() const; + [[nodiscard]] Common::Vec3f GetAcceleration() const; + [[nodiscard]] Common::Vec3f GetGyroscope() const; + [[nodiscard]] Common::Vec3f GetRotations() const; + [[nodiscard]] Common::Quaternion GetQuaternion() const; + + [[nodiscard]] bool IsMoving(f32 sensitivity) const; + [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; + +private: + void ResetOrientation(); + void SetOrientationFromAccelerometer(); + + // PID constants + f32 kp; + f32 ki; + f32 kd; + + // PID errors + Common::Vec3f real_error; + Common::Vec3f integral_error; + Common::Vec3f derivative_error; + + Common::Quaternion quat{{0.0f, 0.0f, -1.0f}, 0.0f}; + Common::Vec3f rotations; + Common::Vec3f accel; + Common::Vec3f gyro; + Common::Vec3f gyro_drift; + + f32 gyro_threshold = 0.0f; + u32 reset_counter = 0; + bool reset_enabled = true; + bool only_accelerometer = true; +}; + +} // namespace Core::HID -- cgit v1.2.3 From c3f54ff2329d79bdbb273678b5123cf0b1cd090c Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 19:43:16 -0500 Subject: core/hid: Add emulated controllers --- src/core/CMakeLists.txt | 8 + src/core/hid/emulated_console.cpp | 208 ++++++++++ src/core/hid/emulated_console.h | 142 +++++++ src/core/hid/emulated_controller.cpp | 745 +++++++++++++++++++++++++++++++++++ src/core/hid/emulated_controller.h | 232 +++++++++++ src/core/hid/emulated_devices.cpp | 349 ++++++++++++++++ src/core/hid/emulated_devices.h | 137 +++++++ src/core/hid/hid_core.cpp | 144 +++++++ src/core/hid/hid_core.h | 60 +++ 9 files changed, 2025 insertions(+) create mode 100644 src/core/hid/emulated_console.cpp create mode 100644 src/core/hid/emulated_console.h create mode 100644 src/core/hid/emulated_controller.cpp create mode 100644 src/core/hid/emulated_controller.h create mode 100644 src/core/hid/emulated_devices.cpp create mode 100644 src/core/hid/emulated_devices.h create mode 100644 src/core/hid/hid_core.cpp create mode 100644 src/core/hid/hid_core.h (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index eddf455c0..09163fab9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -135,6 +135,14 @@ add_library(core STATIC frontend/input.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h + hid/emulated_console.cpp + hid/emulated_console.h + hid/emulated_controller.cpp + hid/emulated_controller.h + hid/emulated_devices.cpp + hid/emulated_devices.h + hid/hid_core.cpp + hid/hid_core.h hid/hid_types.h hid/input_converter.cpp hid/input_converter.h diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp new file mode 100644 index 000000000..c65d05041 --- /dev/null +++ b/src/core/hid/emulated_console.cpp @@ -0,0 +1,208 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include + +#include "core/hid/emulated_console.h" +#include "core/hid/input_converter.h" + +namespace Core::HID { +EmulatedConsole::EmulatedConsole() {} + +EmulatedConsole::~EmulatedConsole() = default; + +void EmulatedConsole::ReloadFromSettings() { + // Using first motion device from player 1. No need to assign a special config at the moment + const auto& player = Settings::values.players.GetValue()[0]; + motion_params = Common::ParamPackage(player.motions[0]); + + ReloadInput(); +} + +void EmulatedConsole::ReloadInput() { + motion_devices = Input::CreateDevice(motion_params); + if (motion_devices) { + Input::InputCallback motion_callback{ + [this](Input::CallbackStatus callback) { SetMotion(callback); }}; + motion_devices->SetCallback(motion_callback); + } + + // TODO: Fix this mess + std::size_t index = 0; + const std::string mouse_device_string = + fmt::format("engine:mouse,axis_x:10,axis_y:11,button:{}", index); + touch_devices[index] = Input::CreateDeviceFromString(mouse_device_string); + Input::InputCallback trigger_callbackk{ + [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }}; + touch_devices[index]->SetCallback(trigger_callbackk); + + index++; + const auto button_index = + static_cast(Settings::values.touch_from_button_map_index.GetValue()); + const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons; + for (const auto& config_entry : touch_buttons) { + Common::ParamPackage params{config_entry}; + Common::ParamPackage touch_button_params; + const int x = params.Get("x", 0); + const int y = params.Get("y", 0); + params.Erase("x"); + params.Erase("y"); + touch_button_params.Set("engine", "touch_from_button"); + touch_button_params.Set("button", params.Serialize()); + touch_button_params.Set("x", x); + touch_button_params.Set("y", y); + touch_button_params.Set("touch_id", static_cast(index)); + LOG_ERROR(Common, "{} ", touch_button_params.Serialize()); + touch_devices[index] = + Input::CreateDeviceFromString(touch_button_params.Serialize()); + if (!touch_devices[index]) { + continue; + } + + Input::InputCallback trigger_callback{ + [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }}; + touch_devices[index]->SetCallback(trigger_callback); + index++; + } +} + +void EmulatedConsole::UnloadInput() { + motion_devices.reset(); + for (auto& touch : touch_devices) { + touch.reset(); + } +} + +void EmulatedConsole::EnableConfiguration() { + is_configuring = true; + SaveCurrentConfig(); +} + +void EmulatedConsole::DisableConfiguration() { + is_configuring = false; +} + +bool EmulatedConsole::IsConfiguring() const { + return is_configuring; +} + +void EmulatedConsole::SaveCurrentConfig() { + if (!is_configuring) { + return; + } +} + +void EmulatedConsole::RestoreConfig() { + if (!is_configuring) { + return; + } + ReloadFromSettings(); +} + +Common::ParamPackage EmulatedConsole::GetMotionParam() const { + return motion_params; +} + +void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { + motion_params = param; + ReloadInput(); +} + +void EmulatedConsole::SetMotion(Input::CallbackStatus callback) { + std::lock_guard lock{mutex}; + auto& raw_status = console.motion_values.raw_status; + auto& emulated = console.motion_values.emulated; + + raw_status = TransformToMotion(callback); + emulated.SetAcceleration(Common::Vec3f{ + raw_status.accel.x.value, + raw_status.accel.y.value, + raw_status.accel.z.value, + }); + emulated.SetGyroscope(Common::Vec3f{ + raw_status.gyro.x.value, + raw_status.gyro.y.value, + raw_status.gyro.z.value, + }); + emulated.UpdateRotation(raw_status.delta_timestamp); + emulated.UpdateOrientation(raw_status.delta_timestamp); + + if (is_configuring) { + TriggerOnChange(ConsoleTriggerType::Motion); + return; + } + + auto& motion = console.motion_state; + motion.accel = emulated.GetAcceleration(); + motion.gyro = emulated.GetGyroscope(); + motion.rotation = emulated.GetGyroscope(); + motion.orientation = emulated.GetOrientation(); + motion.quaternion = emulated.GetQuaternion(); + motion.is_at_rest = emulated.IsMoving(motion_sensitivity); + + TriggerOnChange(ConsoleTriggerType::Motion); +} + +void EmulatedConsole::SetTouch(Input::CallbackStatus callback, [[maybe_unused]] std::size_t index) { + if (index >= console.touch_values.size()) { + return; + } + std::lock_guard lock{mutex}; + + console.touch_values[index] = TransformToTouch(callback); + + if (is_configuring) { + TriggerOnChange(ConsoleTriggerType::Touch); + return; + } + + console.touch_state[index] = { + .position = {console.touch_values[index].x.value, console.touch_values[index].y.value}, + .id = console.touch_values[index].id, + .pressed = console.touch_values[index].pressed.value, + }; + + TriggerOnChange(ConsoleTriggerType::Touch); +} + +ConsoleMotionValues EmulatedConsole::GetMotionValues() const { + return console.motion_values; +} + +TouchValues EmulatedConsole::GetTouchValues() const { + return console.touch_values; +} + +ConsoleMotion EmulatedConsole::GetMotion() const { + return console.motion_state; +} + +TouchFingerState EmulatedConsole::GetTouch() const { + return console.touch_state; +} + +void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { + for (const std::pair poller_pair : callback_list) { + const ConsoleUpdateCallback& poller = poller_pair.second; + if (poller.on_change) { + poller.on_change(type); + } + } +} + +int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { + std::lock_guard lock{mutex}; + callback_list.insert_or_assign(last_callback_key, update_callback); + return last_callback_key++; +} + +void EmulatedConsole::DeleteCallback(int key) { + std::lock_guard lock{mutex}; + if (!callback_list.contains(key)) { + LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); + return; + } + callback_list.erase(key); +} +} // namespace Core::HID diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h new file mode 100644 index 000000000..d9e275042 --- /dev/null +++ b/src/core/hid/emulated_console.h @@ -0,0 +1,142 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "common/input.h" +#include "common/param_package.h" +#include "common/point.h" +#include "common/quaternion.h" +#include "common/settings.h" +#include "common/vector_math.h" +#include "core/hid/hid_types.h" +#include "core/hid/motion_input.h" + +namespace Core::HID { + +struct ConsoleMotionInfo { + Input::MotionStatus raw_status; + MotionInput emulated{}; +}; + +using ConsoleMotionDevices = std::unique_ptr; +using TouchDevices = std::array, 16>; + +using ConsoleMotionParams = Common::ParamPackage; +using TouchParams = std::array; + +using ConsoleMotionValues = ConsoleMotionInfo; +using TouchValues = std::array; + +struct TouchFinger { + u64_le last_touch{}; + Common::Point position{}; + u32_le id{}; + bool pressed{}; + Core::HID::TouchAttribute attribute{}; +}; + +struct ConsoleMotion { + bool is_at_rest{}; + Common::Vec3f accel{}; + Common::Vec3f gyro{}; + Common::Vec3f rotation{}; + std::array orientation{}; + Common::Quaternion quaternion{}; +}; + +using TouchFingerState = std::array; + +struct ConsoleStatus { + // Data from input_common + ConsoleMotionValues motion_values{}; + TouchValues touch_values{}; + + // Data for Nintendo devices; + ConsoleMotion motion_state{}; + TouchFingerState touch_state{}; +}; + +enum class ConsoleTriggerType { + Motion, + Touch, + All, +}; + +struct ConsoleUpdateCallback { + std::function on_change; +}; + +class EmulatedConsole { +public: + /** + * TODO: Write description + * + * @param npad_id_type + */ + explicit EmulatedConsole(); + ~EmulatedConsole(); + + YUZU_NON_COPYABLE(EmulatedConsole); + YUZU_NON_MOVEABLE(EmulatedConsole); + + void ReloadFromSettings(); + void ReloadInput(); + void UnloadInput(); + + void EnableConfiguration(); + void DisableConfiguration(); + bool IsConfiguring() const; + void SaveCurrentConfig(); + void RestoreConfig(); + + Common::ParamPackage GetMotionParam() const; + + void SetMotionParam(Common::ParamPackage param); + + ConsoleMotionValues GetMotionValues() const; + TouchValues GetTouchValues() const; + + ConsoleMotion GetMotion() const; + TouchFingerState GetTouch() const; + + int SetCallback(ConsoleUpdateCallback update_callback); + void DeleteCallback(int key); + +private: + /** + * Sets the status of a button. Applies toggle properties to the output. + * + * @param A CallbackStatus and a button index number + */ + void SetMotion(Input::CallbackStatus callback); + void SetTouch(Input::CallbackStatus callback, std::size_t index); + + /** + * Triggers a callback that something has changed + * + * @param Input type of the trigger + */ + void TriggerOnChange(ConsoleTriggerType type); + + bool is_configuring{false}; + f32 motion_sensitivity{0.01f}; + + ConsoleMotionParams motion_params; + TouchParams touch_params; + + ConsoleMotionDevices motion_devices; + TouchDevices touch_devices; + + mutable std::mutex mutex; + std::unordered_map callback_list; + int last_callback_key = 0; + ConsoleStatus console; +}; + +} // namespace Core::HID diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp new file mode 100644 index 000000000..4eb5d99bc --- /dev/null +++ b/src/core/hid/emulated_controller.cpp @@ -0,0 +1,745 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include + +#include "core/hid/emulated_controller.h" +#include "core/hid/input_converter.h" + +namespace Core::HID { +constexpr s32 HID_JOYSTICK_MAX = 0x7fff; +constexpr s32 HID_TRIGGER_MAX = 0x7fff; + +EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {} + +EmulatedController::~EmulatedController() = default; + +NpadType EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { + switch (type) { + case Settings::ControllerType::ProController: + return NpadType::ProController; + case Settings::ControllerType::DualJoyconDetached: + return NpadType::JoyconDual; + case Settings::ControllerType::LeftJoycon: + return NpadType::JoyconLeft; + case Settings::ControllerType::RightJoycon: + return NpadType::JoyconRight; + case Settings::ControllerType::Handheld: + return NpadType::Handheld; + case Settings::ControllerType::GameCube: + return NpadType::GameCube; + default: + return NpadType::ProController; + } +} + +Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type) { + switch (type) { + case NpadType::ProController: + return Settings::ControllerType::ProController; + case NpadType::JoyconDual: + return Settings::ControllerType::DualJoyconDetached; + case NpadType::JoyconLeft: + return Settings::ControllerType::LeftJoycon; + case NpadType::JoyconRight: + return Settings::ControllerType::RightJoycon; + case NpadType::Handheld: + return Settings::ControllerType::Handheld; + case NpadType::GameCube: + return Settings::ControllerType::GameCube; + default: + return Settings::ControllerType::ProController; + } +} + +void EmulatedController::ReloadFromSettings() { + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + + for (std::size_t index = 0; index < player.buttons.size(); ++index) { + button_params[index] = Common::ParamPackage(player.buttons[index]); + } + for (std::size_t index = 0; index < player.analogs.size(); ++index) { + stick_params[index] = Common::ParamPackage(player.analogs[index]); + } + for (std::size_t index = 0; index < player.motions.size(); ++index) { + motion_params[index] = Common::ParamPackage(player.motions[index]); + } + ReloadInput(); +} + +void EmulatedController::ReloadInput() { + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + const auto left_side = button_params[Settings::NativeButton::ZL]; + const auto right_side = button_params[Settings::NativeButton::ZR]; + + std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, + button_params.begin() + Settings::NativeButton::BUTTON_NS_END, + button_devices.begin(), Input::CreateDevice); + std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, + stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, + stick_devices.begin(), Input::CreateDevice); + std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, + motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, + motion_devices.begin(), Input::CreateDevice); + + trigger_devices[0] = + Input::CreateDevice(button_params[Settings::NativeButton::ZL]); + trigger_devices[1] = + Input::CreateDevice(button_params[Settings::NativeButton::ZR]); + + controller.colors_state.left = { + .body = player.body_color_left, + .button = player.button_color_left, + }; + + controller.colors_state.right = { + .body = player.body_color_right, + .button = player.button_color_right, + }; + + controller.colors_state.fullkey = controller.colors_state.left; + + battery_devices[0] = Input::CreateDevice(left_side); + battery_devices[1] = Input::CreateDevice(right_side); + + for (std::size_t index = 0; index < button_devices.size(); ++index) { + if (!button_devices[index]) { + continue; + } + Input::InputCallback button_callback{ + [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + button_devices[index]->SetCallback(button_callback); + } + + for (std::size_t index = 0; index < stick_devices.size(); ++index) { + if (!stick_devices[index]) { + continue; + } + Input::InputCallback stick_callback{ + [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + stick_devices[index]->SetCallback(stick_callback); + } + + for (std::size_t index = 0; index < trigger_devices.size(); ++index) { + if (!trigger_devices[index]) { + continue; + } + Input::InputCallback trigger_callback{ + [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }}; + trigger_devices[index]->SetCallback(trigger_callback); + } + + for (std::size_t index = 0; index < battery_devices.size(); ++index) { + if (!battery_devices[index]) { + continue; + } + Input::InputCallback battery_callback{ + [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }}; + battery_devices[index]->SetCallback(battery_callback); + } + + for (std::size_t index = 0; index < motion_devices.size(); ++index) { + if (!motion_devices[index]) { + continue; + } + Input::InputCallback motion_callback{ + [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; + motion_devices[index]->SetCallback(motion_callback); + } + + SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + + if (player.connected) { + Connect(); + } else { + Disconnect(); + } +} + +void EmulatedController::UnloadInput() { + for (auto& button : button_devices) { + button.reset(); + } + for (auto& stick : stick_devices) { + stick.reset(); + } + for (auto& motion : motion_devices) { + motion.reset(); + } + for (auto& trigger : trigger_devices) { + trigger.reset(); + } + for (auto& battery : battery_devices) { + battery.reset(); + } +} + +void EmulatedController::EnableConfiguration() { + is_configuring = true; + SaveCurrentConfig(); +} + +void EmulatedController::DisableConfiguration() { + is_configuring = false; +} + +bool EmulatedController::IsConfiguring() const { + return is_configuring; +} + +void EmulatedController::SaveCurrentConfig() { + if (!is_configuring) { + return; + } + + const auto player_index = NpadIdTypeToIndex(npad_id_type); + auto& player = Settings::values.players.GetValue()[player_index]; + + for (std::size_t index = 0; index < player.buttons.size(); ++index) { + player.buttons[index] = button_params[index].Serialize(); + } + for (std::size_t index = 0; index < player.analogs.size(); ++index) { + player.analogs[index] = stick_params[index].Serialize(); + } + for (std::size_t index = 0; index < player.motions.size(); ++index) { + player.motions[index] = motion_params[index].Serialize(); + } +} + +void EmulatedController::RestoreConfig() { + if (!is_configuring) { + return; + } + ReloadFromSettings(); +} + +std::vector EmulatedController::GetMappedDevices() const { + std::vector devices; + for (const auto& param : button_params) { + if (!param.Has("engine")) { + continue; + } + const auto devices_it = std::find_if( + devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { + return param.Get("engine", "") == param_.Get("engine", "") && + param.Get("guid", "") == param_.Get("guid", "") && + param.Get("port", "") == param_.Get("port", ""); + }); + if (devices_it != devices.end()) { + continue; + } + Common::ParamPackage device{}; + device.Set("engine", param.Get("engine", "")); + device.Set("guid", param.Get("guid", "")); + device.Set("port", param.Get("port", "")); + devices.push_back(device); + } + + for (const auto& param : stick_params) { + if (!param.Has("engine")) { + continue; + } + if (param.Get("engine", "") == "analog_from_button") { + continue; + } + const auto devices_it = std::find_if( + devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { + return param.Get("engine", "") == param_.Get("engine", "") && + param.Get("guid", "") == param_.Get("guid", "") && + param.Get("port", "") == param_.Get("port", ""); + }); + if (devices_it != devices.end()) { + continue; + } + Common::ParamPackage device{}; + device.Set("engine", param.Get("engine", "")); + device.Set("guid", param.Get("guid", "")); + device.Set("port", param.Get("port", "")); + devices.push_back(device); + } + return devices; +} + +Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const { + if (index >= button_params.size()) { + return {}; + } + return button_params[index]; +} + +Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const { + if (index >= stick_params.size()) { + return {}; + } + return stick_params[index]; +} + +Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const { + if (index >= motion_params.size()) { + return {}; + } + return motion_params[index]; +} + +void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) { + if (index >= button_params.size()) { + return; + } + button_params[index] = param; + ReloadInput(); +} + +void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) { + if (index >= stick_params.size()) { + return; + } + stick_params[index] = param; + ReloadInput(); +} + +void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) { + if (index >= motion_params.size()) { + return; + } + motion_params[index] = param; + ReloadInput(); +} + +void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.button_values.size()) { + return; + } + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = controller.button_values[index]; + current_status.toggle = new_status.toggle; + + // Update button status with current + if (!current_status.toggle) { + current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } + } + + if (!value_changed) { + return; + } + + if (is_configuring) { + controller.npad_button_state.raw = NpadButton::None; + controller.debug_pad_button_state.raw = 0; + TriggerOnChange(ControllerTriggerType::Button); + return; + } + + switch (index) { + case Settings::NativeButton::A: + controller.npad_button_state.a.Assign(current_status.value); + controller.debug_pad_button_state.a.Assign(current_status.value); + break; + case Settings::NativeButton::B: + controller.npad_button_state.b.Assign(current_status.value); + controller.debug_pad_button_state.b.Assign(current_status.value); + break; + case Settings::NativeButton::X: + controller.npad_button_state.x.Assign(current_status.value); + controller.debug_pad_button_state.x.Assign(current_status.value); + break; + case Settings::NativeButton::Y: + controller.npad_button_state.y.Assign(current_status.value); + controller.debug_pad_button_state.y.Assign(current_status.value); + break; + case Settings::NativeButton::LStick: + controller.npad_button_state.stick_l.Assign(current_status.value); + break; + case Settings::NativeButton::RStick: + controller.npad_button_state.stick_r.Assign(current_status.value); + break; + case Settings::NativeButton::L: + controller.npad_button_state.l.Assign(current_status.value); + controller.debug_pad_button_state.l.Assign(current_status.value); + break; + case Settings::NativeButton::R: + controller.npad_button_state.r.Assign(current_status.value); + controller.debug_pad_button_state.r.Assign(current_status.value); + break; + case Settings::NativeButton::ZL: + controller.npad_button_state.zl.Assign(current_status.value); + controller.debug_pad_button_state.zl.Assign(current_status.value); + break; + case Settings::NativeButton::ZR: + controller.npad_button_state.zr.Assign(current_status.value); + controller.debug_pad_button_state.zr.Assign(current_status.value); + break; + case Settings::NativeButton::Plus: + controller.npad_button_state.plus.Assign(current_status.value); + controller.debug_pad_button_state.plus.Assign(current_status.value); + break; + case Settings::NativeButton::Minus: + controller.npad_button_state.minus.Assign(current_status.value); + controller.debug_pad_button_state.minus.Assign(current_status.value); + break; + case Settings::NativeButton::DLeft: + controller.npad_button_state.left.Assign(current_status.value); + controller.debug_pad_button_state.d_left.Assign(current_status.value); + break; + case Settings::NativeButton::DUp: + controller.npad_button_state.up.Assign(current_status.value); + controller.debug_pad_button_state.d_up.Assign(current_status.value); + break; + case Settings::NativeButton::DRight: + controller.npad_button_state.right.Assign(current_status.value); + controller.debug_pad_button_state.d_right.Assign(current_status.value); + break; + case Settings::NativeButton::DDown: + controller.npad_button_state.down.Assign(current_status.value); + controller.debug_pad_button_state.d_down.Assign(current_status.value); + break; + case Settings::NativeButton::SL: + controller.npad_button_state.left_sl.Assign(current_status.value); + controller.npad_button_state.right_sl.Assign(current_status.value); + break; + case Settings::NativeButton::SR: + controller.npad_button_state.left_sr.Assign(current_status.value); + controller.npad_button_state.right_sr.Assign(current_status.value); + break; + case Settings::NativeButton::Home: + case Settings::NativeButton::Screenshot: + break; + } + TriggerOnChange(ControllerTriggerType::Button); +} + +void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.stick_values.size()) { + return; + } + std::lock_guard lock{mutex}; + controller.stick_values[index] = TransformToStick(callback); + + if (is_configuring) { + controller.analog_stick_state.left = {}; + controller.analog_stick_state.right = {}; + TriggerOnChange(ControllerTriggerType::Stick); + return; + } + + const AnalogStickState stick{ + .x = static_cast(controller.stick_values[index].x.value * HID_JOYSTICK_MAX), + .y = static_cast(controller.stick_values[index].y.value * HID_JOYSTICK_MAX), + }; + + switch (index) { + case Settings::NativeAnalog::LStick: + controller.analog_stick_state.left = stick; + controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left); + controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up); + controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right); + controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down); + break; + case Settings::NativeAnalog::RStick: + controller.analog_stick_state.right = stick; + controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left); + controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up); + controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right); + controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); + break; + } + + TriggerOnChange(ControllerTriggerType::Stick); +} + +void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.trigger_values.size()) { + return; + } + std::lock_guard lock{mutex}; + controller.trigger_values[index] = TransformToTrigger(callback); + + if (is_configuring) { + controller.gc_trigger_state.left = 0; + controller.gc_trigger_state.right = 0; + TriggerOnChange(ControllerTriggerType::Trigger); + return; + } + + const auto trigger = controller.trigger_values[index]; + + switch (index) { + case Settings::NativeTrigger::LTrigger: + controller.gc_trigger_state.left = static_cast(trigger.analog.value * HID_TRIGGER_MAX); + controller.npad_button_state.zl.Assign(trigger.pressed); + break; + case Settings::NativeTrigger::RTrigger: + controller.gc_trigger_state.right = + static_cast(trigger.analog.value * HID_TRIGGER_MAX); + controller.npad_button_state.zr.Assign(trigger.pressed); + break; + } + + TriggerOnChange(ControllerTriggerType::Trigger); +} + +void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.motion_values.size()) { + return; + } + std::lock_guard lock{mutex}; + auto& raw_status = controller.motion_values[index].raw_status; + auto& emulated = controller.motion_values[index].emulated; + + raw_status = TransformToMotion(callback); + emulated.SetAcceleration(Common::Vec3f{ + raw_status.accel.x.value, + raw_status.accel.y.value, + raw_status.accel.z.value, + }); + emulated.SetGyroscope(Common::Vec3f{ + raw_status.gyro.x.value, + raw_status.gyro.y.value, + raw_status.gyro.z.value, + }); + emulated.UpdateRotation(raw_status.delta_timestamp); + emulated.UpdateOrientation(raw_status.delta_timestamp); + + if (is_configuring) { + TriggerOnChange(ControllerTriggerType::Motion); + return; + } + + auto& motion = controller.motion_state[index]; + motion.accel = emulated.GetAcceleration(); + motion.gyro = emulated.GetGyroscope(); + motion.rotation = emulated.GetGyroscope(); + motion.orientation = emulated.GetOrientation(); + motion.is_at_rest = emulated.IsMoving(motion_sensitivity); + + TriggerOnChange(ControllerTriggerType::Motion); +} + +void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.battery_values.size()) { + return; + } + std::lock_guard lock{mutex}; + controller.battery_values[index] = TransformToBattery(callback); + + if (is_configuring) { + TriggerOnChange(ControllerTriggerType::Battery); + return; + } + + bool is_charging = false; + bool is_powered = false; + BatteryLevel battery_level = 0; + switch (controller.battery_values[index]) { + case Input::BatteryLevel::Charging: + is_charging = true; + is_powered = true; + battery_level = 6; + break; + case Input::BatteryLevel::Medium: + battery_level = 6; + break; + case Input::BatteryLevel::Low: + battery_level = 4; + break; + case Input::BatteryLevel::Critical: + battery_level = 2; + break; + case Input::BatteryLevel::Empty: + battery_level = 0; + break; + case Input::BatteryLevel::Full: + default: + is_powered = true; + battery_level = 8; + break; + } + + switch (index) { + case 0: + controller.battery_state.left = { + .is_powered = is_powered, + .is_charging = is_charging, + .battery_level = battery_level, + }; + break; + case 1: + controller.battery_state.right = { + .is_powered = is_powered, + .is_charging = is_charging, + .battery_level = battery_level, + }; + break; + case 2: + controller.battery_state.dual = { + .is_powered = is_powered, + .is_charging = is_charging, + .battery_level = battery_level, + }; + break; + } + TriggerOnChange(ControllerTriggerType::Battery); +} + +bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index, + [[maybe_unused]] VibrationValue vibration) { + return false; +} + +int EmulatedController::TestVibration(std::size_t device_index) { + return 1; +} + +void EmulatedController::Connect() { + std::lock_guard lock{mutex}; + if (is_connected) { + LOG_WARNING(Service_HID, "Tried to turn on a connected controller {}", npad_id_type); + return; + } + is_connected = true; + TriggerOnChange(ControllerTriggerType::Connected); +} + +void EmulatedController::Disconnect() { + std::lock_guard lock{mutex}; + if (!is_connected) { + LOG_WARNING(Service_HID, "Tried to turn off a disconnected controller {}", npad_id_type); + return; + } + is_connected = false; + TriggerOnChange(ControllerTriggerType::Disconnected); +} + +bool EmulatedController::IsConnected() const { + return is_connected; +} + +bool EmulatedController::IsVibrationEnabled() const { + return is_vibration_enabled; +} + +NpadIdType EmulatedController::GetNpadIdType() const { + return npad_id_type; +} + +NpadType EmulatedController::GetNpadType() const { + return npad_type; +} + +void EmulatedController::SetNpadType(NpadType npad_type_) { + std::lock_guard lock{mutex}; + if (npad_type == npad_type_) { + return; + } + npad_type = npad_type_; + TriggerOnChange(ControllerTriggerType::Type); +} + +ButtonValues EmulatedController::GetButtonsValues() const { + return controller.button_values; +} + +SticksValues EmulatedController::GetSticksValues() const { + return controller.stick_values; +} + +TriggerValues EmulatedController::GetTriggersValues() const { + return controller.trigger_values; +} + +ControllerMotionValues EmulatedController::GetMotionValues() const { + return controller.motion_values; +} + +ColorValues EmulatedController::GetColorsValues() const { + return controller.color_values; +} + +BatteryValues EmulatedController::GetBatteryValues() const { + return controller.battery_values; +} + +NpadButtonState EmulatedController::GetNpadButtons() const { + if (is_configuring) { + return {}; + } + return controller.npad_button_state; +} + +DebugPadButton EmulatedController::GetDebugPadButtons() const { + if (is_configuring) { + return {}; + } + return controller.debug_pad_button_state; +} + +AnalogSticks EmulatedController::GetSticks() const { + if (is_configuring) { + return {}; + } + return controller.analog_stick_state; +} + +NpadGcTriggerState EmulatedController::GetTriggers() const { + if (is_configuring) { + return {}; + } + return controller.gc_trigger_state; +} + +MotionState EmulatedController::GetMotions() const { + return controller.motion_state; +} + +ControllerColors EmulatedController::GetColors() const { + return controller.colors_state; +} + +BatteryLevelState EmulatedController::GetBattery() const { + return controller.battery_state; +} + +void EmulatedController::TriggerOnChange(ControllerTriggerType type) { + for (const std::pair poller_pair : callback_list) { + const ControllerUpdateCallback& poller = poller_pair.second; + if (poller.on_change) { + poller.on_change(type); + } + } +} + +int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { + std::lock_guard lock{mutex}; + callback_list.insert_or_assign(last_callback_key, update_callback); + return last_callback_key++; +} + +void EmulatedController::DeleteCallback(int key) { + std::lock_guard lock{mutex}; + if (!callback_list.contains(key)) { + LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); + return; + } + callback_list.erase(key); +} +} // namespace Core::HID diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h new file mode 100644 index 000000000..94db9b00b --- /dev/null +++ b/src/core/hid/emulated_controller.h @@ -0,0 +1,232 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "common/input.h" +#include "common/param_package.h" +#include "common/point.h" +#include "common/quaternion.h" +#include "common/settings.h" +#include "common/vector_math.h" +#include "core/hid/hid_types.h" +#include "core/hid/motion_input.h" + +namespace Core::HID { + +struct ControllerMotionInfo { + Input::MotionStatus raw_status; + MotionInput emulated{}; +}; + +using ButtonDevices = + std::array, Settings::NativeButton::NumButtons>; +using StickDevices = + std::array, Settings::NativeAnalog::NumAnalogs>; +using ControllerMotionDevices = + std::array, Settings::NativeMotion::NumMotions>; +using TriggerDevices = + std::array, Settings::NativeTrigger::NumTriggers>; +using BatteryDevices = std::array, 2>; + +using ButtonParams = std::array; +using StickParams = std::array; +using ControllerMotionParams = std::array; +using TriggerParams = std::array; +using BatteryParams = std::array; + +using ButtonValues = std::array; +using SticksValues = std::array; +using TriggerValues = std::array; +using ControllerMotionValues = std::array; +using ColorValues = std::array; +using BatteryValues = std::array; +using VibrationValues = std::array; + +struct AnalogSticks { + AnalogStickState left; + AnalogStickState right; +}; + +struct ControllerColors { + NpadControllerColor fullkey; + NpadControllerColor left; + NpadControllerColor right; +}; + +struct BatteryLevelState { + NpadPowerInfo dual; + NpadPowerInfo left; + NpadPowerInfo right; +}; + +struct ControllerMotion { + bool is_at_rest; + Common::Vec3f accel{}; + Common::Vec3f gyro{}; + Common::Vec3f rotation{}; + std::array orientation{}; +}; + +using MotionState = std::array; + +struct ControllerStatus { + // Data from input_common + ButtonValues button_values{}; + SticksValues stick_values{}; + ControllerMotionValues motion_values{}; + TriggerValues trigger_values{}; + ColorValues color_values{}; + BatteryValues battery_values{}; + VibrationValues vibration_values{}; + + // Data for Nintendo devices + NpadButtonState npad_button_state{}; + DebugPadButton debug_pad_button_state{}; + AnalogSticks analog_stick_state{}; + MotionState motion_state{}; + NpadGcTriggerState gc_trigger_state{}; + ControllerColors colors_state{}; + BatteryLevelState battery_state{}; +}; +enum class ControllerTriggerType { + Button, + Stick, + Trigger, + Motion, + Color, + Battery, + Vibration, + Connected, + Disconnected, + Type, + All, +}; + +struct ControllerUpdateCallback { + std::function on_change; +}; + +class EmulatedController { +public: + /** + * TODO: Write description + * + * @param npad_id_type + */ + explicit EmulatedController(NpadIdType npad_id_type_); + ~EmulatedController(); + + YUZU_NON_COPYABLE(EmulatedController); + YUZU_NON_MOVEABLE(EmulatedController); + + static NpadType MapSettingsTypeToNPad(Settings::ControllerType type); + static Settings::ControllerType MapNPadToSettingsType(NpadType type); + + /// Gets the NpadIdType for this controller. + NpadIdType GetNpadIdType() const; + + /// Sets the NpadType for this controller. + void SetNpadType(NpadType npad_type_); + + /// Gets the NpadType for this controller. + NpadType GetNpadType() const; + + void Connect(); + void Disconnect(); + + bool IsConnected() const; + bool IsVibrationEnabled() const; + + void ReloadFromSettings(); + void ReloadInput(); + void UnloadInput(); + + void EnableConfiguration(); + void DisableConfiguration(); + bool IsConfiguring() const; + void SaveCurrentConfig(); + void RestoreConfig(); + + std::vector GetMappedDevices() const; + + Common::ParamPackage GetButtonParam(std::size_t index) const; + Common::ParamPackage GetStickParam(std::size_t index) const; + Common::ParamPackage GetMotionParam(std::size_t index) const; + + void SetButtonParam(std::size_t index, Common::ParamPackage param); + void SetStickParam(std::size_t index, Common::ParamPackage param); + void SetMotionParam(std::size_t index, Common::ParamPackage param); + + ButtonValues GetButtonsValues() const; + SticksValues GetSticksValues() const; + TriggerValues GetTriggersValues() const; + ControllerMotionValues GetMotionValues() const; + ColorValues GetColorsValues() const; + BatteryValues GetBatteryValues() const; + + NpadButtonState GetNpadButtons() const; + DebugPadButton GetDebugPadButtons() const; + AnalogSticks GetSticks() const; + NpadGcTriggerState GetTriggers() const; + MotionState GetMotions() const; + ControllerColors GetColors() const; + BatteryLevelState GetBattery() const; + + bool SetVibration(std::size_t device_index, VibrationValue vibration); + int TestVibration(std::size_t device_index); + + int SetCallback(ControllerUpdateCallback update_callback); + void DeleteCallback(int key); + +private: + /** + * Sets the status of a button. Applies toggle properties to the output. + * + * @param A CallbackStatus and a button index number + */ + void SetButton(Input::CallbackStatus callback, std::size_t index); + void SetStick(Input::CallbackStatus callback, std::size_t index); + void SetTrigger(Input::CallbackStatus callback, std::size_t index); + void SetMotion(Input::CallbackStatus callback, std::size_t index); + void SetBattery(Input::CallbackStatus callback, std::size_t index); + + /** + * Triggers a callback that something has changed + * + * @param Input type of the trigger + */ + void TriggerOnChange(ControllerTriggerType type); + + NpadIdType npad_id_type; + NpadType npad_type{NpadType::None}; + bool is_connected{false}; + bool is_configuring{false}; + bool is_vibration_enabled{true}; + f32 motion_sensitivity{0.01f}; + + ButtonParams button_params; + StickParams stick_params; + ControllerMotionParams motion_params; + TriggerParams trigger_params; + BatteryParams battery_params; + + ButtonDevices button_devices; + StickDevices stick_devices; + ControllerMotionDevices motion_devices; + TriggerDevices trigger_devices; + BatteryDevices battery_devices; + // VibrationDevices vibration_devices; + + mutable std::mutex mutex; + std::unordered_map callback_list; + int last_callback_key = 0; + ControllerStatus controller; +}; + +} // namespace Core::HID diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp new file mode 100644 index 000000000..3caf90714 --- /dev/null +++ b/src/core/hid/emulated_devices.cpp @@ -0,0 +1,349 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include + +#include "core/hid/emulated_devices.h" +#include "core/hid/input_converter.h" + +namespace Core::HID { + +EmulatedDevices::EmulatedDevices() {} + +EmulatedDevices::~EmulatedDevices() = default; + +void EmulatedDevices::ReloadFromSettings() { + const auto& mouse = Settings::values.mouse_buttons; + + for (std::size_t index = 0; index < mouse.size(); ++index) { + mouse_button_params[index] = Common::ParamPackage(mouse[index]); + } + ReloadInput(); +} + +void EmulatedDevices::ReloadInput() { + std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN, + mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END, + mouse_button_devices.begin(), Input::CreateDevice); + + std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(), + keyboard_devices.begin(), Input::CreateDeviceFromString); + + std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(), + keyboard_modifier_devices.begin(), + Input::CreateDeviceFromString); + + for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { + if (!mouse_button_devices[index]) { + continue; + } + Input::InputCallback button_callback{ + [this, index](Input::CallbackStatus callback) { SetMouseButton(callback, index); }}; + mouse_button_devices[index]->SetCallback(button_callback); + } + + for (std::size_t index = 0; index < keyboard_devices.size(); ++index) { + if (!keyboard_devices[index]) { + continue; + } + Input::InputCallback button_callback{ + [this, index](Input::CallbackStatus callback) { SetKeyboardButton(callback, index); }}; + keyboard_devices[index]->SetCallback(button_callback); + } + + for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) { + if (!keyboard_modifier_devices[index]) { + continue; + } + Input::InputCallback button_callback{[this, index](Input::CallbackStatus callback) { + SetKeyboardModifier(callback, index); + }}; + keyboard_modifier_devices[index]->SetCallback(button_callback); + } +} + +void EmulatedDevices::UnloadInput() { + for (auto& button : mouse_button_devices) { + button.reset(); + } + for (auto& button : keyboard_devices) { + button.reset(); + } + for (auto& button : keyboard_modifier_devices) { + button.reset(); + } +} + +void EmulatedDevices::EnableConfiguration() { + is_configuring = true; + SaveCurrentConfig(); +} + +void EmulatedDevices::DisableConfiguration() { + is_configuring = false; +} + +bool EmulatedDevices::IsConfiguring() const { + return is_configuring; +} + +void EmulatedDevices::SaveCurrentConfig() { + if (!is_configuring) { + return; + } + + auto& mouse = Settings::values.mouse_buttons; + + for (std::size_t index = 0; index < mouse.size(); ++index) { + mouse[index] = mouse_button_params[index].Serialize(); + } +} + +void EmulatedDevices::RestoreConfig() { + if (!is_configuring) { + return; + } + ReloadFromSettings(); +} + +Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) const { + if (index >= mouse_button_params.size()) { + return {}; + } + return mouse_button_params[index]; +} + +void EmulatedDevices::SetButtonParam(std::size_t index, Common::ParamPackage param) { + if (index >= mouse_button_params.size()) { + return; + } + mouse_button_params[index] = param; + ReloadInput(); +} + +void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::size_t index) { + if (index >= device_status.keyboard_values.size()) { + return; + } + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = device_status.keyboard_values[index]; + current_status.toggle = new_status.toggle; + + // Update button status with current + if (!current_status.toggle) { + current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } + } + + if (!value_changed) { + return; + } + + if (is_configuring) { + TriggerOnChange(DeviceTriggerType::Keyboard); + return; + } + + // TODO(german77): Do this properly + // switch (index) { + // case Settings::NativeKeyboard::A: + // interface_status.keyboard_state.a.Assign(current_status.value); + // break; + // .... + //} + + TriggerOnChange(DeviceTriggerType::Keyboard); +} + +void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) { + if (index >= device_status.keyboard_moddifier_values.size()) { + return; + } + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = device_status.keyboard_moddifier_values[index]; + current_status.toggle = new_status.toggle; + + // Update button status with current + if (!current_status.toggle) { + current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } + } + + if (!value_changed) { + return; + } + + if (is_configuring) { + TriggerOnChange(DeviceTriggerType::KeyboardModdifier); + return; + } + + switch (index) { + case Settings::NativeKeyboard::LeftControl: + case Settings::NativeKeyboard::RightControl: + device_status.keyboard_moddifier_state.control.Assign(current_status.value); + break; + case Settings::NativeKeyboard::LeftShift: + case Settings::NativeKeyboard::RightShift: + device_status.keyboard_moddifier_state.shift.Assign(current_status.value); + break; + case Settings::NativeKeyboard::LeftAlt: + device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value); + break; + case Settings::NativeKeyboard::RightAlt: + device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value); + break; + case Settings::NativeKeyboard::CapsLock: + device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value); + break; + case Settings::NativeKeyboard::ScrollLock: + device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value); + break; + case Settings::NativeKeyboard::NumLock: + device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value); + break; + } + + TriggerOnChange(DeviceTriggerType::KeyboardModdifier); +} + +void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t index) { + if (index >= device_status.mouse_button_values.size()) { + return; + } + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = device_status.mouse_button_values[index]; + current_status.toggle = new_status.toggle; + + // Update button status with current + if (!current_status.toggle) { + current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } + } + + if (!value_changed) { + return; + } + + if (is_configuring) { + TriggerOnChange(DeviceTriggerType::Mouse); + return; + } + + switch (index) { + case Settings::NativeMouseButton::Left: + device_status.mouse_button_state.left.Assign(current_status.value); + break; + case Settings::NativeMouseButton::Right: + device_status.mouse_button_state.right.Assign(current_status.value); + break; + case Settings::NativeMouseButton::Middle: + device_status.mouse_button_state.middle.Assign(current_status.value); + break; + case Settings::NativeMouseButton::Forward: + device_status.mouse_button_state.forward.Assign(current_status.value); + break; + case Settings::NativeMouseButton::Back: + device_status.mouse_button_state.back.Assign(current_status.value); + break; + } + + TriggerOnChange(DeviceTriggerType::Mouse); +} + +MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { + return device_status.mouse_button_values; +} + +KeyboardKey EmulatedDevices::GetKeyboard() const { + return device_status.keyboard_state; +} + +KeyboardModifier EmulatedDevices::GetKeyboardModifier() const { + return device_status.keyboard_moddifier_state; +} + +MouseButton EmulatedDevices::GetMouseButtons() const { + return device_status.mouse_button_state; +} + +MousePosition EmulatedDevices::GetMousePosition() const { + return device_status.mouse_position_state; +} + +void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { + for (const std::pair poller_pair : callback_list) { + const InterfaceUpdateCallback& poller = poller_pair.second; + if (poller.on_change) { + poller.on_change(type); + } + } +} + +int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { + std::lock_guard lock{mutex}; + callback_list.insert_or_assign(last_callback_key, update_callback); + return last_callback_key++; +} + +void EmulatedDevices::DeleteCallback(int key) { + std::lock_guard lock{mutex}; + if (!callback_list.contains(key)) { + LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); + return; + } + callback_list.erase(key); +} +} // namespace Core::HID diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h new file mode 100644 index 000000000..6f728eff5 --- /dev/null +++ b/src/core/hid/emulated_devices.h @@ -0,0 +1,137 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "common/input.h" +#include "common/param_package.h" +#include "common/settings.h" +#include "core/hid/hid_types.h" +#include "core/hid/motion_input.h" + +namespace Core::HID { + +using KeyboardDevices = + std::array, Settings::NativeKeyboard::NumKeyboardKeys>; +using KeyboardModifierDevices = + std::array, Settings::NativeKeyboard::NumKeyboardMods>; +using MouseButtonDevices = + std::array, Settings::NativeMouseButton::NumMouseButtons>; + +using MouseButtonParams = + std::array; + +using KeyboardValues = std::array; +using KeyboardModifierValues = + std::array; +using MouseButtonValues = + std::array; + +struct MousePosition { + s32 x; + s32 y; + s32 delta_wheel_x; + s32 delta_wheel_y; +}; + +struct DeviceStatus { + // Data from input_common + KeyboardValues keyboard_values{}; + KeyboardModifierValues keyboard_moddifier_values{}; + MouseButtonValues mouse_button_values{}; + + // Data for Nintendo devices + KeyboardKey keyboard_state{}; + KeyboardModifier keyboard_moddifier_state{}; + MouseButton mouse_button_state{}; + MousePosition mouse_position_state{}; +}; + +enum class DeviceTriggerType { + Keyboard, + KeyboardModdifier, + Mouse, +}; + +struct InterfaceUpdateCallback { + std::function on_change; +}; + +class EmulatedDevices { +public: + /** + * TODO: Write description + * + * @param npad_id_type + */ + explicit EmulatedDevices(); + ~EmulatedDevices(); + + YUZU_NON_COPYABLE(EmulatedDevices); + YUZU_NON_MOVEABLE(EmulatedDevices); + + void ReloadFromSettings(); + void ReloadInput(); + void UnloadInput(); + + void EnableConfiguration(); + void DisableConfiguration(); + bool IsConfiguring() const; + void SaveCurrentConfig(); + void RestoreConfig(); + + std::vector GetMappedDevices() const; + + Common::ParamPackage GetMouseButtonParam(std::size_t index) const; + + void SetButtonParam(std::size_t index, Common::ParamPackage param); + + KeyboardValues GetKeyboardValues() const; + KeyboardModifierValues GetKeyboardModdifierValues() const; + MouseButtonValues GetMouseButtonsValues() const; + + KeyboardKey GetKeyboard() const; + KeyboardModifier GetKeyboardModifier() const; + MouseButton GetMouseButtons() const; + MousePosition GetMousePosition() const; + + int SetCallback(InterfaceUpdateCallback update_callback); + void DeleteCallback(int key); + +private: + /** + * Sets the status of a button. Applies toggle properties to the output. + * + * @param A CallbackStatus and a button index number + */ + void SetKeyboardButton(Input::CallbackStatus callback, std::size_t index); + void SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index); + void SetMouseButton(Input::CallbackStatus callback, std::size_t index); + + /** + * Triggers a callback that something has changed + * + * @param Input type of the trigger + */ + void TriggerOnChange(DeviceTriggerType type); + + bool is_configuring{false}; + + MouseButtonParams mouse_button_params; + + KeyboardDevices keyboard_devices; + KeyboardModifierDevices keyboard_modifier_devices; + MouseButtonDevices mouse_button_devices; + + mutable std::mutex mutex; + std::unordered_map callback_list; + int last_callback_key = 0; + DeviceStatus device_status; +}; + +} // namespace Core::HID diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp new file mode 100644 index 000000000..ee76db110 --- /dev/null +++ b/src/core/hid/hid_core.cpp @@ -0,0 +1,144 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "core/hid/hid_core.h" + +namespace Core::HID { + +HIDCore::HIDCore() + : player_1{std::make_unique(NpadIdType::Player1)}, + player_2{std::make_unique(NpadIdType::Player2)}, + player_3{std::make_unique(NpadIdType::Player3)}, + player_4{std::make_unique(NpadIdType::Player4)}, + player_5{std::make_unique(NpadIdType::Player5)}, + player_6{std::make_unique(NpadIdType::Player6)}, + player_7{std::make_unique(NpadIdType::Player7)}, + player_8{std::make_unique(NpadIdType::Player8)}, + other{std::make_unique(NpadIdType::Other)}, + handheld{std::make_unique(NpadIdType::Handheld)}, + console{std::make_unique()}, devices{std::make_unique()} {} + +HIDCore::~HIDCore() = default; + +EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) { + switch (npad_id_type) { + case NpadIdType::Player1: + return player_1.get(); + case NpadIdType::Player2: + return player_2.get(); + case NpadIdType::Player3: + return player_3.get(); + case NpadIdType::Player4: + return player_4.get(); + case NpadIdType::Player5: + return player_5.get(); + case NpadIdType::Player6: + return player_6.get(); + case NpadIdType::Player7: + return player_7.get(); + case NpadIdType::Player8: + return player_8.get(); + case NpadIdType::Other: + return other.get(); + case NpadIdType::Handheld: + return handheld.get(); + case NpadIdType::Invalid: + default: + UNREACHABLE_MSG("Invalid NpadIdType={}", npad_id_type); + return nullptr; + } +} + +const EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) const { + switch (npad_id_type) { + case NpadIdType::Player1: + return player_1.get(); + case NpadIdType::Player2: + return player_2.get(); + case NpadIdType::Player3: + return player_3.get(); + case NpadIdType::Player4: + return player_4.get(); + case NpadIdType::Player5: + return player_5.get(); + case NpadIdType::Player6: + return player_6.get(); + case NpadIdType::Player7: + return player_7.get(); + case NpadIdType::Player8: + return player_8.get(); + case NpadIdType::Other: + return other.get(); + case NpadIdType::Handheld: + return handheld.get(); + case NpadIdType::Invalid: + default: + UNREACHABLE_MSG("Invalid NpadIdType={}", npad_id_type); + return nullptr; + } +} +EmulatedConsole* HIDCore::GetEmulatedConsole() { + return console.get(); +} + +const EmulatedConsole* HIDCore::GetEmulatedConsole() const { + return console.get(); +} + +EmulatedDevices* HIDCore::GetEmulatedDevices() { + return devices.get(); +} + +const EmulatedDevices* HIDCore::GetEmulatedDevices() const { + return devices.get(); +} + +EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) { + return GetEmulatedController(IndexToNpadIdType(index)); +} + +const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const { + return GetEmulatedController(IndexToNpadIdType(index)); +} + +void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) { + supported_style_tag.raw = style_tag.raw; +} + +NpadStyleTag HIDCore::GetSupportedStyleTag() const { + return supported_style_tag; +} + +void HIDCore::ReloadInputDevices() { + player_1->ReloadFromSettings(); + player_2->ReloadFromSettings(); + player_3->ReloadFromSettings(); + player_4->ReloadFromSettings(); + player_5->ReloadFromSettings(); + player_6->ReloadFromSettings(); + player_7->ReloadFromSettings(); + player_8->ReloadFromSettings(); + other->ReloadFromSettings(); + handheld->ReloadFromSettings(); + console->ReloadFromSettings(); + devices->ReloadFromSettings(); +} + +void HIDCore::UnloadInputDevices() { + player_1->UnloadInput(); + player_2->UnloadInput(); + player_3->UnloadInput(); + player_4->UnloadInput(); + player_5->UnloadInput(); + player_6->UnloadInput(); + player_7->UnloadInput(); + player_8->UnloadInput(); + other->UnloadInput(); + handheld->UnloadInput(); + console->UnloadInput(); + devices->UnloadInput(); +} + +} // namespace Core::HID diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h new file mode 100644 index 000000000..f11f48b61 --- /dev/null +++ b/src/core/hid/hid_core.h @@ -0,0 +1,60 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "core/hid/emulated_console.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/emulated_devices.h" + +namespace Core::HID { + +class HIDCore { +public: + explicit HIDCore(); + ~HIDCore(); + + YUZU_NON_COPYABLE(HIDCore); + YUZU_NON_MOVEABLE(HIDCore); + + EmulatedController* GetEmulatedController(NpadIdType npad_id_type); + const EmulatedController* GetEmulatedController(NpadIdType npad_id_type) const; + + EmulatedController* GetEmulatedControllerByIndex(std::size_t index); + const EmulatedController* GetEmulatedControllerByIndex(std::size_t index) const; + + EmulatedConsole* GetEmulatedConsole(); + const EmulatedConsole* GetEmulatedConsole() const; + + EmulatedDevices* GetEmulatedDevices(); + const EmulatedDevices* GetEmulatedDevices() const; + + void SetSupportedStyleTag(NpadStyleTag style_tag); + NpadStyleTag GetSupportedStyleTag() const; + + // Reloads all input devices from settings + void ReloadInputDevices(); + + // Removes all callbacks from input common + void UnloadInputDevices(); + +private: + std::unique_ptr player_1; + std::unique_ptr player_2; + std::unique_ptr player_3; + std::unique_ptr player_4; + std::unique_ptr player_5; + std::unique_ptr player_6; + std::unique_ptr player_7; + std::unique_ptr player_8; + std::unique_ptr other; + std::unique_ptr handheld; + std::unique_ptr console; + std::unique_ptr devices; + NpadStyleTag supported_style_tag; +}; + +} // namespace Core::HID -- cgit v1.2.3 From 967cca10ff5721cc942f557c3e0a20c07f5aa45e Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 19:44:34 -0500 Subject: core: Register HID --- src/core/core.cpp | 14 +++++++++++--- src/core/core.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/core.cpp b/src/core/core.cpp index 07448fd29..473ab9f81 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -27,6 +27,7 @@ #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" #include "core/hardware_interrupt_manager.h" +#include "core/hid/hid_core.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/kernel.h" @@ -126,7 +127,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, memory{system}, + : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} SystemResultStatus Run() { @@ -391,6 +392,7 @@ struct System::Impl { std::unique_ptr interrupt_manager; std::unique_ptr device_memory; Core::Memory::Memory memory; + Core::HID::HIDCore hid_core; CpuManager cpu_manager; std::atomic_bool is_powered_on{}; bool exit_lock = false; @@ -615,6 +617,14 @@ const Kernel::KernelCore& System::Kernel() const { return impl->kernel; } +HID::HIDCore& System::HIDCore() { + return impl->hid_core; +} + +const HID::HIDCore& System::HIDCore() const { + return impl->hid_core; +} + Timing::CoreTiming& System::CoreTiming() { return impl->core_timing; } @@ -825,8 +835,6 @@ void System::ApplySettings() { if (IsPoweredOn()) { Renderer().RefreshBaseSettings(); } - - Service::HID::ReloadInputDevices(); } } // namespace Core diff --git a/src/core/core.h b/src/core/core.h index 01bc0a2c7..5a031efb0 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -89,6 +89,10 @@ namespace Core::Hardware { class InterruptManager; } +namespace Core::HID { +class HIDCore; +} + namespace Core { class ARM_Interface; @@ -285,6 +289,12 @@ public: /// Provides a constant reference to the kernel instance. [[nodiscard]] const Kernel::KernelCore& Kernel() const; + /// Gets a mutable reference to the HID interface + [[nodiscard]] HID::HIDCore& HIDCore(); + + /// Gets an immutable reference to the HID interface. + [[nodiscard]] const HID::HIDCore& HIDCore() const; + /// Provides a reference to the internal PerfStats instance. [[nodiscard]] Core::PerfStats& GetPerfStats(); -- cgit v1.2.3 From 173a6b1e57c71e8bfe7a1492d5fe9b6b3e81a6cb Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 19:50:30 -0500 Subject: core/emu_window: Remove touch input --- src/core/frontend/emu_window.cpp | 98 ++++------------------------------------ src/core/frontend/emu_window.h | 30 ++---------- 2 files changed, 15 insertions(+), 113 deletions(-) (limited to 'src/core') diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index e1f7e5886..57c6ffc43 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -3,87 +3,23 @@ // Refer to the license.txt file included. #include -#include "common/settings.h" #include "core/frontend/emu_window.h" -#include "core/frontend/input.h" namespace Core::Frontend { GraphicsContext::~GraphicsContext() = default; -class EmuWindow::TouchState : public Input::Factory, - public std::enable_shared_from_this { -public: - std::unique_ptr Create(const Common::ParamPackage&) override { - return std::make_unique(shared_from_this()); - } - - std::mutex mutex; - - Input::TouchStatus status; - -private: - class Device : public Input::TouchDevice { - public: - explicit Device(std::weak_ptr&& touch_state_) : touch_state(touch_state_) {} - Input::TouchStatus GetStatus() const override { - if (auto state = touch_state.lock()) { - std::lock_guard guard{state->mutex}; - return state->status; - } - return {}; - } - - private: - std::weak_ptr touch_state; - }; -}; - EmuWindow::EmuWindow() { // TODO: Find a better place to set this. config.min_client_area_size = std::make_pair(Layout::MinimumSize::Width, Layout::MinimumSize::Height); active_config = config; - touch_state = std::make_shared(); - Input::RegisterFactory("emu_window", touch_state); -} - -EmuWindow::~EmuWindow() { - Input::UnregisterFactory("emu_window"); -} - -/** - * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout - * @param layout FramebufferLayout object describing the framebuffer size and screen positions - * @param framebuffer_x Framebuffer x-coordinate to check - * @param framebuffer_y Framebuffer y-coordinate to check - * @return True if the coordinates are within the touchpad, otherwise false - */ -static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, u32 framebuffer_x, - u32 framebuffer_y) { - return (framebuffer_y >= layout.screen.top && framebuffer_y < layout.screen.bottom && - framebuffer_x >= layout.screen.left && framebuffer_x < layout.screen.right); -} - -std::pair EmuWindow::ClipToTouchScreen(u32 new_x, u32 new_y) const { - new_x = std::max(new_x, framebuffer_layout.screen.left); - new_x = std::min(new_x, framebuffer_layout.screen.right - 1); - - new_y = std::max(new_y, framebuffer_layout.screen.top); - new_y = std::min(new_y, framebuffer_layout.screen.bottom - 1); - - return std::make_pair(new_x, new_y); } -void EmuWindow::TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id) { - if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) { - return; - } - if (id >= touch_state->status.size()) { - return; - } +EmuWindow::~EmuWindow() {} - std::lock_guard guard{touch_state->mutex}; +std::pair EmuWindow::MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const { + std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); const float x = static_cast(framebuffer_x - framebuffer_layout.screen.left) / static_cast(framebuffer_layout.screen.right - framebuffer_layout.screen.left); @@ -91,31 +27,17 @@ void EmuWindow::TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id) { static_cast(framebuffer_y - framebuffer_layout.screen.top) / static_cast(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); - touch_state->status[id] = std::make_tuple(x, y, true); -} - -void EmuWindow::TouchReleased(size_t id) { - if (id >= touch_state->status.size()) { - return; - } - std::lock_guard guard{touch_state->mutex}; - touch_state->status[id] = std::make_tuple(0.0f, 0.0f, false); + return std::make_pair(x, y); } -void EmuWindow::TouchMoved(u32 framebuffer_x, u32 framebuffer_y, size_t id) { - if (id >= touch_state->status.size()) { - return; - } - - if (!std::get<2>(touch_state->status[id])) { - return; - } +std::pair EmuWindow::ClipToTouchScreen(u32 new_x, u32 new_y) const { + new_x = std::max(new_x, framebuffer_layout.screen.left); + new_x = std::min(new_x, framebuffer_layout.screen.right - 1); - if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) { - std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); - } + new_y = std::max(new_y, framebuffer_layout.screen.top); + new_y = std::min(new_y, framebuffer_layout.screen.bottom - 1); - TouchPressed(framebuffer_x, framebuffer_y, id); + return std::make_pair(new_x, new_y); } void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height) { diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 8a86a1d27..e413a520a 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -112,28 +112,6 @@ public: /// Returns if window is shown (not minimized) virtual bool IsShown() const = 0; - /** - * Signal that a touch pressed event has occurred (e.g. mouse click pressed) - * @param framebuffer_x Framebuffer x-coordinate that was pressed - * @param framebuffer_y Framebuffer y-coordinate that was pressed - * @param id Touch event ID - */ - void TouchPressed(u32 framebuffer_x, u32 framebuffer_y, size_t id); - - /** - * Signal that a touch released event has occurred (e.g. mouse click released) - * @param id Touch event ID - */ - void TouchReleased(size_t id); - - /** - * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) - * @param framebuffer_x Framebuffer x-coordinate - * @param framebuffer_y Framebuffer y-coordinate - * @param id Touch event ID - */ - void TouchMoved(u32 framebuffer_x, u32 framebuffer_y, size_t id); - /** * Returns currently active configuration. * @note Accesses to the returned object need not be consistent because it may be modified in @@ -212,6 +190,11 @@ protected: client_area_height = size.second; } + /** + * Converts a screen postion into the equivalent touchscreen position. + */ + std::pair MapToTouchScreen(u32 framebuffer_x, u32 framebuffer_y) const; + WindowSystemInfo window_info; private: @@ -237,9 +220,6 @@ private: WindowConfig config; ///< Internal configuration (changes pending for being applied in /// ProcessConfigurationChanges) WindowConfig active_config; ///< Internal active configuration - - class TouchState; - std::shared_ptr touch_state; }; } // namespace Core::Frontend -- cgit v1.2.3 From 6e2c84042d296272a2186feac67678c19fdb122b Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:18:26 -0500 Subject: settings: Cleanup settings --- src/core/hle/service/hid/controllers/debug_pad.h | 2 +- src/core/hle/service/hid/controllers/mouse.cpp | 2 +- src/core/hle/service/hid/controllers/npad.h | 2 +- src/core/hle/service/hid/hid.cpp | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 1b1645184..e90ae8415 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -87,7 +87,7 @@ private: std::array, Settings::NativeButton::NUM_BUTTONS_HID> buttons; - std::array, Settings::NativeAnalog::NUM_STICKS_HID> + std::array, Settings::NativeAnalog::NumAnalogs> analogs; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 544a71948..2211f1144 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -61,7 +61,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* } void Controller_Mouse::OnLoadInputDevices() { - mouse_device = Input::CreateDevice(Settings::values.mouse_device); + //mouse_device = Input::CreateDevice(Settings::values.mouse_device); std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), mouse_button_devices.begin(), Input::CreateDevice); } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 9ee146caf..f3e868bdb 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -563,7 +563,7 @@ private: std::array, Settings::NativeButton::NUM_BUTTONS_HID>, 10>; using StickArray = std::array< - std::array, Settings::NativeAnalog::NUM_STICKS_HID>, + std::array, Settings::NativeAnalog::NumAnalogs>, 10>; using VibrationArray = std::array, Settings::NativeVibration::NUM_VIBRATIONS_HID>, diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 10c64d41a..9a5b60263 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -117,7 +117,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); - const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); + const bool should_reload = false; for (const auto& controller : controllers) { if (should_reload) { controller->OnLoadInputDevices(); @@ -2038,7 +2038,6 @@ public: }; void ReloadInputDevices() { - Settings::values.is_device_reload_pending.store(true); } void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { -- cgit v1.2.3 From db08721dccdec9330b883324e2a99d784c2405fd Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:25:22 -0500 Subject: service/hid: Create ring LIFO --- src/core/CMakeLists.txt | 2 +- src/core/hle/service/hid/ring_lifo.h | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/core/hle/service/hid/ring_lifo.h (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 09163fab9..582c15f7e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -132,7 +132,6 @@ add_library(core STATIC frontend/emu_window.h frontend/framebuffer_layout.cpp frontend/framebuffer_layout.h - frontend/input.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h hid/emulated_console.cpp @@ -415,6 +414,7 @@ add_library(core STATIC hle/service/hid/hid.h hle/service/hid/irs.cpp hle/service/hid/irs.h + hle/service/hid/ring_lifo.h hle/service/hid/xcd.cpp hle/service/hid/xcd.h hle/service/hid/errors.h diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h new file mode 100644 index 000000000..1cc2a194f --- /dev/null +++ b/src/core/hle/service/hid/ring_lifo.h @@ -0,0 +1,54 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#pragma once + +#include "common/common_types.h" +#include "common/swap.h" + +namespace Service::HID { +constexpr std::size_t max_entry_size = 17; + +template +struct AtomicStorage { + s64_le sampling_number; + State state; +}; + +template +struct Lifo { + s64_le timestamp{}; + s64_le total_entry_count = max_entry_size; + s64_le last_entry_index{}; + s64_le entry_count{}; + std::array, max_entry_size> entries{}; + + const AtomicStorage& ReadCurrentEntry() const { + return entries[last_entry_index]; + } + + const AtomicStorage& ReadPreviousEntry() const { + return entries[GetPreviuousEntryIndex()]; + } + + std::size_t GetPreviuousEntryIndex() const { + return (last_entry_index + total_entry_count - 1) % total_entry_count; + } + + std::size_t GetNextEntryIndex() const { + return (last_entry_index + 1) % total_entry_count; + } + + void WriteNextEntry(const State& new_state) { + if (entry_count < total_entry_count - 1) { + entry_count++; + } + last_entry_index = GetNextEntryIndex(); + const auto& previous_entry = ReadPreviousEntry(); + entries[last_entry_index].sampling_number = previous_entry.sampling_number + 1; + entries[last_entry_index].state = new_state; + } +}; + +} // namespace Service::HID -- cgit v1.2.3 From dbe030110256876438cf568314e3ffb60cd89952 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:29:00 -0500 Subject: service/hid: Use remove duplicated code, update names --- src/core/hle/service/hid/hid.cpp | 67 ++++++++++++++++++---------------------- src/core/hle/service/hid/hid.h | 27 ---------------- 2 files changed, 30 insertions(+), 64 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 9a5b60263..18f29bb78 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -9,6 +9,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/frontend/input.h" +#include "core/hardware_properties.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" @@ -34,10 +35,9 @@ namespace Service::HID { // Updating period for each HID device. -// HID is polled every 15ms, this value was derived from -// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet -constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz) -constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz) +// Period time is obtained by measuring the number of samples in a second +constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; IAppletResource::IAppletResource(Core::System& system_, @@ -89,7 +89,7 @@ IAppletResource::IAppletResource(Core::System& system_, system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); - ReloadInputDevices(); + system.HIDCore().ReloadInputDevices(); } void IAppletResource::ActivateController(HidController controller) { @@ -117,11 +117,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); - const bool should_reload = false; for (const auto& controller : controllers) { - if (should_reload) { - controller->OnLoadInputDevices(); - } controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); } @@ -891,7 +887,7 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - const auto hold_type{rp.PopEnum()}; + const auto hold_type{rp.PopEnum()}; applet_resource->GetController(HidController::NPad).SetHoldType(hold_type); @@ -924,7 +920,7 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); @@ -946,7 +942,7 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", @@ -968,7 +964,7 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual); + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual); LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); @@ -1134,36 +1130,36 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw()}; - VibrationDeviceInfo vibration_device_info; + Core::HID::VibrationDeviceInfo vibration_device_info; switch (vibration_device_handle.npad_type) { - case Controller_NPad::NpadType::ProController: - case Controller_NPad::NpadType::Handheld: - case Controller_NPad::NpadType::JoyconDual: - case Controller_NPad::NpadType::JoyconLeft: - case Controller_NPad::NpadType::JoyconRight: + case Core::HID::NpadType::ProController: + case Core::HID::NpadType::Handheld: + case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadType::JoyconRight: default: - vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; + vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; break; - case Controller_NPad::NpadType::GameCube: - vibration_device_info.type = VibrationDeviceType::GcErm; + case Core::HID::NpadType::GameCube: + vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm; break; - case Controller_NPad::NpadType::Pokeball: - vibration_device_info.type = VibrationDeviceType::Unknown; + case Core::HID::NpadType::Pokeball: + vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown; break; } switch (vibration_device_handle.device_index) { case Controller_NPad::DeviceIndex::Left: - vibration_device_info.position = VibrationDevicePosition::Left; + vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; break; case Controller_NPad::DeviceIndex::Right: - vibration_device_info.position = VibrationDevicePosition::Right; + vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; break; case Controller_NPad::DeviceIndex::None: default: UNREACHABLE_MSG("DeviceIndex should never be None!"); - vibration_device_info.position = VibrationDevicePosition::None; + vibration_device_info.position = Core::HID::VibrationDevicePosition::None; break; } @@ -1278,7 +1274,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { struct Parameters { Controller_NPad::DeviceHandle vibration_device_handle; u64 applet_resource_user_id; - VibrationGcErmCommand gc_erm_command; + Core::HID::VibrationGcErmCommand gc_erm_command; }; static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); @@ -1292,21 +1288,21 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { */ const auto vibration_value = [parameters] { switch (parameters.gc_erm_command) { - case VibrationGcErmCommand::Stop: + case Core::HID::VibrationGcErmCommand::Stop: return Controller_NPad::VibrationValue{ .amp_low = 0.0f, .freq_low = 160.0f, .amp_high = 0.0f, .freq_high = 320.0f, }; - case VibrationGcErmCommand::Start: + case Core::HID::VibrationGcErmCommand::Start: return Controller_NPad::VibrationValue{ .amp_low = 1.0f, .freq_low = 160.0f, .amp_high = 1.0f, .freq_high = 320.0f, }; - case VibrationGcErmCommand::StopHard: + case Core::HID::VibrationGcErmCommand::StopHard: return Controller_NPad::VibrationValue{ .amp_low = 0.0f, .freq_low = 0.0f, @@ -1348,7 +1344,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { const auto gc_erm_command = [last_vibration] { if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) { - return VibrationGcErmCommand::Start; + return Core::HID::VibrationGcErmCommand::Start; } /** @@ -1358,10 +1354,10 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { * This is done to reuse the controller vibration functions made for regular controllers. */ if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) { - return VibrationGcErmCommand::StopHard; + return Core::HID::VibrationGcErmCommand::StopHard; } - return VibrationGcErmCommand::Stop; + return Core::HID::VibrationGcErmCommand::Stop; }(); LOG_DEBUG(Service_HID, @@ -2037,9 +2033,6 @@ public: } }; -void ReloadInputDevices() { -} - void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { std::make_shared(system)->InstallAsService(service_manager); std::make_shared(system)->InstallAsService(service_manager); diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index b1fe75e94..2e0c33c1c 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -161,38 +161,11 @@ private: void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx); - enum class VibrationDeviceType : u32 { - Unknown = 0, - LinearResonantActuator = 1, - GcErm = 2, - }; - - enum class VibrationDevicePosition : u32 { - None = 0, - Left = 1, - Right = 2, - }; - - enum class VibrationGcErmCommand : u64 { - Stop = 0, - Start = 1, - StopHard = 2, - }; - - struct VibrationDeviceInfo { - VibrationDeviceType type{}; - VibrationDevicePosition position{}; - }; - static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); - std::shared_ptr applet_resource; KernelHelpers::ServiceContext service_context; }; -/// Reload input devices. Used when input configuration changed -void ReloadInputDevices(); - /// Registers all HID services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); -- cgit v1.2.3 From 072559dede9e4ab098b84f43ee6db31d3987b2c3 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:31:06 -0500 Subject: service/hid: Update debug pad, xpad, stubbed and controller base to use ring lifo and the emulated controller --- .../hle/service/hid/controllers/controller_base.h | 11 ---- src/core/hle/service/hid/controllers/debug_pad.cpp | 68 ++++++-------------- src/core/hle/service/hid/controllers/debug_pad.h | 73 +++++++--------------- src/core/hle/service/hid/controllers/stubbed.cpp | 3 +- src/core/hle/service/hid/controllers/stubbed.h | 11 +++- src/core/hle/service/hid/controllers/xpad.cpp | 29 +++------ src/core/hle/service/hid/controllers/xpad.h | 51 ++++++--------- 7 files changed, 80 insertions(+), 166 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 1556fb08e..4ba2eda1a 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -35,9 +35,6 @@ public: virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) {} - // Called when input devices should be loaded - virtual void OnLoadInputDevices() = 0; - void ActivateController(); void DeactivateController(); @@ -47,14 +44,6 @@ public: protected: bool is_activated{false}; - struct CommonHeader { - s64_le timestamp; - s64_le total_entry_count; - s64_le last_entry_index; - s64_le entry_count; - }; - static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); - Core::System& system; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index d439b8fb0..b2b4edf51 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -5,7 +5,10 @@ #include #include "common/common_types.h" #include "common/settings.h" +#include "core/core.h" #include "core/core_timing.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/debug_pad.h" namespace Service::HID { @@ -14,7 +17,10 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; -Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {} +Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} { + controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other); +} + Controller_DebugPad::~Controller_DebugPad() = default; void Controller_DebugPad::OnInit() {} @@ -23,63 +29,29 @@ void Controller_DebugPad::OnRelease() {} void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - shared_memory.header.timestamp = core_timing.GetCPUTicks(); - shared_memory.header.total_entry_count = 17; - if (!IsControllerActivated()) { - shared_memory.header.entry_count = 0; - shared_memory.header.last_entry_index = 0; + debug_pad_lifo.entry_count = 0; + debug_pad_lifo.last_entry_index = 0; + std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo)); return; } - shared_memory.header.entry_count = 16; - const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; - shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; - auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; - - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; if (Settings::values.debug_pad_enabled) { - cur_entry.attribute.connected.Assign(1); - auto& pad = cur_entry.pad_state; + next_state.attribute.connected.Assign(1); - using namespace Settings::NativeButton; - pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); - pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); - pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); - pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); - pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); - pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); - pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); - pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); - pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + const auto& button_state = controller->GetDebugPadButtons(); + const auto& stick_state = controller->GetSticks(); - const auto [stick_l_x_f, stick_l_y_f] = - analogs[static_cast(JoystickId::Joystick_Left)]->GetStatus(); - const auto [stick_r_x_f, stick_r_y_f] = - analogs[static_cast(JoystickId::Joystick_Right)]->GetStatus(); - cur_entry.l_stick.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); - cur_entry.l_stick.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); - cur_entry.r_stick.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); - cur_entry.r_stick.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); + next_state.pad_state = button_state; + next_state.l_stick = stick_state.left; + next_state.r_stick = stick_state.right; } - std::memcpy(data, &shared_memory, sizeof(SharedMemory)); + debug_pad_lifo.WriteNextEntry(next_state); + std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo)); } -void Controller_DebugPad::OnLoadInputDevices() { - std::transform(Settings::values.debug_pad_buttons.begin(), - Settings::values.debug_pad_buttons.begin() + - Settings::NativeButton::NUM_BUTTONS_HID, - buttons.begin(), Input::CreateDevice); - std::transform(Settings::values.debug_pad_analogs.begin(), - Settings::values.debug_pad_analogs.end(), analogs.begin(), - Input::CreateDevice); -} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index e90ae8415..11b6c669b 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -10,8 +10,14 @@ #include "common/common_types.h" #include "common/settings.h" #include "common/swap.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" + +namespace Core::HID { +class EmulatedController; +struct DebugPadButton; +struct AnalogStickState; +} // namespace Core::HID namespace Service::HID { class Controller_DebugPad final : public ControllerBase { @@ -28,66 +34,31 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - private: - struct AnalogStick { - s32_le x; - s32_le y; - }; - static_assert(sizeof(AnalogStick) == 0x8); - - struct PadState { - union { - u32_le raw{}; - BitField<0, 1, u32> a; - BitField<1, 1, u32> b; - BitField<2, 1, u32> x; - BitField<3, 1, u32> y; - BitField<4, 1, u32> l; - BitField<5, 1, u32> r; - BitField<6, 1, u32> zl; - BitField<7, 1, u32> zr; - BitField<8, 1, u32> plus; - BitField<9, 1, u32> minus; - BitField<10, 1, u32> d_left; - BitField<11, 1, u32> d_up; - BitField<12, 1, u32> d_right; - BitField<13, 1, u32> d_down; - }; - }; - static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size"); - - struct Attributes { + // This is nn::hid::DebugPadAttribute + struct DebugPadAttribute { union { u32_le raw{}; BitField<0, 1, u32> connected; }; }; - static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); + static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size"); - struct PadStates { + // This is nn::hid::DebugPadState + struct DebugPadState { s64_le sampling_number; - s64_le sampling_number2; - Attributes attribute; - PadState pad_state; - AnalogStick r_stick; - AnalogStick l_stick; + DebugPadAttribute attribute; + Core::HID::DebugPadButton pad_state; + Core::HID::AnalogStickState r_stick; + Core::HID::AnalogStickState l_stick; }; - static_assert(sizeof(PadStates) == 0x28, "PadStates is an invalid state"); + static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); - struct SharedMemory { - CommonHeader header; - std::array pad_states; - INSERT_PADDING_BYTES(0x138); - }; - static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); - SharedMemory shared_memory{}; + // This is nn::hid::detail::DebugPadLifo + Lifo debug_pad_lifo{}; + static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); + DebugPadState next_state{}; - std::array, Settings::NativeButton::NUM_BUTTONS_HID> - buttons; - std::array, Settings::NativeAnalog::NumAnalogs> - analogs; + Core::HID::EmulatedController* controller; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index 772c20453..a8c93909d 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -31,10 +31,9 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); } -void Controller_Stubbed::OnLoadInputDevices() {} - void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { common_offset = off; smart_update = true; } + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index 21092af0d..29f95a100 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -22,12 +22,17 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - void SetCommonHeaderOffset(std::size_t off); private: + struct CommonHeader { + s64_le timestamp; + s64_le total_entry_count; + s64_le last_entry_index; + s64_le entry_count; + }; + static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); + bool smart_update{}; std::size_t common_offset{}; }; diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index 41dc22cf9..29a412ff9 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -19,28 +19,19 @@ void Controller_XPad::OnRelease() {} void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - for (auto& xpad_entry : shared_memory.shared_memory_entries) { - xpad_entry.header.timestamp = core_timing.GetCPUTicks(); - xpad_entry.header.total_entry_count = 17; - - if (!IsControllerActivated()) { - xpad_entry.header.entry_count = 0; - xpad_entry.header.last_entry_index = 0; - return; - } - xpad_entry.header.entry_count = 16; - - const auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; - xpad_entry.header.last_entry_index = (xpad_entry.header.last_entry_index + 1) % 17; - auto& cur_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index]; - - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + if (!IsControllerActivated()) { + basic_xpad_lifo.entry_count = 0; + basic_xpad_lifo.last_entry_index = 0; + std::memcpy(data, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); + return; } + + const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; // TODO(ogniK): Update xpad states - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); + basic_xpad_lifo.WriteNextEntry(next_state); + std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); } -void Controller_XPad::OnLoadInputDevices() {} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index f9ab5facf..a5421f93b 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -8,7 +8,9 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" namespace Service::HID { class Controller_XPad final : public ControllerBase { @@ -25,11 +27,9 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - private: - struct Attributes { + // This is nn::hid::BasicXpadAttributeSet + struct BasicXpadAttributeSet { union { u32_le raw{}; BitField<0, 1, u32> is_connected; @@ -40,9 +40,10 @@ private: BitField<5, 1, u32> is_right_wired; }; }; - static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size"); + static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size"); - struct Buttons { + // This is nn::hid::BasicXpadButtonSet + struct BasicXpadButtonSet { union { u32_le raw{}; // Button states @@ -88,35 +89,21 @@ private: BitField<30, 1, u32> handheld_left_b; }; }; - static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size"); - - struct AnalogStick { - s32_le x; - s32_le y; - }; - static_assert(sizeof(AnalogStick) == 0x8, "AnalogStick is an invalid size"); + static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size"); - struct XPadState { + // This is nn::hid::detail::BasicXpadState + struct BasicXpadState { s64_le sampling_number; - s64_le sampling_number2; - Attributes attributes; - Buttons pad_states; - AnalogStick l_stick; - AnalogStick r_stick; + BasicXpadAttributeSet attributes; + BasicXpadButtonSet pad_states; + Core::HID::AnalogStickState l_stick; + Core::HID::AnalogStickState r_stick; }; - static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size"); + static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size"); - struct XPadEntry { - CommonHeader header; - std::array pad_states{}; - INSERT_PADDING_BYTES(0x138); - }; - static_assert(sizeof(XPadEntry) == 0x400, "XPadEntry is an invalid size"); - - struct SharedMemory { - std::array shared_memory_entries{}; - }; - static_assert(sizeof(SharedMemory) == 0x1000, "SharedMemory is an invalid size"); - SharedMemory shared_memory{}; + // This is nn::hid::detail::BasicXpadLifo + Lifo basic_xpad_lifo{}; + static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size"); + BasicXpadState next_state{}; }; } // namespace Service::HID -- cgit v1.2.3 From afe2d667d95e74be8f401010fa31a9eeca77d93a Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:33:50 -0500 Subject: service/hid: Update touch and gestures to use ring lifo and the emulated console --- src/core/hle/service/hid/controllers/gesture.cpp | 274 ++++++++------------- src/core/hle/service/hid/controllers/gesture.h | 80 +++--- .../hle/service/hid/controllers/touchscreen.cpp | 136 ++++------ src/core/hle/service/hid/controllers/touchscreen.h | 71 ++---- 4 files changed, 191 insertions(+), 370 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 764abb5b6..2f98cc54b 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -5,8 +5,10 @@ #include "common/logging/log.h" #include "common/math_util.h" #include "common/settings.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/gesture.h" namespace Service::HID { @@ -23,16 +25,15 @@ constexpr f32 Square(s32 num) { return static_cast(num * num); } -Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {} +Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) { + console = system.HIDCore().GetEmulatedConsole(); +} + Controller_Gesture::~Controller_Gesture() = default; void Controller_Gesture::OnInit() { - for (std::size_t id = 0; id < MAX_FINGERS; ++id) { - mouse_finger_id[id] = MAX_POINTS; - keyboard_finger_id[id] = MAX_POINTS; - udp_finger_id[id] = MAX_POINTS; - } - shared_memory.header.entry_count = 0; + gesture_lifo.entry_count = 0; + gesture_lifo.last_entry_index = 0; force_update = true; } @@ -40,50 +41,43 @@ void Controller_Gesture::OnRelease() {} void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - shared_memory.header.timestamp = core_timing.GetCPUTicks(); - shared_memory.header.total_entry_count = 17; - + // TODO FIND WTF IS WRONG HERE!!!!!!!! + return; if (!IsControllerActivated()) { - shared_memory.header.entry_count = 0; - shared_memory.header.last_entry_index = 0; + gesture_lifo.entry_count = 0; + gesture_lifo.last_entry_index = 0; + std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo)); return; } ReadTouchInput(); GestureProperties gesture = GetGestureProperties(); - f32 time_difference = static_cast(shared_memory.header.timestamp - last_update_timestamp) / - (1000 * 1000 * 1000); + f32 time_difference = + static_cast(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); // Only update if necesary if (!ShouldUpdateGesture(gesture, time_difference)) { return; } - last_update_timestamp = shared_memory.header.timestamp; + last_update_timestamp = gesture_lifo.timestamp; UpdateGestureSharedMemory(data, size, gesture, time_difference); } void Controller_Gesture::ReadTouchInput() { - const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); - const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); - for (std::size_t id = 0; id < mouse_status.size(); ++id) { - mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); - udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); - } - - if (Settings::values.use_touch_from_button) { - const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); - for (std::size_t id = 0; id < mouse_status.size(); ++id) { - keyboard_finger_id[id] = - UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); - } + const auto touch_status = console->GetTouch(); + for (std::size_t id = 0; id < fingers.size(); ++id) { + const Core::HID::TouchFinger& status = touch_status[id]; + Finger& finger = fingers[id]; + finger.pos = status.position; + finger.pressed = status.pressed; } } bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) { - const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; if (force_update) { force_update = false; return true; @@ -97,7 +91,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, } // Update on press and hold event after 0.5 seconds - if (last_entry.type == TouchType::Touch && last_entry.point_count == 1 && + if (last_entry.type == GestureType::Touch && last_entry.point_count == 1 && time_difference > press_delay) { return enable_press_and_tap; } @@ -108,27 +102,19 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, GestureProperties& gesture, f32 time_difference) { - TouchType type = TouchType::Idle; - Attribute attributes{}; - - const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; - shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + GestureType type = GestureType::Idle; + GestureAttribute attributes{}; - if (shared_memory.header.entry_count < 16) { - shared_memory.header.entry_count++; - } - - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; - // Reset values to default - cur_entry.delta = {}; - cur_entry.vel_x = 0; - cur_entry.vel_y = 0; - cur_entry.direction = Direction::None; - cur_entry.rotation_angle = 0; - cur_entry.scale = 0; + // Reset next state to default + next_state.sampling_number = last_entry.sampling_number + 1; + next_state.delta = {}; + next_state.vel_x = 0; + next_state.vel_y = 0; + next_state.direction = GestureDirection::None; + next_state.rotation_angle = 0; + next_state.scale = 0; if (gesture.active_points > 0) { if (last_gesture.active_points == 0) { @@ -141,46 +127,47 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, } // Apply attributes - cur_entry.detection_count = gesture.detection_count; - cur_entry.type = type; - cur_entry.attributes = attributes; - cur_entry.pos = gesture.mid_point; - cur_entry.point_count = static_cast(gesture.active_points); - cur_entry.points = gesture.points; + next_state.detection_count = gesture.detection_count; + next_state.type = type; + next_state.attributes = attributes; + next_state.pos = gesture.mid_point; + next_state.point_count = static_cast(gesture.active_points); + next_state.points = gesture.points; last_gesture = gesture; - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); + gesture_lifo.WriteNextEntry(next_state); + std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); } -void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, - Attribute& attributes) { - const auto& last_entry = GetLastGestureEntry(); +void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, + GestureAttribute& attributes) { + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; gesture.detection_count++; - type = TouchType::Touch; + type = GestureType::Touch; // New touch after cancel is not considered new - if (last_entry.type != TouchType::Cancel) { + if (last_entry.type != GestureType::Cancel) { attributes.is_new_touch.Assign(1); enable_press_and_tap = true; } } -void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type, +void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; // Promote to pan type if touch moved for (size_t id = 0; id < MAX_POINTS; id++) { if (gesture.points[id] != last_gesture.points[id]) { - type = TouchType::Pan; + type = GestureType::Pan; break; } } // Number of fingers changed cancel the last event and clear data if (gesture.active_points != last_gesture.active_points) { - type = TouchType::Cancel; + type = GestureType::Cancel; enable_press_and_tap = false; gesture.active_points = 0; gesture.mid_point = {}; @@ -189,41 +176,41 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch } // Calculate extra parameters of panning - if (type == TouchType::Pan) { + if (type == GestureType::Pan) { UpdatePanEvent(gesture, last_gesture, type, time_difference); return; } // Promote to press type - if (last_entry.type == TouchType::Touch) { - type = TouchType::Press; + if (last_entry.type == GestureType::Touch) { + type = GestureType::Press; } } void Controller_Gesture::EndGesture(GestureProperties& gesture, - GestureProperties& last_gesture_props, TouchType& type, - Attribute& attributes, f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); + GestureProperties& last_gesture_props, GestureType& type, + GestureAttribute& attributes, f32 time_difference) { + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; if (last_gesture_props.active_points != 0) { switch (last_entry.type) { - case TouchType::Touch: + case GestureType::Touch: if (enable_press_and_tap) { SetTapEvent(gesture, last_gesture_props, type, attributes); return; } - type = TouchType::Cancel; + type = GestureType::Cancel; force_update = true; break; - case TouchType::Press: - case TouchType::Tap: - case TouchType::Swipe: - case TouchType::Pinch: - case TouchType::Rotate: - type = TouchType::Complete; + case GestureType::Press: + case GestureType::Tap: + case GestureType::Swipe: + case GestureType::Pinch: + case GestureType::Rotate: + type = GestureType::Complete; force_update = true; break; - case TouchType::Pan: + case GestureType::Pan: EndPanEvent(gesture, last_gesture_props, type, time_difference); break; default: @@ -231,15 +218,15 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture, } return; } - if (last_entry.type == TouchType::Complete || last_entry.type == TouchType::Cancel) { + if (last_entry.type == GestureType::Complete || last_entry.type == GestureType::Cancel) { gesture.detection_count++; } } void Controller_Gesture::SetTapEvent(GestureProperties& gesture, - GestureProperties& last_gesture_props, TouchType& type, - Attribute& attributes) { - type = TouchType::Tap; + GestureProperties& last_gesture_props, GestureType& type, + GestureAttribute& attributes) { + type = GestureType::Tap; gesture = last_gesture_props; force_update = true; f32 tap_time_difference = @@ -251,44 +238,42 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture, } void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, - GestureProperties& last_gesture_props, TouchType& type, + GestureProperties& last_gesture_props, GestureType& type, f32 time_difference) { - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; - const auto& last_entry = GetLastGestureEntry(); + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; - cur_entry.delta = gesture.mid_point - last_entry.pos; - cur_entry.vel_x = static_cast(cur_entry.delta.x) / time_difference; - cur_entry.vel_y = static_cast(cur_entry.delta.y) / time_difference; + next_state.delta = gesture.mid_point - last_entry.pos; + next_state.vel_x = static_cast(next_state.delta.x) / time_difference; + next_state.vel_y = static_cast(next_state.delta.y) / time_difference; last_pan_time_difference = time_difference; // Promote to pinch type if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > pinch_threshold) { - type = TouchType::Pinch; - cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance; + type = GestureType::Pinch; + next_state.scale = gesture.average_distance / last_gesture_props.average_distance; } const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / (1 + (gesture.angle * last_gesture_props.angle))); // Promote to rotate type if (std::abs(angle_between_two_lines) > angle_threshold) { - type = TouchType::Rotate; - cur_entry.scale = 0; - cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; + type = GestureType::Rotate; + next_state.scale = 0; + next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; } } void Controller_Gesture::EndPanEvent(GestureProperties& gesture, - GestureProperties& last_gesture_props, TouchType& type, + GestureProperties& last_gesture_props, GestureType& type, f32 time_difference) { - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; - const auto& last_entry = GetLastGestureEntry(); - cur_entry.vel_x = + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + next_state.vel_x = static_cast(last_entry.delta.x) / (last_pan_time_difference + time_difference); - cur_entry.vel_y = + next_state.vel_y = static_cast(last_entry.delta.y) / (last_pan_time_difference + time_difference); const f32 curr_vel = - std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); + std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); // Set swipe event with parameters if (curr_vel > swipe_threshold) { @@ -297,93 +282,34 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, } // End panning without swipe - type = TouchType::Complete; - cur_entry.vel_x = 0; - cur_entry.vel_y = 0; + type = GestureType::Complete; + next_state.vel_x = 0; + next_state.vel_y = 0; force_update = true; } void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, - GestureProperties& last_gesture_props, TouchType& type) { - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; - const auto& last_entry = GetLastGestureEntry(); + GestureProperties& last_gesture_props, GestureType& type) { + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; - type = TouchType::Swipe; + type = GestureType::Swipe; gesture = last_gesture_props; force_update = true; - cur_entry.delta = last_entry.delta; + next_state.delta = last_entry.delta; - if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) { - if (cur_entry.delta.x > 0) { - cur_entry.direction = Direction::Right; + if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { + if (next_state.delta.x > 0) { + next_state.direction = GestureDirection::Right; return; } - cur_entry.direction = Direction::Left; + next_state.direction = GestureDirection::Left; return; } - if (cur_entry.delta.y > 0) { - cur_entry.direction = Direction::Down; + if (next_state.delta.y > 0) { + next_state.direction = GestureDirection::Down; return; } - cur_entry.direction = Direction::Up; -} - -void Controller_Gesture::OnLoadInputDevices() { - touch_mouse_device = Input::CreateDevice("engine:emu_window"); - touch_udp_device = Input::CreateDevice("engine:cemuhookudp"); - touch_btn_device = Input::CreateDevice("engine:touch_from_button"); -} - -std::optional Controller_Gesture::GetUnusedFingerID() const { - // Dont assign any touch input to a point if disabled - if (!Settings::values.touchscreen.enabled) { - return std::nullopt; - } - std::size_t first_free_id = 0; - while (first_free_id < MAX_POINTS) { - if (!fingers[first_free_id].pressed) { - return first_free_id; - } else { - first_free_id++; - } - } - return std::nullopt; -} - -Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() { - return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; -} - -const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { - return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; -} - -std::size_t Controller_Gesture::UpdateTouchInputEvent( - const std::tuple& touch_input, std::size_t finger_id) { - const auto& [x, y, pressed] = touch_input; - if (finger_id > MAX_POINTS) { - LOG_ERROR(Service_HID, "Invalid finger id {}", finger_id); - return MAX_POINTS; - } - if (pressed) { - if (finger_id == MAX_POINTS) { - const auto first_free_id = GetUnusedFingerID(); - if (!first_free_id) { - // Invalid finger id do nothing - return MAX_POINTS; - } - finger_id = first_free_id.value(); - fingers[finger_id].pressed = true; - } - fingers[finger_id].pos = {x, y}; - return finger_id; - } - - if (finger_id != MAX_POINTS) { - fingers[finger_id].pressed = false; - } - - return MAX_POINTS; + next_state.direction = GestureDirection::Up; } Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 7e7ae6625..8e6f315a4 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -8,8 +8,12 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "common/point.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" + +namespace Core::HID { +class EmulatedController; +} // namespace Core::HID namespace Service::HID { class Controller_Gesture final : public ControllerBase { @@ -26,14 +30,12 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - private: static constexpr size_t MAX_FINGERS = 16; static constexpr size_t MAX_POINTS = 4; - enum class TouchType : u32 { + // This is nn::hid::GestureType + enum class GestureType : u32 { Idle, // Nothing touching the screen Complete, // Set at the end of a touch event Cancel, // Set when the number of fingers change @@ -46,7 +48,8 @@ private: Rotate, // All points rotating from the midpoint }; - enum class Direction : u32 { + // This is nn::hid::GestureDirection + enum class GestureDirection : u32 { None, Left, Up, @@ -54,7 +57,8 @@ private: Down, }; - struct Attribute { + // This is nn::hid::GestureAttribute + struct GestureAttribute { union { u32_le raw{}; @@ -62,31 +66,25 @@ private: BitField<8, 1, u32> is_double_tap; }; }; - static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); + static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); + // This is nn::hid::GestureState struct GestureState { s64_le sampling_number; - s64_le sampling_number2; s64_le detection_count; - TouchType type; - Direction direction; + GestureType type; + GestureDirection direction; Common::Point pos; Common::Point delta; f32 vel_x; f32 vel_y; - Attribute attributes; + GestureAttribute attributes; f32 scale; f32 rotation_angle; s32_le point_count; std::array, 4> points; }; - static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); - - struct SharedMemory { - CommonHeader header; - std::array gesture_states; - }; - static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size"); + static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); struct Finger { Common::Point pos{}; @@ -114,58 +112,42 @@ private: f32 time_difference); // Initializes new gesture - void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes); + void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes); // Updates existing gesture state - void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference); + void UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference); // Terminates exiting gesture void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, - TouchType& type, Attribute& attributes, f32 time_difference); + GestureType& type, GestureAttribute& attributes, f32 time_difference); // Set current event to a tap event void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - TouchType& type, Attribute& attributes); + GestureType& type, GestureAttribute& attributes); // Calculates and set the extra parameters related to a pan event void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - TouchType& type, f32 time_difference); + GestureType& type, f32 time_difference); // Terminates the pan event void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - TouchType& type, f32 time_difference); + GestureType& type, f32 time_difference); // Set current event to a swipe event void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - TouchType& type); - - // Returns an unused finger id, if there is no fingers available std::nullopt is returned. - [[nodiscard]] std::optional GetUnusedFingerID() const; - - // Retrieves the last gesture entry, as indicated by shared memory indices. - [[nodiscard]] GestureState& GetLastGestureEntry(); - [[nodiscard]] const GestureState& GetLastGestureEntry() const; - - /** - * If the touch is new it tries to assign a new finger id, if there is no fingers available no - * changes will be made. Updates the coordinates if the finger id it's already set. If the touch - * ends delays the output by one frame to set the end_touch flag before finally freeing the - * finger id - */ - size_t UpdateTouchInputEvent(const std::tuple& touch_input, - size_t finger_id); + GestureType& type); // Returns the average distance, angle and middle point of the active fingers GestureProperties GetGestureProperties(); - SharedMemory shared_memory{}; - std::unique_ptr touch_mouse_device; - std::unique_ptr touch_udp_device; - std::unique_ptr touch_btn_device; - std::array mouse_finger_id{}; - std::array keyboard_finger_id{}; - std::array udp_finger_id{}; + // This is nn::hid::detail::GestureLifo + Lifo gesture_lifo{}; + static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); + GestureState next_state{}; + std::array fingers{}; + Core::HID::EmulatedConsole* console; + GestureProperties last_gesture{}; s64_le last_update_timestamp{}; s64_le last_tap_timestamp{}; diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 6ef17acc5..e0a44d06b 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -7,72 +7,79 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/settings.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/touchscreen.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; -Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} {} +Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} { + console = system.HIDCore().GetEmulatedConsole(); +} + Controller_Touchscreen::~Controller_Touchscreen() = default; -void Controller_Touchscreen::OnInit() { - for (std::size_t id = 0; id < MAX_FINGERS; ++id) { - mouse_finger_id[id] = MAX_FINGERS; - keyboard_finger_id[id] = MAX_FINGERS; - udp_finger_id[id] = MAX_FINGERS; - } -} +void Controller_Touchscreen::OnInit() {} void Controller_Touchscreen::OnRelease() {} void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - shared_memory.header.timestamp = core_timing.GetCPUTicks(); - shared_memory.header.total_entry_count = 17; + touch_screen_lifo.timestamp = core_timing.GetCPUTicks(); if (!IsControllerActivated()) { - shared_memory.header.entry_count = 0; - shared_memory.header.last_entry_index = 0; + touch_screen_lifo.entry_count = 0; + touch_screen_lifo.last_entry_index = 0; + std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo)); return; } - shared_memory.header.entry_count = 16; - const auto& last_entry = - shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; - shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; - auto& cur_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; + const auto touch_status = console->GetTouch(); + for (std::size_t id = 0; id < MAX_FINGERS; id++) { + const auto& current_touch = touch_status[id]; + auto& finger = fingers[id]; + finger.position = current_touch.position; + finger.id = current_touch.id; - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + if (finger.attribute.start_touch) { + finger.attribute.raw = 0; + continue; + } - const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); - const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); - for (std::size_t id = 0; id < mouse_status.size(); ++id) { - mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); - udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); - } + if (finger.attribute.end_touch) { + finger.attribute.raw = 0; + finger.pressed = false; + continue; + } + + if (!finger.pressed && current_touch.pressed) { + finger.attribute.start_touch.Assign(1); + finger.pressed = true; + continue; + } - if (Settings::values.use_touch_from_button) { - const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); - for (std::size_t id = 0; id < mouse_status.size(); ++id) { - keyboard_finger_id[id] = - UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); + if (finger.pressed && !current_touch.pressed) { + finger.attribute.raw = 0; + finger.attribute.end_touch.Assign(1); } } - std::array active_fingers; + std::array active_fingers; const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), [](const auto& finger) { return finger.pressed; }); const auto active_fingers_count = static_cast(std::distance(active_fingers.begin(), end_iter)); const u64 tick = core_timing.GetCPUTicks(); - cur_entry.entry_count = static_cast(active_fingers_count); + const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state; + + next_state.sampling_number = last_entry.sampling_number + 1; + next_state.entry_count = static_cast(active_fingers_count); + for (std::size_t id = 0; id < MAX_FINGERS; ++id) { - auto& touch_entry = cur_entry.states[id]; + auto& touch_entry = next_state.states[id]; if (id < active_fingers_count) { const auto& [active_x, active_y] = active_fingers[id].position; touch_entry.position = { @@ -97,66 +104,9 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin touch_entry.finger = 0; } } - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(TouchScreenSharedMemory)); -} - -void Controller_Touchscreen::OnLoadInputDevices() { - touch_mouse_device = Input::CreateDevice("engine:emu_window"); - touch_udp_device = Input::CreateDevice("engine:cemuhookudp"); - touch_btn_device = Input::CreateDevice("engine:touch_from_button"); -} - -std::optional Controller_Touchscreen::GetUnusedFingerID() const { - // Dont assign any touch input to a finger if disabled - if (!Settings::values.touchscreen.enabled) { - return std::nullopt; - } - std::size_t first_free_id = 0; - while (first_free_id < MAX_FINGERS) { - if (!fingers[first_free_id].pressed) { - return first_free_id; - } else { - first_free_id++; - } - } - return std::nullopt; -} - -std::size_t Controller_Touchscreen::UpdateTouchInputEvent( - const std::tuple& touch_input, std::size_t finger_id) { - const auto& [x, y, pressed] = touch_input; - if (finger_id > MAX_FINGERS) { - LOG_ERROR(Service_HID, "Invalid finger id {}", finger_id); - return MAX_FINGERS; - } - if (pressed) { - Attributes attribute{}; - if (finger_id == MAX_FINGERS) { - const auto first_free_id = GetUnusedFingerID(); - if (!first_free_id) { - // Invalid finger id do nothing - return MAX_FINGERS; - } - finger_id = first_free_id.value(); - fingers[finger_id].pressed = true; - fingers[finger_id].id = static_cast(finger_id); - attribute.start_touch.Assign(1); - } - fingers[finger_id].position = {x, y}; - fingers[finger_id].attribute = attribute; - return finger_id; - } - - if (finger_id != MAX_FINGERS) { - if (!fingers[finger_id].attribute.end_touch) { - fingers[finger_id].attribute.end_touch.Assign(1); - fingers[finger_id].attribute.start_touch.Assign(0); - return finger_id; - } - fingers[finger_id].pressed = false; - } - return MAX_FINGERS; + touch_screen_lifo.WriteNextEntry(next_state); + std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo)); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 8e9b40c0a..bcf79237d 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -9,18 +9,22 @@ #include "common/common_types.h" #include "common/point.h" #include "common/swap.h" -#include "core/frontend/input.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" namespace Service::HID { class Controller_Touchscreen final : public ControllerBase { public: + // This is nn::hid::TouchScreenModeForNx enum class TouchScreenModeForNx : u8 { UseSystemSetting, Finger, Heat2, }; + // This is nn::hid::TouchScreenConfigurationForNx struct TouchScreenConfigurationForNx { TouchScreenModeForNx mode; INSERT_PADDING_BYTES_NOINIT(0x7); @@ -41,73 +45,32 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - private: static constexpr std::size_t MAX_FINGERS = 16; - // Returns an unused finger id, if there is no fingers available std::nullopt will be returned - std::optional GetUnusedFingerID() const; - - // If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no - // changes will be made. Updates the coordinates if the finger id it's already set. If the touch - // ends delays the output by one frame to set the end_touch flag before finally freeing the - // finger id - std::size_t UpdateTouchInputEvent(const std::tuple& touch_input, - std::size_t finger_id); - - struct Attributes { - union { - u32 raw{}; - BitField<0, 1, u32> start_touch; - BitField<1, 1, u32> end_touch; - }; - }; - static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); - - struct TouchState { - u64_le delta_time; - Attributes attribute; - u32_le finger; - Common::Point position; - u32_le diameter_x; - u32_le diameter_y; - u32_le rotation_angle; - }; - static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); - - struct TouchScreenEntry { + // This is nn::hid::TouchScreenState + struct TouchScreenState { s64_le sampling_number; - s64_le sampling_number2; s32_le entry_count; - std::array states; + INSERT_PADDING_BYTES(4); // Reserved + std::array states; }; - static_assert(sizeof(TouchScreenEntry) == 0x298, "TouchScreenEntry is an invalid size"); - - struct TouchScreenSharedMemory { - CommonHeader header; - std::array shared_memory_entries{}; - INSERT_PADDING_BYTES(0x3c8); - }; - static_assert(sizeof(TouchScreenSharedMemory) == 0x3000, - "TouchScreenSharedMemory is an invalid size"); + static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); struct Finger { u64_le last_touch{}; Common::Point position; u32_le id{}; bool pressed{}; - Attributes attribute; + Core::HID::TouchAttribute attribute; }; - TouchScreenSharedMemory shared_memory{}; - std::unique_ptr touch_mouse_device; - std::unique_ptr touch_udp_device; - std::unique_ptr touch_btn_device; - std::array mouse_finger_id; - std::array keyboard_finger_id; - std::array udp_finger_id; + // This is nn::hid::detail::TouchScreenLifo + Lifo touch_screen_lifo{}; + static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); + TouchScreenState next_state{}; + std::array fingers; + Core::HID::EmulatedConsole* console; }; } // namespace Service::HID -- cgit v1.2.3 From 800a66d25a214363d1d06b68a59f315ed295f9e4 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:35:27 -0500 Subject: service/hid: Update mouse and keyboard to use ring lifo and the emulated device --- src/core/hle/service/hid/controllers/keyboard.cpp | 56 +++++++------------- src/core/hle/service/hid/controllers/keyboard.h | 53 ++++++------------- src/core/hle/service/hid/controllers/mouse.cpp | 62 ++++++++++------------- src/core/hle/service/hid/controllers/mouse.h | 58 ++++----------------- 4 files changed, 71 insertions(+), 158 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index c6c620008..db0f56b92 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -5,14 +5,19 @@ #include #include "common/common_types.h" #include "common/settings.h" +#include "core/core.h" #include "core/core_timing.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/keyboard.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; constexpr u8 KEYS_PER_BYTE = 8; -Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {} +Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} { + emulated_devices = system.HIDCore().GetEmulatedDevices(); +} + Controller_Keyboard::~Controller_Keyboard() = default; void Controller_Keyboard::OnInit() {} @@ -21,51 +26,26 @@ void Controller_Keyboard::OnRelease() {} void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - shared_memory.header.timestamp = core_timing.GetCPUTicks(); - shared_memory.header.total_entry_count = 17; - if (!IsControllerActivated()) { - shared_memory.header.entry_count = 0; - shared_memory.header.last_entry_index = 0; + keyboard_lifo.entry_count = 0; + keyboard_lifo.last_entry_index = 0; + std::memcpy(data, &keyboard_lifo, sizeof(keyboard_lifo)); return; } - shared_memory.header.entry_count = 16; - - const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; - shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; - auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; - cur_entry.key.fill(0); if (Settings::values.keyboard_enabled) { - for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { - auto& entry = cur_entry.key[i / KEYS_PER_BYTE]; - entry = static_cast(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE))); - } + const auto& keyboard_state = emulated_devices->GetKeyboard(); + const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier(); - using namespace Settings::NativeKeyboard; - - // TODO: Assign the correct key to all modifiers - cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus()); - cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus()); - cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus()); - cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus()); - cur_entry.modifier.gui.Assign(0); - cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus()); - cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus()); - cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus()); - cur_entry.modifier.katakana.Assign(0); - cur_entry.modifier.hiragana.Assign(0); + next_state.key = keyboard_state; + next_state.modifier = keyboard_modifier_state; } - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); -} -void Controller_Keyboard::OnLoadInputDevices() { - std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(), - keyboard_keys.begin(), Input::CreateDevice); - std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(), - keyboard_mods.begin(), Input::CreateDevice); + keyboard_lifo.WriteNextEntry(next_state); + std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo)); } + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 172a80e9c..6919e092a 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -10,8 +10,14 @@ #include "common/common_types.h" #include "common/settings.h" #include "common/swap.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" + +namespace Core::HID { +class EmulatedDevices; +struct KeyboardModifier; +struct KeyboardKey; +} // namespace Core::HID namespace Service::HID { class Controller_Keyboard final : public ControllerBase { @@ -28,47 +34,20 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - private: - struct Modifiers { - union { - u32_le raw{}; - BitField<0, 1, u32> control; - BitField<1, 1, u32> shift; - BitField<2, 1, u32> left_alt; - BitField<3, 1, u32> right_alt; - BitField<4, 1, u32> gui; - BitField<8, 1, u32> caps_lock; - BitField<9, 1, u32> scroll_lock; - BitField<10, 1, u32> num_lock; - BitField<11, 1, u32> katakana; - BitField<12, 1, u32> hiragana; - }; - }; - static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size"); - + // This is nn::hid::detail::KeyboardState struct KeyboardState { s64_le sampling_number; - s64_le sampling_number2; - - Modifiers modifier; - std::array key; + Core::HID::KeyboardModifier modifier; + Core::HID::KeyboardKey key; }; - static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); + static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); - struct SharedMemory { - CommonHeader header; - std::array pad_states; - INSERT_PADDING_BYTES(0x28); - }; - static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); - SharedMemory shared_memory{}; + // This is nn::hid::detail::KeyboardLifo + Lifo keyboard_lifo{}; + static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); + KeyboardState next_state{}; - std::array, Settings::NativeKeyboard::NumKeyboardKeys> - keyboard_keys; - std::array, Settings::NativeKeyboard::NumKeyboardMods> - keyboard_mods; + Core::HID::EmulatedDevices* emulated_devices; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 2211f1144..2f607bfe9 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -4,14 +4,19 @@ #include #include "common/common_types.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/mouse.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; -Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {} +Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} { + emulated_devices = system.HIDCore().GetEmulatedDevices(); +} + Controller_Mouse::~Controller_Mouse() = default; void Controller_Mouse::OnInit() {} @@ -19,50 +24,35 @@ void Controller_Mouse::OnRelease() {} void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - shared_memory.header.timestamp = core_timing.GetCPUTicks(); - shared_memory.header.total_entry_count = 17; + mouse_lifo.timestamp = core_timing.GetCPUTicks(); if (!IsControllerActivated()) { - shared_memory.header.entry_count = 0; - shared_memory.header.last_entry_index = 0; + mouse_lifo.entry_count = 0; + mouse_lifo.last_entry_index = 0; + std::memcpy(data, &mouse_lifo, sizeof(mouse_lifo)); return; } - shared_memory.header.entry_count = 16; - - auto& last_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index]; - shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; - auto& cur_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index]; - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + const auto& last_entry = mouse_lifo.ReadCurrentEntry().state; + next_state.sampling_number = last_entry.sampling_number + 1; - cur_entry.attribute.raw = 0; + next_state.attribute.raw = 0; if (Settings::values.mouse_enabled) { - const auto [px, py, sx, sy] = mouse_device->GetStatus(); - const auto x = static_cast(px * Layout::ScreenUndocked::Width); - const auto y = static_cast(py * Layout::ScreenUndocked::Height); - cur_entry.x = x; - cur_entry.y = y; - cur_entry.delta_x = x - last_entry.x; - cur_entry.delta_y = y - last_entry.y; - cur_entry.mouse_wheel_x = sx; - cur_entry.mouse_wheel_y = sy; - cur_entry.attribute.is_connected.Assign(1); - - using namespace Settings::NativeMouseButton; - cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus()); - cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus()); - cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus()); - cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus()); - cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus()); + const auto& mouse_button_state = emulated_devices->GetMouseButtons(); + const auto& mouse_position_state = emulated_devices->GetMousePosition(); + next_state.attribute.is_connected.Assign(1); + next_state.x = mouse_position_state.x; + next_state.y = mouse_position_state.y; + next_state.delta_x = next_state.x - last_entry.x; + next_state.delta_y = next_state.y - last_entry.y; + next_state.delta_wheel_x = mouse_position_state.delta_wheel_x; + next_state.delta_wheel_y = mouse_position_state.delta_wheel_y; + + next_state.button = mouse_button_state; } - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); + mouse_lifo.WriteNextEntry(next_state); + std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo)); } -void Controller_Mouse::OnLoadInputDevices() { - //mouse_device = Input::CreateDevice(Settings::values.mouse_device); - std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), - mouse_button_devices.begin(), Input::CreateDevice); -} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 3d391a798..ce868a247 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -9,8 +9,13 @@ #include "common/common_types.h" #include "common/settings.h" #include "common/swap.h" -#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" + +namespace Core::HID { +class EmulatedDevices; +struct MouseState; +} // namespace Core::HID namespace Service::HID { class Controller_Mouse final : public ControllerBase { @@ -27,53 +32,12 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - private: - struct Buttons { - union { - u32_le raw{}; - BitField<0, 1, u32> left; - BitField<1, 1, u32> right; - BitField<2, 1, u32> middle; - BitField<3, 1, u32> forward; - BitField<4, 1, u32> back; - }; - }; - static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size"); - - struct Attributes { - union { - u32_le raw{}; - BitField<0, 1, u32> transferable; - BitField<1, 1, u32> is_connected; - }; - }; - static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); - - struct MouseState { - s64_le sampling_number; - s64_le sampling_number2; - s32_le x; - s32_le y; - s32_le delta_x; - s32_le delta_y; - s32_le mouse_wheel_x; - s32_le mouse_wheel_y; - Buttons button; - Attributes attribute; - }; - static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size"); - - struct SharedMemory { - CommonHeader header; - std::array mouse_states; - }; - SharedMemory shared_memory{}; + // This is nn::hid::detail::MouseLifo + Lifo mouse_lifo{}; + static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); + Core::HID::MouseState next_state{}; - std::unique_ptr mouse_device; - std::array, Settings::NativeMouseButton::NumMouseButtons> - mouse_button_devices; + Core::HID::EmulatedDevices* emulated_devices; }; } // namespace Service::HID -- cgit v1.2.3 From a2ad5762e61f5d63d9a8c8a409f32c24409df67f Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:36:05 -0500 Subject: service/hid: Update console sixaxis to the emulated console --- .../service/hid/controllers/console_sixaxis.cpp | 33 +++++++++------------- .../hle/service/hid/controllers/console_sixaxis.h | 21 ++++++++------ 2 files changed, 26 insertions(+), 28 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index bda6e2557..1d351fde0 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/settings.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/console_sixaxis.h" @@ -10,7 +11,10 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_) - : ControllerBase{system_} {} + : ControllerBase{system_} { + console = system.HIDCore().GetEmulatedConsole(); +} + Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; void Controller_ConsoleSixAxis::OnInit() {} @@ -38,25 +42,21 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti cur_entry.sampling_number2 = cur_entry.sampling_number; // Try to read sixaxis sensor states - MotionDevice motion_device{}; - const auto& device = motions[0]; - if (device) { - std::tie(motion_device.accel, motion_device.gyro, motion_device.rotation, - motion_device.orientation, motion_device.quaternion) = device->GetStatus(); - console_six_axis.is_seven_six_axis_sensor_at_rest = motion_device.gyro.Length2() < 0.0001f; - } + const auto motion_status = console->GetMotion(); - cur_entry.accel = motion_device.accel; + console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; + + cur_entry.accel = motion_status.accel; // Zero gyro values as they just mess up with the camera // Note: Probably a correct sensivity setting must be set cur_entry.gyro = {}; cur_entry.quaternion = { { - motion_device.quaternion.xyz.y, - motion_device.quaternion.xyz.x, - -motion_device.quaternion.w, + motion_status.quaternion.xyz.y, + motion_status.quaternion.xyz.x, + -motion_status.quaternion.w, }, - -motion_device.quaternion.xyz.z, + -motion_status.quaternion.xyz.z, }; console_six_axis.sampling_number++; @@ -70,13 +70,6 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti std::memcpy(transfer_memory, &seven_six_axis, sizeof(seven_six_axis)); } -void Controller_ConsoleSixAxis::OnLoadInputDevices() { - const auto player = Settings::values.players.GetValue()[0]; - std::transform(player.motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, - player.motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions.begin(), - Input::CreateDevice); -} - void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) { is_transfer_memory_set = true; transfer_memory = t_mem; diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index fd8a427af..6d18d2ce0 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -5,10 +5,10 @@ #pragma once #include -#include "common/bit_field.h" #include "common/common_types.h" #include "common/quaternion.h" -#include "core/frontend/input.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" namespace Service::HID { @@ -26,9 +26,6 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - // Called on InitializeSevenSixAxisSensor void SetTransferMemoryPointer(u8* t_mem); @@ -47,12 +44,22 @@ private: }; static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size"); + struct CommonHeader { + s64_le timestamp; + s64_le total_entry_count; + s64_le last_entry_index; + s64_le entry_count; + }; + static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); + + // TODO(german77): SevenSixAxisMemory doesn't follow the standard lifo. Investigate struct SevenSixAxisMemory { CommonHeader header{}; std::array sevensixaxis_states{}; }; static_assert(sizeof(SevenSixAxisMemory) == 0xA70, "SevenSixAxisMemory is an invalid size"); + // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat struct ConsoleSharedMemory { u64_le sampling_number{}; bool is_seven_six_axis_sensor_at_rest{}; @@ -69,9 +76,7 @@ private: Common::Quaternion quaternion; }; - using MotionArray = - std::array, Settings::NativeMotion::NUM_MOTIONS_HID>; - MotionArray motions; + Core::HID::EmulatedConsole* console; u8* transfer_memory = nullptr; bool is_transfer_memory_set = false; ConsoleSharedMemory console_six_axis{}; -- cgit v1.2.3 From c87ad2d0d635d8786c48fed856e1bcf1ecc154bf Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:37:50 -0500 Subject: service/hid: Rewrite npad to use ring lifo and the emulated controller --- src/core/hle/service/hid/controllers/npad.cpp | 1100 +++++++++++-------------- src/core/hle/service/hid/controllers/npad.h | 395 +++------ 2 files changed, 605 insertions(+), 890 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 196876810..03cbd42f4 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -12,7 +12,6 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/frontend/input.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_writable_event.h" @@ -20,64 +19,13 @@ #include "core/hle/service/kernel_helpers.h" namespace Service::HID { -constexpr s32 HID_JOYSTICK_MAX = 0x7fff; -constexpr s32 HID_TRIGGER_MAX = 0x7fff; -[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; -constexpr u32 BATTERY_FULL = 2; constexpr u32 MAX_NPAD_ID = 7; constexpr std::size_t HANDHELD_INDEX = 8; constexpr std::array npad_id_list{ 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, }; -enum class JoystickId : std::size_t { - Joystick_Left, - Joystick_Right, -}; - -Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( - Settings::ControllerType type) { - switch (type) { - case Settings::ControllerType::ProController: - return NPadControllerType::ProController; - case Settings::ControllerType::DualJoyconDetached: - return NPadControllerType::JoyDual; - case Settings::ControllerType::LeftJoycon: - return NPadControllerType::JoyLeft; - case Settings::ControllerType::RightJoycon: - return NPadControllerType::JoyRight; - case Settings::ControllerType::Handheld: - return NPadControllerType::Handheld; - case Settings::ControllerType::GameCube: - return NPadControllerType::GameCube; - default: - UNREACHABLE(); - return NPadControllerType::ProController; - } -} - -Settings::ControllerType Controller_NPad::MapNPadToSettingsType( - Controller_NPad::NPadControllerType type) { - switch (type) { - case NPadControllerType::ProController: - return Settings::ControllerType::ProController; - case NPadControllerType::JoyDual: - return Settings::ControllerType::DualJoyconDetached; - case NPadControllerType::JoyLeft: - return Settings::ControllerType::LeftJoycon; - case NPadControllerType::JoyRight: - return Settings::ControllerType::RightJoycon; - case NPadControllerType::Handheld: - return Settings::ControllerType::Handheld; - case NPadControllerType::GameCube: - return Settings::ControllerType::GameCube; - default: - UNREACHABLE(); - return Settings::ControllerType::ProController; - } -} - std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { switch (npad_id) { case 0: @@ -143,118 +91,157 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) { bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { return IsNpadIdValid(device_handle.npad_id) && - device_handle.npad_type < NpadType::MaxNpadType && + device_handle.npad_type < Core::HID::NpadType::MaxNpadType && device_handle.device_index < DeviceIndex::MaxDeviceIndex; } Controller_NPad::Controller_NPad(Core::System& system_, KernelHelpers::ServiceContext& service_context_) : ControllerBase{system_}, service_context{service_context_} { - latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE}); + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i]; + controller.device = system.HIDCore().GetEmulatedControllerByIndex(i); + controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE; + controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE; + Core::HID::ControllerUpdateCallback engine_callback{ + [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }}; + controller.callback_key = controller.device->SetCallback(engine_callback); + } } Controller_NPad::~Controller_NPad() { + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i]; + controller.device->DeleteCallback(controller.callback_key); + } OnRelease(); } +void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, + std::size_t controller_idx) { + if (type == Core::HID::ControllerTriggerType::All) { + ControllerUpdate(Core::HID::ControllerTriggerType::Type, controller_idx); + ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); + return; + } + + switch (type) { + case Core::HID::ControllerTriggerType::Connected: + InitNewlyAddedController(controller_idx); + break; + case Core::HID::ControllerTriggerType::Disconnected: + DisconnectNpadAtIndex(controller_idx); + break; + case Core::HID::ControllerTriggerType::Type: { + auto& controller = controller_data[controller_idx]; + if (controller.device->IsConnected()) { + LOG_ERROR(Service_HID, "Controller type changed without turning off the controller"); + } + break; + } + default: + break; + } +} + void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { - const auto controller_type = connected_controllers[controller_idx].type; - auto& controller = shared_memory_entries[controller_idx]; - if (controller_type == NPadControllerType::None) { - styleset_changed_events[controller_idx]->GetWritableEvent().Signal(); + auto& controller = controller_data[controller_idx]; + const auto controller_type = controller.device->GetNpadType(); + auto& shared_memory = controller.shared_memory_entry; + if (controller_type == Core::HID::NpadType::None) { + controller.styleset_changed_event->GetWritableEvent().Signal(); return; } - controller.style_set.raw = 0; // Zero out - controller.device_type.raw = 0; - controller.system_properties.raw = 0; + shared_memory.style_set.raw = 0; // Zero out + shared_memory.device_type.raw = 0; + shared_memory.system_properties.raw = 0; switch (controller_type) { - case NPadControllerType::None: + case Core::HID::NpadType::None: UNREACHABLE(); break; - case NPadControllerType::ProController: - controller.style_set.fullkey.Assign(1); - controller.device_type.fullkey.Assign(1); - controller.system_properties.is_vertical.Assign(1); - controller.system_properties.use_plus.Assign(1); - controller.system_properties.use_minus.Assign(1); - controller.assignment_mode = NpadAssignments::Single; - controller.footer_type = AppletFooterUiType::SwitchProController; + case Core::HID::NpadType::ProController: + shared_memory.style_set.fullkey.Assign(1); + shared_memory.device_type.fullkey.Assign(1); + shared_memory.system_properties.is_vertical.Assign(1); + shared_memory.system_properties.use_plus.Assign(1); + shared_memory.system_properties.use_minus.Assign(1); + shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; + shared_memory.footer_type = AppletFooterUiType::SwitchProController; break; - case NPadControllerType::Handheld: - controller.style_set.handheld.Assign(1); - controller.device_type.handheld_left.Assign(1); - controller.device_type.handheld_right.Assign(1); - controller.system_properties.is_vertical.Assign(1); - controller.system_properties.use_plus.Assign(1); - controller.system_properties.use_minus.Assign(1); - controller.assignment_mode = NpadAssignments::Dual; - controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; + case Core::HID::NpadType::Handheld: + shared_memory.style_set.handheld.Assign(1); + shared_memory.device_type.handheld_left.Assign(1); + shared_memory.device_type.handheld_right.Assign(1); + shared_memory.system_properties.is_vertical.Assign(1); + shared_memory.system_properties.use_plus.Assign(1); + shared_memory.system_properties.use_minus.Assign(1); + shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; + shared_memory.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; break; - case NPadControllerType::JoyDual: - controller.style_set.joycon_dual.Assign(1); - controller.device_type.joycon_left.Assign(1); - controller.device_type.joycon_right.Assign(1); - controller.system_properties.is_vertical.Assign(1); - controller.system_properties.use_plus.Assign(1); - controller.system_properties.use_minus.Assign(1); - controller.assignment_mode = NpadAssignments::Dual; - controller.footer_type = AppletFooterUiType::JoyDual; + case Core::HID::NpadType::JoyconDual: + shared_memory.style_set.joycon_dual.Assign(1); + shared_memory.device_type.joycon_left.Assign(1); + shared_memory.device_type.joycon_right.Assign(1); + shared_memory.system_properties.is_vertical.Assign(1); + shared_memory.system_properties.use_plus.Assign(1); + shared_memory.system_properties.use_minus.Assign(1); + shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; + shared_memory.footer_type = AppletFooterUiType::JoyDual; break; - case NPadControllerType::JoyLeft: - controller.style_set.joycon_left.Assign(1); - controller.device_type.joycon_left.Assign(1); - controller.system_properties.is_horizontal.Assign(1); - controller.system_properties.use_minus.Assign(1); - controller.assignment_mode = NpadAssignments::Single; - controller.footer_type = AppletFooterUiType::JoyLeftHorizontal; + case Core::HID::NpadType::JoyconLeft: + shared_memory.style_set.joycon_left.Assign(1); + shared_memory.device_type.joycon_left.Assign(1); + shared_memory.system_properties.is_horizontal.Assign(1); + shared_memory.system_properties.use_minus.Assign(1); + shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; + shared_memory.footer_type = AppletFooterUiType::JoyLeftHorizontal; break; - case NPadControllerType::JoyRight: - controller.style_set.joycon_right.Assign(1); - controller.device_type.joycon_right.Assign(1); - controller.system_properties.is_horizontal.Assign(1); - controller.system_properties.use_plus.Assign(1); - controller.assignment_mode = NpadAssignments::Single; - controller.footer_type = AppletFooterUiType::JoyRightHorizontal; + case Core::HID::NpadType::JoyconRight: + shared_memory.style_set.joycon_right.Assign(1); + shared_memory.device_type.joycon_right.Assign(1); + shared_memory.system_properties.is_horizontal.Assign(1); + shared_memory.system_properties.use_plus.Assign(1); + shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; + shared_memory.footer_type = AppletFooterUiType::JoyRightHorizontal; break; - case NPadControllerType::GameCube: - controller.style_set.gamecube.Assign(1); + case Core::HID::NpadType::GameCube: + shared_memory.style_set.gamecube.Assign(1); // The GC Controller behaves like a wired Pro Controller - controller.device_type.fullkey.Assign(1); - controller.system_properties.is_vertical.Assign(1); - controller.system_properties.use_plus.Assign(1); + shared_memory.device_type.fullkey.Assign(1); + shared_memory.system_properties.is_vertical.Assign(1); + shared_memory.system_properties.use_plus.Assign(1); break; - case NPadControllerType::Pokeball: - controller.style_set.palma.Assign(1); - controller.device_type.palma.Assign(1); - controller.assignment_mode = NpadAssignments::Single; + case Core::HID::NpadType::Pokeball: + shared_memory.style_set.palma.Assign(1); + shared_memory.device_type.palma.Assign(1); + shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; + break; + default: break; } - controller.fullkey_color.attribute = ColorAttributes::Ok; - controller.fullkey_color.fullkey.body = 0; - controller.fullkey_color.fullkey.button = 0; + const auto& body_colors = controller.device->GetColors(); - controller.joycon_color.attribute = ColorAttributes::Ok; - controller.joycon_color.left.body = - Settings::values.players.GetValue()[controller_idx].body_color_left; - controller.joycon_color.left.button = - Settings::values.players.GetValue()[controller_idx].button_color_left; - controller.joycon_color.right.body = - Settings::values.players.GetValue()[controller_idx].body_color_right; - controller.joycon_color.right.button = - Settings::values.players.GetValue()[controller_idx].button_color_right; + shared_memory.fullkey_color.attribute = ColorAttribute::Ok; + shared_memory.fullkey_color.fullkey = body_colors.fullkey; + + shared_memory.joycon_color.attribute = ColorAttribute::Ok; + shared_memory.joycon_color.left = body_colors.left; + shared_memory.joycon_color.right = body_colors.right; // TODO: Investigate when we should report all batery types - controller.battery_level_dual = BATTERY_FULL; - controller.battery_level_left = BATTERY_FULL; - controller.battery_level_right = BATTERY_FULL; + const auto& battery_level = controller.device->GetBattery(); + shared_memory.battery_level_dual = battery_level.dual.battery_level; + shared_memory.battery_level_left = battery_level.left.battery_level; + shared_memory.battery_level_right = battery_level.right.battery_level; SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); } void Controller_NPad::OnInit() { - for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { - styleset_changed_events[i] = + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i]; + controller.styleset_changed_event = service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); } @@ -262,10 +249,9 @@ void Controller_NPad::OnInit() { return; } - OnLoadInputDevices(); - - if (style.raw == 0) { + if (system.HIDCore().GetSupportedStyleTag().raw == 0) { // We want to support all controllers + Core::HID::NpadStyleTag style{}; style.handheld.Assign(1); style.joycon_left.Assign(1); style.joycon_right.Assign(1); @@ -273,173 +259,98 @@ void Controller_NPad::OnInit() { style.fullkey.Assign(1); style.gamecube.Assign(1); style.palma.Assign(1); - } - - std::transform(Settings::values.players.GetValue().begin(), - Settings::values.players.GetValue().end(), connected_controllers.begin(), - [](const Settings::PlayerInput& player) { - return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), - player.connected}; - }); - - // Connect the Player 1 or Handheld controller if none are connected. - if (std::none_of(connected_controllers.begin(), connected_controllers.end(), - [](const ControllerHolder& controller) { return controller.is_connected; })) { - const auto controller = - MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type); - if (controller == NPadControllerType::Handheld) { - Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; - connected_controllers[HANDHELD_INDEX] = {controller, true}; - } else { - Settings::values.players.GetValue()[0].connected = true; - connected_controllers[0] = {controller, true}; - } - } - - // Account for handheld - if (connected_controllers[HANDHELD_INDEX].is_connected) { - connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; + system.HIDCore().SetSupportedStyleTag(style); } supported_npad_id_types.resize(npad_id_list.size()); std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - for (std::size_t i = 0; i < connected_controllers.size(); ++i) { - const auto& controller = connected_controllers[i]; - if (controller.is_connected) { - AddNewControllerAt(controller.type, i); + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i].device; + if (controller->IsConnected()) { + AddNewControllerAt(controller->GetNpadType(), i); } } -} -void Controller_NPad::OnLoadInputDevices() { - const auto& players = Settings::values.players.GetValue(); - - std::lock_guard lock{mutex}; - for (std::size_t i = 0; i < players.size(); ++i) { - std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, - buttons[i].begin(), Input::CreateDevice); - std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, - sticks[i].begin(), Input::CreateDevice); - std::transform(players[i].vibrations.begin() + - Settings::NativeVibration::VIBRATION_HID_BEGIN, - players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END, - vibrations[i].begin(), Input::CreateDevice); - std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, - players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, - motions[i].begin(), Input::CreateDevice); - for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) { - InitializeVibrationDeviceAtIndex(i, device_idx); + // Prefill controller buffers + for (auto& controller : controller_data) { + NPadGenericState dummy_pad_state{}; + auto& npad = controller.shared_memory_entry; + for (std::size_t i = 0; i < 17; ++i) { + dummy_pad_state.sampling_number = + npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; + npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); + npad.handheld_lifo.WriteNextEntry(dummy_pad_state); + npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); + npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); + npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); + npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); + npad.palma_lifo.WriteNextEntry(dummy_pad_state); } } } void Controller_NPad::OnRelease() { - for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { - for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { - VibrateControllerAtIndex(npad_idx, device_idx, {}); + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i]; + service_context.CloseEvent(controller.styleset_changed_event); + for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { + VibrateControllerAtIndex(i, device_idx, {}); } } - - for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { - service_context.CloseEvent(styleset_changed_events[i]); - } } void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { std::lock_guard lock{mutex}; - const auto controller_idx = NPadIdToIndex(npad_id); - const auto controller_type = connected_controllers[controller_idx].type; - if (!connected_controllers[controller_idx].is_connected) { + auto& controller = controller_data[controller_idx]; + const auto controller_type = controller.device->GetNpadType(); + if (!controller.device->IsConnected()) { return; } - auto& pad_state = npad_pad_states[controller_idx].pad_states; - auto& lstick_entry = npad_pad_states[controller_idx].l_stick; - auto& rstick_entry = npad_pad_states[controller_idx].r_stick; - auto& trigger_entry = npad_trigger_states[controller_idx]; - const auto& button_state = buttons[controller_idx]; - const auto& analog_state = sticks[controller_idx]; - const auto [stick_l_x_f, stick_l_y_f] = - analog_state[static_cast(JoystickId::Joystick_Left)]->GetStatus(); - const auto [stick_r_x_f, stick_r_y_f] = - analog_state[static_cast(JoystickId::Joystick_Right)]->GetStatus(); - - using namespace Settings::NativeButton; - if (controller_type != NPadControllerType::JoyLeft) { - pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.r_stick_right.Assign( - analog_state[static_cast(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); - pad_state.r_stick_left.Assign( - analog_state[static_cast(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); - pad_state.r_stick_up.Assign( - analog_state[static_cast(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); - pad_state.r_stick_down.Assign( - analog_state[static_cast(JoystickId::Joystick_Right)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); - rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); - rstick_entry.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); + + auto& pad_entry = controller.npad_pad_state; + auto& trigger_entry = controller.npad_trigger_state; + const auto button_state = controller.device->GetNpadButtons(); + const auto stick_state = controller.device->GetSticks(); + + using btn = Core::HID::NpadButton; + pad_entry.npad_buttons.raw = btn::None; + if (controller_type != Core::HID::NpadType::JoyconLeft) { + constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | + btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | + btn::StickRRight | btn::StickRDown; + pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask; + pad_entry.r_stick = stick_state.right; } - if (controller_type != NPadControllerType::JoyRight) { - pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.l_stick_right.Assign( - analog_state[static_cast(JoystickId::Joystick_Left)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); - pad_state.l_stick_left.Assign( - analog_state[static_cast(JoystickId::Joystick_Left)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); - pad_state.l_stick_up.Assign( - analog_state[static_cast(JoystickId::Joystick_Left)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); - pad_state.l_stick_down.Assign( - analog_state[static_cast(JoystickId::Joystick_Left)] - ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); - lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); - lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); + if (controller_type != Core::HID::NpadType::JoyconRight) { + constexpr btn left_button_mask = + btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | + btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; + pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask; + pad_entry.l_stick = stick_state.left; } - if (controller_type == NPadControllerType::JoyLeft) { - pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); + if (controller_type == Core::HID::NpadType::JoyconLeft) { + pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); + pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); } - if (controller_type == NPadControllerType::JoyRight) { - pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); + if (controller_type == Core::HID::NpadType::JoyconRight) { + pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); + pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); } - if (controller_type == NPadControllerType::GameCube) { - trigger_entry.l_analog = static_cast( - button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); - trigger_entry.r_analog = static_cast( - button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); - pad_state.zl.Assign(false); - pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); + if (controller_type == Core::HID::NpadType::GameCube) { + const auto& trigger_state = controller.device->GetTriggers(); + trigger_entry.l_analog = trigger_state.left; + trigger_entry.r_analog = trigger_state.right; + pad_entry.npad_buttons.zl.Assign(false); + pad_entry.npad_buttons.zr.Assign(button_state.r); + pad_entry.npad_buttons.l.Assign(button_state.zl); + pad_entry.npad_buttons.r.Assign(button_state.zr); } } @@ -448,173 +359,124 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { return; } - for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { - auto& npad = shared_memory_entries[i]; - const std::array controller_npads{ - &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states, - &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states, - &npad.system_ext_states}; - - // There is the posibility to have more controllers with analog triggers - const std::array controller_triggers{ - &npad.gc_trigger_states, - }; - - for (auto* main_controller : controller_npads) { - main_controller->common.entry_count = 16; - main_controller->common.total_entry_count = 17; - - const auto& last_entry = - main_controller->npad[main_controller->common.last_entry_index]; - - main_controller->common.timestamp = core_timing.GetCPUTicks(); - main_controller->common.last_entry_index = - (main_controller->common.last_entry_index + 1) % 17; - - auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index]; - - cur_entry.timestamp = last_entry.timestamp + 1; - cur_entry.timestamp2 = cur_entry.timestamp; - } + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i]; + auto& npad = controller.shared_memory_entry; - for (auto* analog_trigger : controller_triggers) { - analog_trigger->entry_count = 16; - analog_trigger->total_entry_count = 17; + const auto& controller_type = controller.device->GetNpadType(); - const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index]; - - analog_trigger->timestamp = core_timing.GetCPUTicks(); - analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17; - - auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index]; - - cur_entry.timestamp = last_entry.timestamp + 1; - cur_entry.timestamp2 = cur_entry.timestamp; - } - - const auto& controller_type = connected_controllers[i].type; - - if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { + if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { continue; } const u32 npad_index = static_cast(i); RequestPadStateUpdate(npad_index); - auto& pad_state = npad_pad_states[npad_index]; - auto& trigger_state = npad_trigger_states[npad_index]; - - auto& main_controller = - npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index]; - auto& handheld_entry = - npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; - auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index]; - auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index]; - auto& right_entry = - npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index]; - auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index]; - auto& libnx_entry = - npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index]; - auto& trigger_entry = - npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index]; - - libnx_entry.connection_status.raw = 0; - libnx_entry.connection_status.is_connected.Assign(1); + auto& pad_state = controller.npad_pad_state; + auto& libnx_state = controller.npad_libnx_state; + auto& trigger_state = controller.npad_trigger_state; + // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate + // any controllers. + libnx_state.connection_status.raw = 0; + libnx_state.connection_status.is_connected.Assign(1); switch (controller_type) { - case NPadControllerType::None: + case Core::HID::NpadType::None: UNREACHABLE(); break; - case NPadControllerType::ProController: - main_controller.connection_status.raw = 0; - main_controller.connection_status.is_connected.Assign(1); - main_controller.connection_status.is_wired.Assign(1); - main_controller.pad.pad_states.raw = pad_state.pad_states.raw; - main_controller.pad.l_stick = pad_state.l_stick; - main_controller.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.is_wired.Assign(1); + case Core::HID::NpadType::ProController: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.connection_status.is_wired.Assign(1); + + libnx_state.connection_status.is_wired.Assign(1); + pad_state.sampling_number = + npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.fullkey_lifo.WriteNextEntry(pad_state); break; - case NPadControllerType::Handheld: - handheld_entry.connection_status.raw = 0; - handheld_entry.connection_status.is_connected.Assign(1); - handheld_entry.connection_status.is_wired.Assign(1); - handheld_entry.connection_status.is_left_connected.Assign(1); - handheld_entry.connection_status.is_right_connected.Assign(1); - handheld_entry.connection_status.is_left_wired.Assign(1); - handheld_entry.connection_status.is_right_wired.Assign(1); - handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; - handheld_entry.pad.l_stick = pad_state.l_stick; - handheld_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.is_wired.Assign(1); - libnx_entry.connection_status.is_left_connected.Assign(1); - libnx_entry.connection_status.is_right_connected.Assign(1); - libnx_entry.connection_status.is_left_wired.Assign(1); - libnx_entry.connection_status.is_right_wired.Assign(1); + case Core::HID::NpadType::Handheld: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.connection_status.is_wired.Assign(1); + pad_state.connection_status.is_left_connected.Assign(1); + pad_state.connection_status.is_right_connected.Assign(1); + pad_state.connection_status.is_left_wired.Assign(1); + pad_state.connection_status.is_right_wired.Assign(1); + + libnx_state.connection_status.is_wired.Assign(1); + libnx_state.connection_status.is_left_connected.Assign(1); + libnx_state.connection_status.is_right_connected.Assign(1); + libnx_state.connection_status.is_left_wired.Assign(1); + libnx_state.connection_status.is_right_wired.Assign(1); + pad_state.sampling_number = + npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.handheld_lifo.WriteNextEntry(pad_state); break; - case NPadControllerType::JoyDual: - dual_entry.connection_status.raw = 0; - dual_entry.connection_status.is_connected.Assign(1); - dual_entry.connection_status.is_left_connected.Assign(1); - dual_entry.connection_status.is_right_connected.Assign(1); - dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; - dual_entry.pad.l_stick = pad_state.l_stick; - dual_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.is_left_connected.Assign(1); - libnx_entry.connection_status.is_right_connected.Assign(1); + case Core::HID::NpadType::JoyconDual: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.connection_status.is_left_connected.Assign(1); + pad_state.connection_status.is_right_connected.Assign(1); + + libnx_state.connection_status.is_left_connected.Assign(1); + libnx_state.connection_status.is_right_connected.Assign(1); + pad_state.sampling_number = + npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.joy_dual_lifo.WriteNextEntry(pad_state); break; - case NPadControllerType::JoyLeft: - left_entry.connection_status.raw = 0; - left_entry.connection_status.is_connected.Assign(1); - left_entry.connection_status.is_left_connected.Assign(1); - left_entry.pad.pad_states.raw = pad_state.pad_states.raw; - left_entry.pad.l_stick = pad_state.l_stick; - left_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.is_left_connected.Assign(1); + case Core::HID::NpadType::JoyconLeft: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.connection_status.is_left_connected.Assign(1); + + libnx_state.connection_status.is_left_connected.Assign(1); + pad_state.sampling_number = + npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.joy_left_lifo.WriteNextEntry(pad_state); break; - case NPadControllerType::JoyRight: - right_entry.connection_status.raw = 0; - right_entry.connection_status.is_connected.Assign(1); - right_entry.connection_status.is_right_connected.Assign(1); - right_entry.pad.pad_states.raw = pad_state.pad_states.raw; - right_entry.pad.l_stick = pad_state.l_stick; - right_entry.pad.r_stick = pad_state.r_stick; - - libnx_entry.connection_status.is_right_connected.Assign(1); + case Core::HID::NpadType::JoyconRight: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.connection_status.is_right_connected.Assign(1); + + libnx_state.connection_status.is_right_connected.Assign(1); + pad_state.sampling_number = + npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.joy_right_lifo.WriteNextEntry(pad_state); break; - case NPadControllerType::GameCube: - main_controller.connection_status.raw = 0; - main_controller.connection_status.is_connected.Assign(1); - main_controller.connection_status.is_wired.Assign(1); - main_controller.pad.pad_states.raw = pad_state.pad_states.raw; - main_controller.pad.l_stick = pad_state.l_stick; - main_controller.pad.r_stick = pad_state.r_stick; - trigger_entry.l_analog = trigger_state.l_analog; - trigger_entry.r_analog = trigger_state.r_analog; - - libnx_entry.connection_status.is_wired.Assign(1); + case Core::HID::NpadType::GameCube: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.connection_status.is_wired.Assign(1); + + libnx_state.connection_status.is_wired.Assign(1); + pad_state.sampling_number = + npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + trigger_state.sampling_number = + npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.fullkey_lifo.WriteNextEntry(pad_state); + npad.gc_trigger_lifo.WriteNextEntry(trigger_state); break; - case NPadControllerType::Pokeball: - pokeball_entry.connection_status.raw = 0; - pokeball_entry.connection_status.is_connected.Assign(1); - pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; - pokeball_entry.pad.l_stick = pad_state.l_stick; - pokeball_entry.pad.r_stick = pad_state.r_stick; + case Core::HID::NpadType::Pokeball: + pad_state.connection_status.raw = 0; + pad_state.connection_status.is_connected.Assign(1); + pad_state.sampling_number = + npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.palma_lifo.WriteNextEntry(pad_state); + break; + default: break; } - // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate - // any controllers. - libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; - libnx_entry.pad.l_stick = pad_state.l_stick; - libnx_entry.pad.r_stick = pad_state.r_stick; + libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; + libnx_state.l_stick = pad_state.l_stick; + libnx_state.r_stick = pad_state.r_stick; + npad.system_ext_lifo.WriteNextEntry(pad_state); + + press_state |= static_cast(pad_state.npad_buttons.raw); - press_state |= static_cast(pad_state.pad_states.raw); + std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), + &controller.shared_memory_entry, sizeof(NpadInternalState)); } - std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), - shared_memory_entries.size() * sizeof(NPadEntry)); } void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, @@ -622,145 +484,130 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing if (!IsControllerActivated()) { return; } - for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { - auto& npad = shared_memory_entries[i]; - const auto& controller_type = connected_controllers[i].type; - - if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { - continue; - } + for (std::size_t i = 0; i < controller_data.size(); ++i) { + auto& controller = controller_data[i]; - const std::array controller_sixaxes{ - &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, - &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right, - }; + const auto& controller_type = controller.device->GetNpadType(); - for (auto* sixaxis_sensor : controller_sixaxes) { - sixaxis_sensor->common.entry_count = 16; - sixaxis_sensor->common.total_entry_count = 17; - - const auto& last_entry = - sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index]; - - sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks(); - sixaxis_sensor->common.last_entry_index = - (sixaxis_sensor->common.last_entry_index + 1) % 17; - - auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index]; - - cur_entry.timestamp = last_entry.timestamp + 1; - cur_entry.timestamp2 = cur_entry.timestamp; + if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { + continue; } - // Try to read sixaxis sensor states - std::array motion_devices; + auto& npad = controller.shared_memory_entry; + const auto& motion_state = controller.device->GetMotions(); + auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; + auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; + auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state; + auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state; + auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; + auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { sixaxis_at_rest = true; - for (std::size_t e = 0; e < motion_devices.size(); ++e) { - const auto& device = motions[i][e]; - if (device) { - std::tie(motion_devices[e].accel, motion_devices[e].gyro, - motion_devices[e].rotation, motion_devices[e].orientation, - motion_devices[e].quaternion) = device->GetStatus(); - sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f; - } + for (std::size_t e = 0; e < motion_state.size(); ++e) { + sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest; } } - auto& full_sixaxis_entry = - npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index]; - auto& handheld_sixaxis_entry = - npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index]; - auto& dual_left_sixaxis_entry = - npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index]; - auto& dual_right_sixaxis_entry = - npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index]; - auto& left_sixaxis_entry = - npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index]; - auto& right_sixaxis_entry = - npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index]; - switch (controller_type) { - case NPadControllerType::None: + case Core::HID::NpadType::None: UNREACHABLE(); break; - case NPadControllerType::ProController: - full_sixaxis_entry.attribute.raw = 0; - if (sixaxis_sensors_enabled && motions[i][0]) { - full_sixaxis_entry.attribute.is_connected.Assign(1); - full_sixaxis_entry.accel = motion_devices[0].accel; - full_sixaxis_entry.gyro = motion_devices[0].gyro; - full_sixaxis_entry.rotation = motion_devices[0].rotation; - full_sixaxis_entry.orientation = motion_devices[0].orientation; + case Core::HID::NpadType::ProController: + sixaxis_fullkey_state.attribute.raw = 0; + if (sixaxis_sensors_enabled) { + sixaxis_fullkey_state.attribute.is_connected.Assign(1); + sixaxis_fullkey_state.accel = motion_state[0].accel; + sixaxis_fullkey_state.gyro = motion_state[0].gyro; + sixaxis_fullkey_state.rotation = motion_state[0].rotation; + sixaxis_fullkey_state.orientation = motion_state[0].orientation; } break; - case NPadControllerType::Handheld: - handheld_sixaxis_entry.attribute.raw = 0; - if (sixaxis_sensors_enabled && motions[i][0]) { - handheld_sixaxis_entry.attribute.is_connected.Assign(1); - handheld_sixaxis_entry.accel = motion_devices[0].accel; - handheld_sixaxis_entry.gyro = motion_devices[0].gyro; - handheld_sixaxis_entry.rotation = motion_devices[0].rotation; - handheld_sixaxis_entry.orientation = motion_devices[0].orientation; + case Core::HID::NpadType::Handheld: + sixaxis_handheld_state.attribute.raw = 0; + if (sixaxis_sensors_enabled) { + sixaxis_handheld_state.attribute.is_connected.Assign(1); + sixaxis_handheld_state.accel = motion_state[0].accel; + sixaxis_handheld_state.gyro = motion_state[0].gyro; + sixaxis_handheld_state.rotation = motion_state[0].rotation; + sixaxis_handheld_state.orientation = motion_state[0].orientation; } break; - case NPadControllerType::JoyDual: - dual_left_sixaxis_entry.attribute.raw = 0; - dual_right_sixaxis_entry.attribute.raw = 0; - if (sixaxis_sensors_enabled && motions[i][0]) { + case Core::HID::NpadType::JoyconDual: + sixaxis_dual_left_state.attribute.raw = 0; + sixaxis_dual_right_state.attribute.raw = 0; + if (sixaxis_sensors_enabled) { // Set motion for the left joycon - dual_left_sixaxis_entry.attribute.is_connected.Assign(1); - dual_left_sixaxis_entry.accel = motion_devices[0].accel; - dual_left_sixaxis_entry.gyro = motion_devices[0].gyro; - dual_left_sixaxis_entry.rotation = motion_devices[0].rotation; - dual_left_sixaxis_entry.orientation = motion_devices[0].orientation; + sixaxis_dual_left_state.attribute.is_connected.Assign(1); + sixaxis_dual_left_state.accel = motion_state[0].accel; + sixaxis_dual_left_state.gyro = motion_state[0].gyro; + sixaxis_dual_left_state.rotation = motion_state[0].rotation; + sixaxis_dual_left_state.orientation = motion_state[0].orientation; } - if (sixaxis_sensors_enabled && motions[i][1]) { + if (sixaxis_sensors_enabled) { // Set motion for the right joycon - dual_right_sixaxis_entry.attribute.is_connected.Assign(1); - dual_right_sixaxis_entry.accel = motion_devices[1].accel; - dual_right_sixaxis_entry.gyro = motion_devices[1].gyro; - dual_right_sixaxis_entry.rotation = motion_devices[1].rotation; - dual_right_sixaxis_entry.orientation = motion_devices[1].orientation; + sixaxis_dual_right_state.attribute.is_connected.Assign(1); + sixaxis_dual_right_state.accel = motion_state[1].accel; + sixaxis_dual_right_state.gyro = motion_state[1].gyro; + sixaxis_dual_right_state.rotation = motion_state[1].rotation; + sixaxis_dual_right_state.orientation = motion_state[1].orientation; } break; - case NPadControllerType::JoyLeft: - left_sixaxis_entry.attribute.raw = 0; - if (sixaxis_sensors_enabled && motions[i][0]) { - left_sixaxis_entry.attribute.is_connected.Assign(1); - left_sixaxis_entry.accel = motion_devices[0].accel; - left_sixaxis_entry.gyro = motion_devices[0].gyro; - left_sixaxis_entry.rotation = motion_devices[0].rotation; - left_sixaxis_entry.orientation = motion_devices[0].orientation; + case Core::HID::NpadType::JoyconLeft: + sixaxis_left_lifo_state.attribute.raw = 0; + if (sixaxis_sensors_enabled) { + sixaxis_left_lifo_state.attribute.is_connected.Assign(1); + sixaxis_left_lifo_state.accel = motion_state[0].accel; + sixaxis_left_lifo_state.gyro = motion_state[0].gyro; + sixaxis_left_lifo_state.rotation = motion_state[0].rotation; + sixaxis_left_lifo_state.orientation = motion_state[0].orientation; } break; - case NPadControllerType::JoyRight: - right_sixaxis_entry.attribute.raw = 0; - if (sixaxis_sensors_enabled && motions[i][1]) { - right_sixaxis_entry.attribute.is_connected.Assign(1); - right_sixaxis_entry.accel = motion_devices[1].accel; - right_sixaxis_entry.gyro = motion_devices[1].gyro; - right_sixaxis_entry.rotation = motion_devices[1].rotation; - right_sixaxis_entry.orientation = motion_devices[1].orientation; + case Core::HID::NpadType::JoyconRight: + sixaxis_right_lifo_state.attribute.raw = 0; + if (sixaxis_sensors_enabled) { + sixaxis_right_lifo_state.attribute.is_connected.Assign(1); + sixaxis_right_lifo_state.accel = motion_state[1].accel; + sixaxis_right_lifo_state.gyro = motion_state[1].gyro; + sixaxis_right_lifo_state.rotation = motion_state[1].rotation; + sixaxis_right_lifo_state.orientation = motion_state[1].orientation; } break; - case NPadControllerType::GameCube: - case NPadControllerType::Pokeball: + default: break; } + + sixaxis_fullkey_state.sampling_number = + npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_handheld_state.sampling_number = + npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_dual_left_state.sampling_number = + npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_dual_right_state.sampling_number = + npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_left_lifo_state.sampling_number = + npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_right_lifo_state.sampling_number = + npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + + npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); + npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); + npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); + npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); + npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); + npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); + std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), + &controller.shared_memory_entry, sizeof(NpadInternalState)); } - std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), - shared_memory_entries.size() * sizeof(NPadEntry)); } -void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { - style.raw = style_set.raw; +void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) { + system.HIDCore().SetSupportedStyleTag(style_set); } -Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { - return style; +Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { + return system.HIDCore().GetSupportedStyleTag(); } void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { @@ -779,11 +626,11 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { return supported_npad_id_types.size(); } -void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { +void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { hold_type = joy_hold_type; } -Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { +Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const { return hold_type; } @@ -803,29 +650,31 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode return communication_mode; } -void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { +void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) { const std::size_t npad_index = NPadIdToIndex(npad_id); - ASSERT(npad_index < shared_memory_entries.size()); - if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) { - shared_memory_entries[npad_index].assignment_mode = assignment_mode; + ASSERT(npad_index < controller_data.size()); + auto& controller = controller_data[npad_index]; + if (controller.shared_memory_entry.assignment_mode != assignment_mode) { + controller.shared_memory_entry.assignment_mode = assignment_mode; } } bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, const VibrationValue& vibration_value) { - if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { + auto& controller = controller_data[npad_index]; + + if (!controller.device->IsConnected()) { return false; } - const auto& player = Settings::values.players.GetValue()[npad_index]; - - if (!player.vibration_enabled) { - if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || - latest_vibration_values[npad_index][device_index].amp_high != 0.0f) { + if (!controller.device->IsVibrationEnabled()) { + if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f || + controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) { // Send an empty vibration to stop any vibrations. - vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); + Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; + controller.device->SetVibration(device_index, vibration); // Then reset the vibration value to its default value. - latest_vibration_values[npad_index][device_index] = DEFAULT_VIBRATION_VALUE; + controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE; } return false; @@ -840,22 +689,18 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size // Filter out non-zero vibrations that are within 10ms of each other. if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && - duration_cast(now - last_vibration_timepoints[npad_index][device_index]) < + duration_cast( + now - controller.vibration[device_index].last_vibration_timepoint) < milliseconds(10)) { return false; } - last_vibration_timepoints[npad_index][device_index] = now; + controller.vibration[device_index].last_vibration_timepoint = now; } - auto& vibration = vibrations[npad_index][device_index]; - const auto player_vibration_strength = static_cast(player.vibration_strength); - const auto amp_low = - std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); - const auto amp_high = - std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f); - return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high, - vibration_value.freq_high); + Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low, + vibration_value.amp_high, vibration_value.freq_high}; + return controller.device->SetVibration(device_index, vibration); } void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, @@ -869,10 +714,10 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han } const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + auto& controller = controller_data[npad_index]; const auto device_index = static_cast(vibration_device_handle.device_index); - if (!vibration_devices_mounted[npad_index][device_index] || - !connected_controllers[npad_index].is_connected) { + if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { return; } @@ -882,23 +727,25 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han } // Some games try to send mismatched parameters in the device handle, block these. - if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && - (vibration_device_handle.npad_type == NpadType::JoyconRight || + if ((controller.device->GetNpadType() == Core::HID::NpadType::JoyconLeft && + (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconRight || vibration_device_handle.device_index == DeviceIndex::Right)) || - (connected_controllers[npad_index].type == NPadControllerType::JoyRight && - (vibration_device_handle.npad_type == NpadType::JoyconLeft || + (controller.device->GetNpadType() == Core::HID::NpadType::JoyconRight && + (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconLeft || vibration_device_handle.device_index == DeviceIndex::Left))) { return; } // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && - vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { + if (vibration_value.amp_low == + controller.vibration[device_index].latest_vibration_value.amp_low && + vibration_value.amp_high == + controller.vibration[device_index].latest_vibration_value.amp_high) { return; } if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { - latest_vibration_values[npad_index][device_index] = vibration_value; + controller.vibration[device_index].latest_vibration_value = vibration_value; } } @@ -925,8 +772,9 @@ Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( } const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto& controller = controller_data[npad_index]; const auto device_index = static_cast(vibration_device_handle.device_index); - return latest_vibration_values[npad_index][device_index]; + return controller.vibration[device_index].latest_vibration_value; } void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { @@ -941,17 +789,14 @@ void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_de void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index) { + auto& controller = controller_data[npad_index]; if (!Settings::values.vibration_enabled.GetValue()) { - vibration_devices_mounted[npad_index][device_index] = false; + controller.vibration[device_index].device_mounted = false; return; } - if (vibrations[npad_index][device_index]) { - vibration_devices_mounted[npad_index][device_index] = - vibrations[npad_index][device_index]->GetStatus() == 1; - } else { - vibration_devices_mounted[npad_index][device_index] = false; - } + controller.vibration[device_index].device_mounted = + controller.device->TestVibration(device_index) == 1; } void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { @@ -964,42 +809,35 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev } const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto& controller = controller_data[npad_index]; const auto device_index = static_cast(vibration_device_handle.device_index); - return vibration_devices_mounted[npad_index][device_index]; + return controller.vibration[device_index].device_mounted; } Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { - return styleset_changed_events[NPadIdToIndex(npad_id)]->GetReadableEvent(); + const auto& controller = controller_data[NPadIdToIndex(npad_id)]; + return controller.styleset_changed_event->GetReadableEvent(); } void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { - styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent().Signal(); + const auto& controller = controller_data[NPadIdToIndex(npad_id)]; + controller.styleset_changed_event->GetWritableEvent().Signal(); } -void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { +void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index) { UpdateControllerAt(controller, npad_index, true); } -void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, +void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index, bool connected) { + auto& controller = controller_data[npad_index].device; if (!connected) { DisconnectNpadAtIndex(npad_index); return; } - if (controller == NPadControllerType::Handheld && npad_index == HANDHELD_INDEX) { - Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = - MapNPadToSettingsType(controller); - Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; - connected_controllers[HANDHELD_INDEX] = {controller, true}; - InitNewlyAddedController(HANDHELD_INDEX); - return; - } - - Settings::values.players.GetValue()[npad_index].controller_type = - MapNPadToSettingsType(controller); - Settings::values.players.GetValue()[npad_index].connected = true; - connected_controllers[npad_index] = {controller, true}; + controller->SetNpadType(type); + controller->Connect(); InitNewlyAddedController(npad_index); } @@ -1008,27 +846,27 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { } void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { - for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { + auto& controller = controller_data[npad_index]; + for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { // Send an empty vibration to stop any vibrations. VibrateControllerAtIndex(npad_index, device_idx, {}); - vibration_devices_mounted[npad_index][device_idx] = false; + controller.vibration[device_idx].device_mounted = false; } - Settings::values.players.GetValue()[npad_index].connected = false; - connected_controllers[npad_index].is_connected = false; - - auto& controller = shared_memory_entries[npad_index]; - controller.style_set.raw = 0; // Zero out - controller.device_type.raw = 0; - controller.system_properties.raw = 0; - controller.button_properties.raw = 0; - controller.battery_level_dual = 0; - controller.battery_level_left = 0; - controller.battery_level_right = 0; - controller.fullkey_color = {}; - controller.joycon_color = {}; - controller.assignment_mode = NpadAssignments::Dual; - controller.footer_type = AppletFooterUiType::None; + controller.device->Disconnect(); + + auto& shared_memory_entry = controller.shared_memory_entry; + shared_memory_entry.style_set.raw = 0; // Zero out + shared_memory_entry.device_type.raw = 0; + shared_memory_entry.system_properties.raw = 0; + shared_memory_entry.button_properties.raw = 0; + shared_memory_entry.battery_level_dual = 0; + shared_memory_entry.battery_level_left = 0; + shared_memory_entry.battery_level_right = 0; + shared_memory_entry.fullkey_color = {}; + shared_memory_entry.joycon_color = {}; + shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; + shared_memory_entry.footer_type = AppletFooterUiType::None; SignalStyleSetChangedEvent(IndexToNPad(npad_index)); } @@ -1069,16 +907,18 @@ void Controller_NPad::ResetSixAxisFusionParameters() { void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { const auto npad_index_1 = NPadIdToIndex(npad_id_1); const auto npad_index_2 = NPadIdToIndex(npad_id_2); + const auto& controller_1 = controller_data[npad_index_1].device; + const auto& controller_2 = controller_data[npad_index_2].device; // If the controllers at both npad indices form a pair of left and right joycons, merge them. // Otherwise, do nothing. - if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft && - connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) || - (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && - connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { + if ((controller_1->GetNpadType() == Core::HID::NpadType::JoyconLeft && + controller_2->GetNpadType() == Core::HID::NpadType::JoyconRight) || + (controller_2->GetNpadType() == Core::HID::NpadType::JoyconLeft && + controller_1->GetNpadType() == Core::HID::NpadType::JoyconRight)) { // Disconnect the joycon at the second id and connect the dual joycon at the first index. DisconnectNpad(npad_id_2); - AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); + AddNewControllerAt(Core::HID::NpadType::JoyconDual, npad_index_1); } } @@ -1099,16 +939,17 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { } const auto npad_index_1 = NPadIdToIndex(npad_id_1); const auto npad_index_2 = NPadIdToIndex(npad_id_2); + const auto& controller_1 = controller_data[npad_index_1].device; + const auto& controller_2 = controller_data[npad_index_2].device; + const auto type_index_1 = controller_1->GetNpadType(); + const auto type_index_2 = controller_2->GetNpadType(); - if (!IsControllerSupported(connected_controllers[npad_index_1].type) || - !IsControllerSupported(connected_controllers[npad_index_2].type)) { + if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) { return false; } - std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); - - AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); - AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); + AddNewControllerAt(type_index_2, npad_index_1); + AddNewControllerAt(type_index_1, npad_index_2); return true; } @@ -1141,12 +982,14 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { } bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { - return unintended_home_button_input_protection[NPadIdToIndex(npad_id)]; + auto& controller = controller_data[NPadIdToIndex(npad_id)]; + return controller.unintended_home_button_input_protection; } void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id) { - unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; + auto& controller = controller_data[NPadIdToIndex(npad_id)]; + controller.unintended_home_button_input_protection = is_protection_enabled; } void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { @@ -1154,32 +997,34 @@ void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { } void Controller_NPad::ClearAllConnectedControllers() { - for (auto& controller : connected_controllers) { - if (controller.is_connected && controller.type != NPadControllerType::None) { - controller.type = NPadControllerType::None; - controller.is_connected = false; + for (auto& controller : controller_data) { + if (controller.device->IsConnected() && + controller.device->GetNpadType() != Core::HID::NpadType::None) { + controller.device->SetNpadType(Core::HID::NpadType::None); + controller.device->Disconnect(); } } } void Controller_NPad::DisconnectAllConnectedControllers() { - for (auto& controller : connected_controllers) { - controller.is_connected = false; + for (auto& controller : controller_data) { + controller.device->Disconnect(); } } void Controller_NPad::ConnectAllDisconnectedControllers() { - for (auto& controller : connected_controllers) { - if (controller.type != NPadControllerType::None && !controller.is_connected) { - controller.is_connected = true; + for (auto& controller : controller_data) { + if (controller.device->GetNpadType() != Core::HID::NpadType::None && + !controller.device->IsConnected()) { + controller.device->Connect(); } } } void Controller_NPad::ClearAllControllers() { - for (auto& controller : connected_controllers) { - controller.type = NPadControllerType::None; - controller.is_connected = false; + for (auto& controller : controller_data) { + controller.device->SetNpadType(Core::HID::NpadType::None); + controller.device->Disconnect(); } } @@ -1187,8 +1032,8 @@ u32 Controller_NPad::GetAndResetPressState() { return press_state.exchange(0); } -bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { - if (controller == NPadControllerType::Handheld) { +bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) const { + if (controller == Core::HID::NpadType::Handheld) { const bool support_handheld = std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) != supported_npad_id_types.end(); @@ -1196,7 +1041,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const if (!support_handheld) { return false; } - // Handheld should not be supported in docked mode + // Handheld shouldn't be supported in docked mode if (Settings::values.use_docked_mode.GetValue()) { return false; } @@ -1206,18 +1051,19 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { + Core::HID::NpadStyleTag style = GetSupportedStyleSet(); switch (controller) { - case NPadControllerType::ProController: + case Core::HID::NpadType::ProController: return style.fullkey; - case NPadControllerType::JoyDual: + case Core::HID::NpadType::JoyconDual: return style.joycon_dual; - case NPadControllerType::JoyLeft: + case Core::HID::NpadType::JoyconLeft: return style.joycon_left; - case NPadControllerType::JoyRight: + case Core::HID::NpadType::JoyconRight: return style.joycon_right; - case NPadControllerType::GameCube: + case Core::HID::NpadType::GameCube: return style.gamecube; - case NPadControllerType::Pokeball: + case Core::HID::NpadType::Pokeball: return style.palma; default: return false; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index f3e868bdb..483cae5b6 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -12,8 +12,10 @@ #include "common/common_types.h" #include "common/quaternion.h" #include "common/settings.h" -#include "core/frontend/input.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" namespace Kernel { class KEvent; @@ -48,31 +50,6 @@ public: void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - // Called when input devices should be loaded - void OnLoadInputDevices() override; - - enum class NPadControllerType { - None, - ProController, - Handheld, - JoyDual, - JoyLeft, - JoyRight, - GameCube, - Pokeball, - }; - - enum class NpadType : u8 { - ProController = 3, - Handheld = 4, - JoyconDual = 5, - JoyconLeft = 6, - JoyconRight = 7, - GameCube = 8, - Pokeball = 9, - MaxNpadType = 10, - }; - enum class DeviceIndex : u8 { Left = 0, Right = 1, @@ -80,28 +57,33 @@ public: MaxDeviceIndex = 3, }; + // This is nn::hid::GyroscopeZeroDriftMode enum class GyroscopeZeroDriftMode : u32 { Loose = 0, Standard = 1, Tight = 2, }; - enum class NpadHoldType : u64 { + // This is nn::hid::NpadJoyHoldType + enum class NpadJoyHoldType : u64 { Vertical = 0, Horizontal = 1, }; - enum class NpadAssignments : u32 { + // This is nn::hid::NpadJoyAssignmentMode + enum class NpadJoyAssignmentMode : u32 { Dual = 0, Single = 1, }; + // This is nn::hid::NpadHandheldActivationMode enum class NpadHandheldActivationMode : u64 { Dual = 0, Single = 1, None = 2, }; + // This is nn::hid::NpadCommunicationMode enum class NpadCommunicationMode : u64 { Mode_5ms = 0, Mode_10ms = 1, @@ -110,33 +92,14 @@ public: }; struct DeviceHandle { - NpadType npad_type; + Core::HID::NpadType npad_type; u8 npad_id; DeviceIndex device_index; INSERT_PADDING_BYTES_NOINIT(1); }; static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); - struct NpadStyleSet { - union { - u32_le raw{}; - - BitField<0, 1, u32> fullkey; - BitField<1, 1, u32> handheld; - BitField<2, 1, u32> joycon_dual; - BitField<3, 1, u32> joycon_left; - BitField<4, 1, u32> joycon_right; - BitField<5, 1, u32> gamecube; - BitField<6, 1, u32> palma; - BitField<7, 1, u32> lark; - BitField<8, 1, u32> handheld_lark; - BitField<9, 1, u32> lucia; - BitField<29, 1, u32> system_ext; - BitField<30, 1, u32> system; - }; - }; - static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); - + // This is nn::hid::VibrationValue struct VibrationValue { f32 amp_low; f32 freq_low; @@ -168,15 +131,15 @@ public: }; }; - void SetSupportedStyleSet(NpadStyleSet style_set); - NpadStyleSet GetSupportedStyleSet() const; + void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); + Core::HID::NpadStyleTag GetSupportedStyleSet() const; void SetSupportedNpadIdTypes(u8* data, std::size_t length); void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); std::size_t GetSupportedNpadIdTypesSize() const; - void SetHoldType(NpadHoldType joy_hold_type); - NpadHoldType GetHoldType() const; + void SetHoldType(NpadJoyHoldType joy_hold_type); + NpadJoyHoldType GetHoldType() const; void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); NpadHandheldActivationMode GetNpadHandheldActivationMode() const; @@ -184,7 +147,7 @@ public: void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); NpadCommunicationMode GetNpadCommunicationMode() const; - void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); + void SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode); bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, const VibrationValue& vibration_value); @@ -209,9 +172,9 @@ public: void SignalStyleSetChangedEvent(u32 npad_id) const; // Adds a new controller at an index. - void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); + void AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index); // Adds a new controller at an index with connection status. - void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); + void UpdateControllerAt(Core::HID::NpadType controller, std::size_t npad_index, bool connected); void DisconnectNpad(u32 npad_id); void DisconnectNpadAtIndex(std::size_t index); @@ -241,103 +204,37 @@ public: // Specifically for cheat engine and other features. u32 GetAndResetPressState(); - static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); - static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); static std::size_t NPadIdToIndex(u32 npad_id); static u32 IndexToNPad(std::size_t index); static bool IsNpadIdValid(u32 npad_id); static bool IsDeviceHandleValid(const DeviceHandle& device_handle); private: - struct CommonHeader { - s64_le timestamp; - s64_le total_entry_count; - s64_le last_entry_index; - s64_le entry_count; - }; - static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); - - enum class ColorAttributes : u32_le { + // This is nn::hid::detail::ColorAttribute + enum class ColorAttribute : u32_le { Ok = 0, ReadError = 1, NoController = 2, }; - static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size"); - - struct ControllerColor { - u32_le body; - u32_le button; - }; - static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); - - struct FullKeyColor { - ColorAttributes attribute; - ControllerColor fullkey; - }; - static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size"); - - struct JoyconColor { - ColorAttributes attribute; - ControllerColor left; - ControllerColor right; - }; - static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size"); + static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); - struct ControllerPadState { - union { - u64_le raw{}; - // Button states - BitField<0, 1, u64> a; - BitField<1, 1, u64> b; - BitField<2, 1, u64> x; - BitField<3, 1, u64> y; - BitField<4, 1, u64> l_stick; - BitField<5, 1, u64> r_stick; - BitField<6, 1, u64> l; - BitField<7, 1, u64> r; - BitField<8, 1, u64> zl; - BitField<9, 1, u64> zr; - BitField<10, 1, u64> plus; - BitField<11, 1, u64> minus; - - // D-Pad - BitField<12, 1, u64> d_left; - BitField<13, 1, u64> d_up; - BitField<14, 1, u64> d_right; - BitField<15, 1, u64> d_down; - - // Left JoyStick - BitField<16, 1, u64> l_stick_left; - BitField<17, 1, u64> l_stick_up; - BitField<18, 1, u64> l_stick_right; - BitField<19, 1, u64> l_stick_down; - - // Right JoyStick - BitField<20, 1, u64> r_stick_left; - BitField<21, 1, u64> r_stick_up; - BitField<22, 1, u64> r_stick_right; - BitField<23, 1, u64> r_stick_down; - - // Not always active? - BitField<24, 1, u64> left_sl; - BitField<25, 1, u64> left_sr; - - BitField<26, 1, u64> right_sl; - BitField<27, 1, u64> right_sr; - - BitField<28, 1, u64> palma; - BitField<30, 1, u64> handheld_left_b; - }; + // This is nn::hid::detail::NpadFullKeyColorState + struct NpadFullKeyColorState { + ColorAttribute attribute; + Core::HID::NpadControllerColor fullkey; }; - static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); + static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); - struct AnalogPosition { - s32_le x; - s32_le y; + // This is nn::hid::detail::NpadJoyColorState + struct NpadJoyColorState { + ColorAttribute attribute; + Core::HID::NpadControllerColor left; + Core::HID::NpadControllerColor right; }; - static_assert(sizeof(AnalogPosition) == 8, "AnalogPosition is an invalid size"); + static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); - struct ConnectionState { + // This is nn::hid::NpadAttribute + struct NpadAttribute { union { u32_le raw{}; BitField<0, 1, u32> is_connected; @@ -348,76 +245,57 @@ private: BitField<5, 1, u32> is_right_wired; }; }; - static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); - - struct ControllerPad { - ControllerPadState pad_states; - AnalogPosition l_stick; - AnalogPosition r_stick; - }; - static_assert(sizeof(ControllerPad) == 0x18, "ControllerPad is an invalid size"); - - struct GenericStates { - s64_le timestamp; - s64_le timestamp2; - ControllerPad pad; - ConnectionState connection_status; - }; - static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size"); - - struct NPadGeneric { - CommonHeader common; - std::array npad; + static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); + + // This is nn::hid::NpadFullKeyState + // This is nn::hid::NpadHandheldState + // This is nn::hid::NpadJoyDualState + // This is nn::hid::NpadJoyLeftState + // This is nn::hid::NpadJoyRightState + // This is nn::hid::NpadPalmaState + // This is nn::hid::NpadSystemExtState + struct NPadGenericState { + s64_le sampling_number; + Core::HID::NpadButtonState npad_buttons; + Core::HID::AnalogStickState l_stick; + Core::HID::AnalogStickState r_stick; + NpadAttribute connection_status; + INSERT_PADDING_BYTES(4); // Reserved }; - static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); + static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); - struct SixAxisAttributes { + // This is nn::hid::SixAxisSensorAttribute + struct SixAxisSensorAttribute { union { u32_le raw{}; BitField<0, 1, u32> is_connected; BitField<1, 1, u32> is_interpolated; }; }; - static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size"); + static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size"); - struct SixAxisStates { - s64_le timestamp{}; - INSERT_PADDING_WORDS(2); - s64_le timestamp2{}; + // This is nn::hid::SixAxisSensorState + struct SixAxisSensorState { + s64_le delta_time{}; + s64_le sampling_number{}; Common::Vec3f accel{}; Common::Vec3f gyro{}; Common::Vec3f rotation{}; std::array orientation{}; - SixAxisAttributes attribute; + SixAxisSensorAttribute attribute; INSERT_PADDING_BYTES(4); // Reserved }; - static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size"); - - struct SixAxisGeneric { - CommonHeader common{}; - std::array sixaxis{}; - }; - static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); + static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size"); - struct TriggerState { - s64_le timestamp{}; - s64_le timestamp2{}; + // This is nn::hid::server::NpadGcTriggerState + struct NpadGcTriggerState { + s64_le sampling_number{}; s32_le l_analog{}; s32_le r_analog{}; }; - static_assert(sizeof(TriggerState) == 0x18, "TriggerState is an invalid size"); - - struct TriggerGeneric { - INSERT_PADDING_BYTES(0x4); - s64_le timestamp; - INSERT_PADDING_BYTES(0x4); - s64_le total_entry_count; - s64_le last_entry_index; - s64_le entry_count; - std::array trigger{}; - }; - static_assert(sizeof(TriggerGeneric) == 0x1C8, "TriggerGeneric is an invalid size"); + static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); + // This is nn::hid::NpadSystemProperties struct NPadSystemProperties { union { s64_le raw{}; @@ -438,15 +316,18 @@ private: }; static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); - struct NPadButtonProperties { + // This is nn::hid::NpadSystemButtonProperties + struct NpadSystemButtonProperties { union { s32_le raw{}; BitField<0, 1, s32> is_home_button_protection_enabled; }; }; - static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); + static_assert(sizeof(NpadSystemButtonProperties) == 0x4, + "NPadButtonProperties is an invalid size"); - struct NPadDevice { + // This is nn::hid::system::DeviceType + struct DeviceType { union { u32_le raw{}; BitField<0, 1, s32> fullkey; @@ -469,14 +350,6 @@ private: }; }; - struct MotionDevice { - Common::Vec3f accel; - Common::Vec3f gyro; - Common::Vec3f rotation; - std::array orientation; - Common::Quaternion quaternion; - }; - struct NfcXcdHandle { INSERT_PADDING_BYTES(0x60); }; @@ -485,6 +358,7 @@ private: INSERT_PADDING_BYTES(0x4); }; + // This is nn::hid::server::NpadGcTriggerState enum class AppletFooterUiType : u8 { None = 0, HandheldNone = 1, @@ -510,95 +384,90 @@ private: Lagon = 21, }; - struct NPadEntry { - NpadStyleSet style_set; - NpadAssignments assignment_mode; - FullKeyColor fullkey_color; - JoyconColor joycon_color; - - NPadGeneric fullkey_states; - NPadGeneric handheld_states; - NPadGeneric joy_dual_states; - NPadGeneric joy_left_states; - NPadGeneric joy_right_states; - NPadGeneric palma_states; - NPadGeneric system_ext_states; - SixAxisGeneric sixaxis_fullkey; - SixAxisGeneric sixaxis_handheld; - SixAxisGeneric sixaxis_dual_left; - SixAxisGeneric sixaxis_dual_right; - SixAxisGeneric sixaxis_left; - SixAxisGeneric sixaxis_right; - NPadDevice device_type; - INSERT_PADDING_BYTES(0x4); // reserved + // This is nn::hid::detail::NpadInternalState + struct NpadInternalState { + Core::HID::NpadStyleTag style_set; + NpadJoyAssignmentMode assignment_mode; + NpadFullKeyColorState fullkey_color; + NpadJoyColorState joycon_color; + Lifo fullkey_lifo; + Lifo handheld_lifo; + Lifo joy_dual_lifo; + Lifo joy_left_lifo; + Lifo joy_right_lifo; + Lifo palma_lifo; + Lifo system_ext_lifo; + Lifo sixaxis_fullkey_lifo; + Lifo sixaxis_handheld_lifo; + Lifo sixaxis_dual_left_lifo; + Lifo sixaxis_dual_right_lifo; + Lifo sixaxis_left_lifo; + Lifo sixaxis_right_lifo; + DeviceType device_type; + INSERT_PADDING_BYTES(0x4); // Reserved NPadSystemProperties system_properties; - NPadButtonProperties button_properties; - u32 battery_level_dual; - u32 battery_level_left; - u32 battery_level_right; + NpadSystemButtonProperties button_properties; + Core::HID::BatteryLevel battery_level_dual; + Core::HID::BatteryLevel battery_level_left; + Core::HID::BatteryLevel battery_level_right; AppletFooterUiAttributes footer_attributes; AppletFooterUiType footer_type; - // nfc_states needs to be checked switchbrew does not match with HW + // nfc_states needs to be checked switchbrew doesn't match with HW NfcXcdHandle nfc_states; - INSERT_PADDING_BYTES(0x8); // Mutex - TriggerGeneric gc_trigger_states; - INSERT_PADDING_BYTES(0xc1f); + INSERT_PADDING_BYTES(0x18); // Unknown + Lifo gc_trigger_lifo; + INSERT_PADDING_BYTES(0xc1f); // Unknown }; - static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); + static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); - struct ControllerHolder { - NPadControllerType type; - bool is_connected; + struct VibrationData { + bool device_mounted{}; + VibrationValue latest_vibration_value{}; + std::chrono::steady_clock::time_point last_vibration_timepoint{}; }; + struct ControllerData { + Core::HID::EmulatedController* device; + Kernel::KEvent* styleset_changed_event{}; + NpadInternalState shared_memory_entry{}; + + std::array vibration{}; + bool unintended_home_button_input_protection{}; + + // Current pad state + NPadGenericState npad_pad_state{}; + NPadGenericState npad_libnx_state{}; + NpadGcTriggerState npad_trigger_state{}; + SixAxisSensorState sixaxis_fullkey_state{}; + SixAxisSensorState sixaxis_handheld_state{}; + SixAxisSensorState sixaxis_dual_left_state{}; + SixAxisSensorState sixaxis_dual_right_state{}; + SixAxisSensorState sixaxis_left_lifo_state{}; + SixAxisSensorState sixaxis_right_lifo_state{}; + int callback_key; + }; + + void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); void InitNewlyAddedController(std::size_t controller_idx); - bool IsControllerSupported(NPadControllerType controller) const; + bool IsControllerSupported(Core::HID::NpadType controller) const; void RequestPadStateUpdate(u32 npad_id); std::atomic press_state{}; - NpadStyleSet style{}; - std::array shared_memory_entries{}; - using ButtonArray = std::array< - std::array, Settings::NativeButton::NUM_BUTTONS_HID>, - 10>; - using StickArray = std::array< - std::array, Settings::NativeAnalog::NumAnalogs>, - 10>; - using VibrationArray = std::array, - Settings::NativeVibration::NUM_VIBRATIONS_HID>, - 10>; - using MotionArray = std::array< - std::array, Settings::NativeMotion::NUM_MOTIONS_HID>, - 10>; - + std::array controller_data{}; KernelHelpers::ServiceContext& service_context; std::mutex mutex; - ButtonArray buttons; - StickArray sticks; - VibrationArray vibrations; - MotionArray motions; std::vector supported_npad_id_types{}; - NpadHoldType hold_type{NpadHoldType::Vertical}; + NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; - // Each controller should have their own styleset changed event - std::array styleset_changed_events{}; - std::array, 10> - last_vibration_timepoints{}; - std::array, 10> latest_vibration_values{}; bool permit_vibration_session_enabled{false}; - std::array, 10> vibration_devices_mounted{}; - std::array connected_controllers{}; - std::array unintended_home_button_input_protection{}; bool analog_stick_use_center_clamp{}; GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; bool sixaxis_sensors_enabled{true}; f32 sixaxis_fusion_parameter1{}; f32 sixaxis_fusion_parameter2{}; bool sixaxis_at_rest{true}; - std::array npad_pad_states{}; - std::array npad_trigger_states{}; bool is_in_lr_assignment_mode{false}; }; } // namespace Service::HID -- cgit v1.2.3 From dd62a0187d2f8208e288528a7cbf01810bfed20a Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:39:43 -0500 Subject: core: Remove frontend/input --- src/core/frontend/input.h | 217 ---------------------------------------------- 1 file changed, 217 deletions(-) delete mode 100644 src/core/frontend/input.h (limited to 'src/core') diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h deleted file mode 100644 index f1747c5b2..000000000 --- a/src/core/frontend/input.h +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include "common/logging/log.h" -#include "common/param_package.h" -#include "common/quaternion.h" -#include "common/vector_math.h" - -namespace Input { - -enum class AnalogDirection : u8 { - RIGHT, - LEFT, - UP, - DOWN, -}; -struct AnalogProperties { - float deadzone; - float range; - float threshold; -}; -template -struct InputCallback { - std::function on_change; -}; - -/// An abstract class template for an input device (a button, an analog input, etc.). -template -class InputDevice { -public: - virtual ~InputDevice() = default; - virtual StatusType GetStatus() const { - return {}; - } - virtual StatusType GetRawStatus() const { - return GetStatus(); - } - virtual AnalogProperties GetAnalogProperties() const { - return {}; - } - virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { - return {}; - } - virtual bool SetRumblePlay([[maybe_unused]] f32 amp_low, [[maybe_unused]] f32 freq_low, - [[maybe_unused]] f32 amp_high, - [[maybe_unused]] f32 freq_high) const { - return {}; - } - void SetCallback(InputCallback callback_) { - callback = std::move(callback_); - } - void TriggerOnChange() { - if (callback.on_change) { - callback.on_change(GetStatus()); - } - } - -private: - InputCallback callback; -}; - -/// An abstract class template for a factory that can create input devices. -template -class Factory { -public: - virtual ~Factory() = default; - virtual std::unique_ptr Create(const Common::ParamPackage&) = 0; -}; - -namespace Impl { - -template -using FactoryListType = std::unordered_map>>; - -template -struct FactoryList { - static FactoryListType list; -}; - -template -FactoryListType FactoryList::list; - -} // namespace Impl - -/** - * Registers an input device factory. - * @tparam InputDeviceType the type of input devices the factory can create - * @param name the name of the factory. Will be used to match the "engine" parameter when creating - * a device - * @param factory the factory object to register - */ -template -void RegisterFactory(const std::string& name, std::shared_ptr> factory) { - auto pair = std::make_pair(name, std::move(factory)); - if (!Impl::FactoryList::list.insert(std::move(pair)).second) { - LOG_ERROR(Input, "Factory '{}' already registered", name); - } -} - -/** - * Unregisters an input device factory. - * @tparam InputDeviceType the type of input devices the factory can create - * @param name the name of the factory to unregister - */ -template -void UnregisterFactory(const std::string& name) { - if (Impl::FactoryList::list.erase(name) == 0) { - LOG_ERROR(Input, "Factory '{}' not registered", name); - } -} - -/** - * Create an input device from given paramters. - * @tparam InputDeviceType the type of input devices to create - * @param params a serialized ParamPackage string contains all parameters for creating the device - */ -template -std::unique_ptr CreateDevice(const std::string& params) { - const Common::ParamPackage package(params); - const std::string engine = package.Get("engine", "null"); - const auto& factory_list = Impl::FactoryList::list; - const auto pair = factory_list.find(engine); - if (pair == factory_list.end()) { - if (engine != "null") { - LOG_ERROR(Input, "Unknown engine name: {}", engine); - } - return std::make_unique(); - } - return pair->second->Create(package); -} - -/** - * A button device is an input device that returns bool as status. - * true for pressed; false for released. - */ -using ButtonDevice = InputDevice; - -/** - * An analog device is an input device that returns a tuple of x and y coordinates as status. The - * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up - * direction - */ -using AnalogDevice = InputDevice>; - -/** - * A vibration device is an input device that returns an unsigned byte as status. - * It represents whether the vibration device supports vibration or not. - * If the status returns 1, it supports vibration. Otherwise, it does not support vibration. - */ -using VibrationDevice = InputDevice; - -/** - * A motion status is an object that returns a tuple of accelerometer state vector, - * gyroscope state vector, rotation state vector, orientation state matrix and quaterion state - * vector. - * - * For both 3D vectors: - * x+ is the same direction as RIGHT on D-pad. - * y+ is normal to the touch screen, pointing outward. - * z+ is the same direction as UP on D-pad. - * - * For accelerometer state vector - * Units: g (gravitational acceleration) - * - * For gyroscope state vector: - * Orientation is determined by right-hand rule. - * Units: deg/sec - * - * For rotation state vector - * Units: rotations - * - * For orientation state matrix - * x vector - * y vector - * z vector - * - * For quaternion state vector - * xyz vector - * w float - */ -using MotionStatus = std::tuple, Common::Vec3, Common::Vec3, - std::array, Common::Quaternion>; - -/** - * A motion device is an input device that returns a motion status object - */ -using MotionDevice = InputDevice; - -/** - * A touch status is an object that returns an array of 16 tuple elements of two floats and a bool. - * The floats are x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is - * pressed. - */ -using TouchStatus = std::array, 16>; - -/** - * A touch device is an input device that returns a touch status object - */ -using TouchDevice = InputDevice; - -/** - * A mouse device is an input device that returns a tuple of two floats and four ints. - * The first two floats are X and Y device coordinates of the mouse (from 0-1). - * The s32s are the mouse wheel. - */ -using MouseDevice = InputDevice>; - -} // namespace Input -- cgit v1.2.3 From 510c7d29537f4d17ec5751b981729e1bf66fe44c Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:46:17 -0500 Subject: core/frontend: Update applets --- src/core/frontend/applets/controller.cpp | 23 +++++++++++++--------- .../hle/service/am/applets/applet_controller.cpp | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 03bbedf8b..ca1edce15 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -49,26 +49,31 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb // Connect controllers based on the following priority list from highest to lowest priority: // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld if (parameters.allow_pro_controller) { - npad.AddNewControllerAt( - npad.MapSettingsTypeToNPad(Settings::ControllerType::ProController), index); + npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( + Settings::ControllerType::ProController), + index); } else if (parameters.allow_dual_joycons) { - npad.AddNewControllerAt( - npad.MapSettingsTypeToNPad(Settings::ControllerType::DualJoyconDetached), index); + npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( + Settings::ControllerType::DualJoyconDetached), + index); } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { // Assign left joycons to even player indices and right joycons to odd player indices. // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and // a right Joycon for Player 2 in 2 Player Assist mode. if (index % 2 == 0) { - npad.AddNewControllerAt( - npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index); + npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( + Settings::ControllerType::LeftJoycon), + index); } else { - npad.AddNewControllerAt( - npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); + npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( + Settings::ControllerType::RightJoycon), + index); } } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && !Settings::values.use_docked_mode.GetValue()) { // We should *never* reach here under any normal circumstances. - npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), + npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( + Settings::ControllerType::Handheld), index); } else { UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 2721679c1..c1b6cd126 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp @@ -25,7 +25,7 @@ namespace Service::AM::Applets { static Core::Frontend::ControllerParameters ConvertToFrontendParameters( ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, std::vector identification_colors, std::vector text) { - HID::Controller_NPad::NpadStyleSet npad_style_set; + Core::HID::NpadStyleTag npad_style_set; npad_style_set.raw = private_arg.style_set; return { -- cgit v1.2.3 From e14ae06391ac724e4be4557df0568846687a3662 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 20:53:04 -0500 Subject: core: Update input interpreter --- src/core/hid/input_interpreter.cpp | 17 ++++++------- src/core/hid/input_interpreter.h | 52 ++++++++------------------------------ 2 files changed, 18 insertions(+), 51 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp index c33d8a11a..7e7c1816f 100644 --- a/src/core/hid/input_interpreter.cpp +++ b/src/core/hid/input_interpreter.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "core/core.h" +#include "core/hid/hid_types.h" #include "core/hid/input_interpreter.h" #include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/hid.h" @@ -38,25 +39,23 @@ void InputInterpreter::ResetButtonStates() { } } -bool InputInterpreter::IsButtonPressed(HIDButton button) const { - return (button_states[current_index] & (1U << static_cast(button))) != 0; +bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { + return (button_states[current_index] & static_cast(button)) != 0; } -bool InputInterpreter::IsButtonPressedOnce(HIDButton button) const { - const bool current_press = - (button_states[current_index] & (1U << static_cast(button))) != 0; - const bool previous_press = - (button_states[previous_index] & (1U << static_cast(button))) != 0; +bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { + const bool current_press = (button_states[current_index] & static_cast(button)) != 0; + const bool previous_press = (button_states[previous_index] & static_cast(button)) != 0; return current_press && !previous_press; } -bool InputInterpreter::IsButtonHeld(HIDButton button) const { +bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { u32 held_buttons{button_states[0]}; for (std::size_t i = 1; i < button_states.size(); ++i) { held_buttons &= button_states[i]; } - return (held_buttons & (1U << static_cast(button))) != 0; + return (held_buttons & static_cast(button)) != 0; } diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h index 9495e3daf..1791cf9b7 100644 --- a/src/core/hid/input_interpreter.h +++ b/src/core/hid/input_interpreter.h @@ -12,46 +12,14 @@ namespace Core { class System; } +namespace Core::HID { +enum class NpadButton : u64; +} + namespace Service::HID { class Controller_NPad; } -enum class HIDButton : u8 { - A, - B, - X, - Y, - LStick, - RStick, - L, - R, - ZL, - ZR, - Plus, - Minus, - - DLeft, - DUp, - DRight, - DDown, - - LStickLeft, - LStickUp, - LStickRight, - LStickDown, - - RStickLeft, - RStickUp, - RStickRight, - RStickDown, - - LeftSL, - LeftSR, - - RightSL, - RightSR, -}; - /** * The InputInterpreter class interfaces with HID to retrieve button press states. * Input is intended to be polled every 50ms so that a button is considered to be @@ -76,7 +44,7 @@ public: * * @returns True when the button is pressed. */ - [[nodiscard]] bool IsButtonPressed(HIDButton button) const; + [[nodiscard]] bool IsButtonPressed(Core::HID::NpadButton button) const; /** * Checks whether any of the buttons in the parameter list is pressed. @@ -85,7 +53,7 @@ public: * * @returns True when at least one of the buttons is pressed. */ - template + template [[nodiscard]] bool IsAnyButtonPressed() { return (IsButtonPressed(T) || ...); } @@ -98,7 +66,7 @@ public: * * @returns True when the button is pressed once. */ - [[nodiscard]] bool IsButtonPressedOnce(HIDButton button) const; + [[nodiscard]] bool IsButtonPressedOnce(Core::HID::NpadButton button) const; /** * Checks whether any of the buttons in the parameter list is pressed once. @@ -107,7 +75,7 @@ public: * * @returns True when at least one of the buttons is pressed once. */ - template + template [[nodiscard]] bool IsAnyButtonPressedOnce() const { return (IsButtonPressedOnce(T) || ...); } @@ -119,7 +87,7 @@ public: * * @returns True when the button is held down. */ - [[nodiscard]] bool IsButtonHeld(HIDButton button) const; + [[nodiscard]] bool IsButtonHeld(Core::HID::NpadButton button) const; /** * Checks whether any of the buttons in the parameter list is held down. @@ -128,7 +96,7 @@ public: * * @returns True when at least one of the buttons is held down. */ - template + template [[nodiscard]] bool IsAnyButtonHeld() const { return (IsButtonHeld(T) || ...); } -- cgit v1.2.3 From 06a5ef5874144a70e30e577a83ba68d1dad79e78 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 11 Oct 2021 00:43:11 -0500 Subject: core/hid: Add output devices --- src/core/hid/emulated_controller.cpp | 119 ++++++++++++++++++++------ src/core/hid/emulated_controller.h | 13 ++- src/core/hid/hid_types.h | 18 ++++ src/core/hle/service/hid/controllers/npad.cpp | 27 +----- src/core/hle/service/hid/controllers/npad.h | 18 +--- 5 files changed, 126 insertions(+), 69 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 4eb5d99bc..b9d16657a 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -66,12 +66,32 @@ void EmulatedController::ReloadFromSettings() { for (std::size_t index = 0; index < player.motions.size(); ++index) { motion_params[index] = Common::ParamPackage(player.motions[index]); } + + controller.colors_state.left = { + .body = player.body_color_left, + .button = player.button_color_left, + }; + + controller.colors_state.right = { + .body = player.body_color_right, + .button = player.button_color_right, + }; + + controller.colors_state.fullkey = controller.colors_state.left; + + SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + + if (player.connected) { + Connect(); + } else { + Disconnect(); + } + ReloadInput(); } void EmulatedController::ReloadInput() { const auto player_index = NpadIdTypeToIndex(npad_id_type); - const auto& player = Settings::values.players.GetValue()[player_index]; const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -90,21 +110,13 @@ void EmulatedController::ReloadInput() { trigger_devices[1] = Input::CreateDevice(button_params[Settings::NativeButton::ZR]); - controller.colors_state.left = { - .body = player.body_color_left, - .button = player.button_color_left, - }; - - controller.colors_state.right = { - .body = player.body_color_right, - .button = player.button_color_right, - }; - - controller.colors_state.fullkey = controller.colors_state.left; - battery_devices[0] = Input::CreateDevice(left_side); battery_devices[1] = Input::CreateDevice(right_side); + button_params[Settings::NativeButton::ZL].Set("output",true); + output_devices[0] = + Input::CreateDevice(button_params[Settings::NativeButton::ZL]); + for (std::size_t index = 0; index < button_devices.size(); ++index) { if (!button_devices[index]) { continue; @@ -149,14 +161,6 @@ void EmulatedController::ReloadInput() { [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; motion_devices[index]->SetCallback(motion_callback); } - - SetNpadType(MapSettingsTypeToNPad(player.controller_type)); - - if (player.connected) { - Connect(); - } else { - Disconnect(); - } } void EmulatedController::UnloadInput() { @@ -197,7 +201,8 @@ void EmulatedController::SaveCurrentConfig() { const auto player_index = NpadIdTypeToIndex(npad_id_type); auto& player = Settings::values.players.GetValue()[player_index]; - + player.connected = is_connected; + player.controller_type = MapNPadToSettingsType(npad_type); for (std::size_t index = 0; index < player.buttons.size(); ++index) { player.buttons[index] = button_params[index].Serialize(); } @@ -601,13 +606,50 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t TriggerOnChange(ControllerTriggerType::Battery); } -bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index, - [[maybe_unused]] VibrationValue vibration) { - return false; +bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { + if (!output_devices[device_index]) { + return false; + } + + const Input::VibrationStatus status = { + .low_amplitude = vibration.high_amplitude, + .low_frequency = vibration.high_amplitude, + .high_amplitude = vibration.high_amplitude, + .high_frequency = vibration.high_amplitude, + }; + return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; +} + +bool EmulatedController::TestVibration(std::size_t device_index) { + if (!output_devices[device_index]) { + return false; + } + + // Send a slight vibration to test for rumble support + constexpr Input::VibrationStatus status = { + .low_amplitude = 0.001f, + .low_frequency = 160.0f, + .high_amplitude = 0.001f, + .high_frequency = 320.0f, + }; + return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; } -int EmulatedController::TestVibration(std::size_t device_index) { - return 1; +void EmulatedController::SetLedPattern() { + for (auto& device : output_devices) { + if (!device) { + continue; + } + + const LedPattern pattern = GetLedPattern(); + const Input::LedStatus status = { + .led_1 = pattern.position1 != 0, + .led_2 = pattern.position2 != 0, + .led_3 = pattern.position3 != 0, + .led_4 = pattern.position4 != 0, + }; + device->SetLED(status); + } } void EmulatedController::Connect() { @@ -655,6 +697,29 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { TriggerOnChange(ControllerTriggerType::Type); } +LedPattern EmulatedController::GetLedPattern() const { + switch (npad_id_type) { + case NpadIdType::Player1: + return LedPattern{1, 0, 0, 0}; + case NpadIdType::Player2: + return LedPattern{1, 1, 0, 0}; + case NpadIdType::Player3: + return LedPattern{1, 1, 1, 0}; + case NpadIdType::Player4: + return LedPattern{1, 1, 1, 1}; + case NpadIdType::Player5: + return LedPattern{1, 0, 0, 1}; + case NpadIdType::Player6: + return LedPattern{1, 0, 1, 0}; + case NpadIdType::Player7: + return LedPattern{1, 0, 1, 1}; + case NpadIdType::Player8: + return LedPattern{0, 1, 1, 0}; + default: + return LedPattern{0, 0, 0, 0}; + } +} + ButtonValues EmulatedController::GetButtonsValues() const { return controller.button_values; } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 94db9b00b..322d2cab0 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -33,12 +33,14 @@ using ControllerMotionDevices = using TriggerDevices = std::array, Settings::NativeTrigger::NumTriggers>; using BatteryDevices = std::array, 2>; +using OutputDevices = std::array, 2>; using ButtonParams = std::array; using StickParams = std::array; using ControllerMotionParams = std::array; using TriggerParams = std::array; using BatteryParams = std::array; +using OutputParams = std::array; using ButtonValues = std::array; using SticksValues = std::array; @@ -94,6 +96,7 @@ struct ControllerStatus { ControllerColors colors_state{}; BatteryLevelState battery_state{}; }; + enum class ControllerTriggerType { Button, Stick, @@ -137,6 +140,9 @@ public: /// Gets the NpadType for this controller. NpadType GetNpadType() const; + /// Gets the NpadType for this controller. + LedPattern GetLedPattern() const; + void Connect(); void Disconnect(); @@ -179,7 +185,9 @@ public: BatteryLevelState GetBattery() const; bool SetVibration(std::size_t device_index, VibrationValue vibration); - int TestVibration(std::size_t device_index); + bool TestVibration(std::size_t device_index); + + void SetLedPattern(); int SetCallback(ControllerUpdateCallback update_callback); void DeleteCallback(int key); @@ -215,13 +223,14 @@ private: ControllerMotionParams motion_params; TriggerParams trigger_params; BatteryParams battery_params; + OutputParams output_params; ButtonDevices button_devices; StickDevices stick_devices; ControllerMotionDevices motion_devices; TriggerDevices trigger_devices; BatteryDevices battery_devices; - // VibrationDevices vibration_devices; + OutputDevices output_devices; mutable std::mutex mutex; std::unordered_map callback_list; diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index d3f7930c9..f12a14cb8 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -112,6 +112,8 @@ struct NpadStyleTag { BitField<7, 1, u32> lark; BitField<8, 1, u32> handheld_lark; BitField<9, 1, u32> lucia; + BitField<10, 1, u32> lagoon; + BitField<11, 1, u32> lager; BitField<29, 1, u32> system_ext; BitField<30, 1, u32> system; }; @@ -175,6 +177,22 @@ struct NpadPowerInfo { }; static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); +struct LedPattern { + explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { + position1.Assign(light1); + position2.Assign(light2); + position3.Assign(light3); + position4.Assign(light4); + } + union { + u64 raw{}; + BitField<0, 1, u64> position1; + BitField<1, 1, u64> position2; + BitField<2, 1, u64> position3; + BitField<3, 1, u64> position4; + }; +}; + // This is nn::hid::NpadButton enum class NpadButton : u64 { None = 0, diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 03cbd42f4..a2e9ddf4d 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -796,7 +796,7 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, } controller.vibration[device_index].device_mounted = - controller.device->TestVibration(device_index) == 1; + controller.device->TestVibration(device_index); } void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { @@ -954,31 +954,12 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { return true; } -Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { +Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { // These are controllers without led patterns - return LedPattern{0, 0, 0, 0}; - } - switch (npad_id) { - case 0: - return LedPattern{1, 0, 0, 0}; - case 1: - return LedPattern{1, 1, 0, 0}; - case 2: - return LedPattern{1, 1, 1, 0}; - case 3: - return LedPattern{1, 1, 1, 1}; - case 4: - return LedPattern{1, 0, 0, 1}; - case 5: - return LedPattern{1, 0, 1, 0}; - case 6: - return LedPattern{1, 0, 1, 1}; - case 7: - return LedPattern{0, 1, 1, 0}; - default: - return LedPattern{0, 0, 0, 0}; + return Core::HID::LedPattern{0, 0, 0, 0}; } + return controller_data[npad_id].device->GetLedPattern(); } bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 483cae5b6..b0e2f8430 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -115,22 +115,6 @@ public: .freq_high = 320.0f, }; - struct LedPattern { - explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { - position1.Assign(light1); - position2.Assign(light2); - position3.Assign(light3); - position4.Assign(light4); - } - union { - u64 raw{}; - BitField<0, 1, u64> position1; - BitField<1, 1, u64> position2; - BitField<2, 1, u64> position3; - BitField<3, 1, u64> position4; - }; - }; - void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); Core::HID::NpadStyleTag GetSupportedStyleSet() const; @@ -186,7 +170,7 @@ public: void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2); std::pair GetSixAxisFusionParameters(); void ResetSixAxisFusionParameters(); - LedPattern GetLedPattern(u32 npad_id); + Core::HID::LedPattern GetLedPattern(u32 npad_id); bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); void SetAnalogStickUseCenterClamp(bool use_center_clamp); -- cgit v1.2.3 From e0da5c1bbcdf85676f968b63c8ae2587f0464193 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 15 Oct 2021 19:07:47 -0500 Subject: kraken: Fix errors from rebase and format files --- src/core/hid/emulated_controller.cpp | 6 +++++- src/core/hle/service/hid/hid.cpp | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index b9d16657a..b04ab4cd8 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -91,6 +91,7 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { + // If you load any device here add the equivalent to the UnloadInput() function const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -113,7 +114,7 @@ void EmulatedController::ReloadInput() { battery_devices[0] = Input::CreateDevice(left_side); battery_devices[1] = Input::CreateDevice(right_side); - button_params[Settings::NativeButton::ZL].Set("output",true); + button_params[Settings::NativeButton::ZL].Set("output", true); output_devices[0] = Input::CreateDevice(button_params[Settings::NativeButton::ZL]); @@ -179,6 +180,9 @@ void EmulatedController::UnloadInput() { for (auto& battery : battery_devices) { battery.reset(); } + for (auto& output : output_devices) { + output.reset(); + } } void EmulatedController::EnableConfiguration() { diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 18f29bb78..5391334f4 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -8,7 +8,6 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/frontend/input.h" #include "core/hardware_properties.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" -- cgit v1.2.3 From 72e5920240381cbe775dc38fcdff88cf46b55101 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 17 Oct 2021 00:33:00 -0500 Subject: core/hid: Documment some files --- src/core/hid/emulated_console.h | 69 +++++++++++++---- src/core/hid/emulated_controller.h | 148 ++++++++++++++++++++++++++++++++----- src/core/hid/emulated_devices.cpp | 16 +++- src/core/hid/emulated_devices.h | 84 +++++++++++++++++---- 4 files changed, 265 insertions(+), 52 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index d9e275042..7d6cf9506 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -38,9 +38,10 @@ struct TouchFinger { Common::Point position{}; u32_le id{}; bool pressed{}; - Core::HID::TouchAttribute attribute{}; + TouchAttribute attribute{}; }; +// Contains all motion related data that is used on the services struct ConsoleMotion { bool is_at_rest{}; Common::Vec3f accel{}; @@ -57,7 +58,7 @@ struct ConsoleStatus { ConsoleMotionValues motion_values{}; TouchValues touch_values{}; - // Data for Nintendo devices; + // Data for HID services ConsoleMotion motion_state{}; TouchFingerState touch_state{}; }; @@ -75,52 +76,90 @@ struct ConsoleUpdateCallback { class EmulatedConsole { public: /** - * TODO: Write description - * - * @param npad_id_type + * Contains all input data related to the console like motion and touch input */ - explicit EmulatedConsole(); + EmulatedConsole(); ~EmulatedConsole(); YUZU_NON_COPYABLE(EmulatedConsole); YUZU_NON_MOVEABLE(EmulatedConsole); - void ReloadFromSettings(); - void ReloadInput(); + /// Removes all callbacks created from input devices void UnloadInput(); + /// Sets the emulated console into configuring mode. Locking all HID service events from being + /// moddified void EnableConfiguration(); + + /// Returns the emulated console to the normal behaivour void DisableConfiguration(); + + /// Returns true if the emulated console is on configuring mode bool IsConfiguring() const; + + /// Reload all input devices + void ReloadInput(); + + /// Overrides current mapped devices with the stored configuration and reloads all input devices + void ReloadFromSettings(); + + /// Saves the current mapped configuration void SaveCurrentConfig(); + + /// Reverts any mapped changes made that weren't saved void RestoreConfig(); + // Returns the current mapped motion device Common::ParamPackage GetMotionParam() const; + /** + * Updates the current mapped motion device + * @param ParamPackage with controller data to be mapped + */ void SetMotionParam(Common::ParamPackage param); + /// Returns the latest status of motion input from the console with parameters ConsoleMotionValues GetMotionValues() const; + + /// Returns the latest status of touch input from the console with parameters TouchValues GetTouchValues() const; + /// Returns the latest status of motion input from the console ConsoleMotion GetMotion() const; + + /// Returns the latest status of touch input from the console TouchFingerState GetTouch() const; + /** + * Adds a callback to the list of events + * @param ConsoleUpdateCallback that will be triggered + * @return an unique key corresponding to the callback index in the list + */ int SetCallback(ConsoleUpdateCallback update_callback); + + /** + * Removes a callback from the list stopping any future events to this object + * @param Key corresponding to the callback index in the list + */ void DeleteCallback(int key); private: /** - * Sets the status of a button. Applies toggle properties to the output. - * - * @param A CallbackStatus and a button index number + * Updates the motion status of the console + * @param A CallbackStatus containing gyro and accelerometer data */ void SetMotion(Input::CallbackStatus callback); + + /** + * Updates the touch status of the console + * @param callback: A CallbackStatus containing the touch position + * @param index: Finger ID to be updated + */ void SetTouch(Input::CallbackStatus callback, std::size_t index); /** - * Triggers a callback that something has changed - * - * @param Input type of the trigger + * Triggers a callback that something has changed on the console status + * @param Input type of the event to trigger */ void TriggerOnChange(ConsoleTriggerType type); @@ -136,6 +175,8 @@ private: mutable std::mutex mutex; std::unordered_map callback_list; int last_callback_key = 0; + + // Stores the current status of all console input ConsoleStatus console; }; diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 322d2cab0..096fe1705 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -87,7 +87,7 @@ struct ControllerStatus { BatteryValues battery_values{}; VibrationValues vibration_values{}; - // Data for Nintendo devices + // Data for HID serices NpadButtonState npad_button_state{}; DebugPadButton debug_pad_button_state{}; AnalogSticks analog_stick_state{}; @@ -118,9 +118,8 @@ struct ControllerUpdateCallback { class EmulatedController { public: /** - * TODO: Write description - * - * @param npad_id_type + * Contains all input data related to this controller. Like buttons, joysticks, motion. + * @param Npad id type for this specific controller */ explicit EmulatedController(NpadIdType npad_id_type_); ~EmulatedController(); @@ -128,86 +127,197 @@ public: YUZU_NON_COPYABLE(EmulatedController); YUZU_NON_MOVEABLE(EmulatedController); + /// Converts the controller type from settings to npad type static NpadType MapSettingsTypeToNPad(Settings::ControllerType type); + + /// Converts npad type to the equivalent of controller type from settings static Settings::ControllerType MapNPadToSettingsType(NpadType type); - /// Gets the NpadIdType for this controller. + /// Gets the NpadIdType for this controller NpadIdType GetNpadIdType() const; - /// Sets the NpadType for this controller. + /// Sets the NpadType for this controller void SetNpadType(NpadType npad_type_); - /// Gets the NpadType for this controller. + /// Gets the NpadType for this controller NpadType GetNpadType() const; - /// Gets the NpadType for this controller. - LedPattern GetLedPattern() const; - + /// Sets the connected status to true void Connect(); + + /// Sets the connected status to false void Disconnect(); + /// Returns true if the controller has the connected status bool IsConnected() const; + + /// Returns true if vibration is enabled bool IsVibrationEnabled() const; - void ReloadFromSettings(); - void ReloadInput(); + /// Removes all callbacks created from input devices void UnloadInput(); + /// Sets the emulated console into configuring mode. Locking all HID service events from being + /// moddified void EnableConfiguration(); + + /// Returns the emulated console to the normal behaivour void DisableConfiguration(); + + /// Returns true if the emulated device is on configuring mode bool IsConfiguring() const; + + /// Reload all input devices + void ReloadInput(); + + /// Overrides current mapped devices with the stored configuration and reloads all input devices + void ReloadFromSettings(); + + /// Saves the current mapped configuration void SaveCurrentConfig(); + + /// Reverts any mapped changes made that weren't saved void RestoreConfig(); + /// Returns a vector of mapped devices from the mapped button and stick parameters std::vector GetMappedDevices() const; + // Returns the current mapped button device Common::ParamPackage GetButtonParam(std::size_t index) const; + + // Returns the current mapped stick device Common::ParamPackage GetStickParam(std::size_t index) const; + + // Returns the current mapped motion device Common::ParamPackage GetMotionParam(std::size_t index) const; + /** + * Updates the current mapped button device + * @param ParamPackage with controller data to be mapped + */ void SetButtonParam(std::size_t index, Common::ParamPackage param); + + /** + * Updates the current mapped stick device + * @param ParamPackage with controller data to be mapped + */ void SetStickParam(std::size_t index, Common::ParamPackage param); + + /** + * Updates the current mapped motion device + * @param ParamPackage with controller data to be mapped + */ void SetMotionParam(std::size_t index, Common::ParamPackage param); + /// Returns the latest button status from the controller with parameters ButtonValues GetButtonsValues() const; + + /// Returns the latest analog stick status from the controller with parameters SticksValues GetSticksValues() const; + + /// Returns the latest trigger status from the controller with parameters TriggerValues GetTriggersValues() const; + + /// Returns the latest motion status from the controller with parameters ControllerMotionValues GetMotionValues() const; + + /// Returns the latest color status from the controller with parameters ColorValues GetColorsValues() const; + + /// Returns the latest battery status from the controller with parameters BatteryValues GetBatteryValues() const; + /// Returns the latest status of button input for the npad service NpadButtonState GetNpadButtons() const; + + /// Returns the latest status of button input for the debug pad service DebugPadButton GetDebugPadButtons() const; + + /// Returns the latest status of stick input from the mouse AnalogSticks GetSticks() const; + + /// Returns the latest status of trigger input from the mouse NpadGcTriggerState GetTriggers() const; + + /// Returns the latest status of motion input from the mouse MotionState GetMotions() const; + + /// Returns the latest color value from the controller ControllerColors GetColors() const; + + /// Returns the latest battery status from the controller BatteryLevelState GetBattery() const; + /* + * Sends a specific vibration to the output device + * @return returns true if vibration had no errors + */ bool SetVibration(std::size_t device_index, VibrationValue vibration); + + /* + * Sends a small vibration to the output device + * @return returns true if SetVibration was successfull + */ bool TestVibration(std::size_t device_index); + /// Returns the led pattern corresponding to this emulated controller + LedPattern GetLedPattern() const; + + /// Asks the output device to change the player led pattern void SetLedPattern(); + /** + * Adds a callback to the list of events + * @param ConsoleUpdateCallback that will be triggered + * @return an unique key corresponding to the callback index in the list + */ int SetCallback(ControllerUpdateCallback update_callback); + + /** + * Removes a callback from the list stopping any future events to this object + * @param Key corresponding to the callback index in the list + */ void DeleteCallback(int key); private: /** - * Sets the status of a button. Applies toggle properties to the output. - * - * @param A CallbackStatus and a button index number + * Updates the button status of the controller + * @param callback: A CallbackStatus containing the button status + * @param index: Button ID of the to be updated */ void SetButton(Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the analog stick status of the controller + * @param callback: A CallbackStatus containing the analog stick status + * @param index: stick ID of the to be updated + */ void SetStick(Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the trigger status of the controller + * @param callback: A CallbackStatus containing the trigger status + * @param index: trigger ID of the to be updated + */ void SetTrigger(Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the motion status of the controller + * @param callback: A CallbackStatus containing gyro and accelerometer data + * @param index: motion ID of the to be updated + */ void SetMotion(Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the battery status of the controller + * @param callback: A CallbackStatus containing the battery status + * @param index: Button ID of the to be updated + */ void SetBattery(Input::CallbackStatus callback, std::size_t index); /** - * Triggers a callback that something has changed - * - * @param Input type of the trigger + * Triggers a callback that something has changed on the controller status + * @param Input type of the event to trigger */ void TriggerOnChange(ControllerTriggerType type); @@ -235,6 +345,8 @@ private: mutable std::mutex mutex; std::unordered_map callback_list; int last_callback_key = 0; + + // Stores the current status of all controller input ControllerStatus controller; }; diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 3caf90714..54a753d8a 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -114,7 +114,7 @@ Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) con return mouse_button_params[index]; } -void EmulatedDevices::SetButtonParam(std::size_t index, Common::ParamPackage param) { +void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackage param) { if (index >= mouse_button_params.size()) { return; } @@ -132,7 +132,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz auto& current_status = device_status.keyboard_values[index]; current_status.toggle = new_status.toggle; - // Update button status with current + // Update button status with current status if (!current_status.toggle) { current_status.locked = false; if (current_status.value != new_status.value) { @@ -147,7 +147,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz value_changed = true; } - // Unlock button ready for next press + // Unlock button, ready for next press if (!new_status.value && current_status.locked) { current_status.locked = false; } @@ -168,7 +168,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz // interface_status.keyboard_state.a.Assign(current_status.value); // break; // .... - //} + // } TriggerOnChange(DeviceTriggerType::Keyboard); } @@ -303,6 +303,14 @@ void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t TriggerOnChange(DeviceTriggerType::Mouse); } +KeyboardValues EmulatedDevices::GetKeyboardValues() const { + return device_status.keyboard_values; +} + +KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const { + return device_status.keyboard_moddifier_values; +} + MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { return device_status.mouse_button_values; } diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 6f728eff5..c6c19fae4 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -45,7 +45,7 @@ struct DeviceStatus { KeyboardModifierValues keyboard_moddifier_values{}; MouseButtonValues mouse_button_values{}; - // Data for Nintendo devices + // Data for HID serices KeyboardKey keyboard_state{}; KeyboardModifier keyboard_moddifier_state{}; MouseButton mouse_button_state{}; @@ -65,58 +65,108 @@ struct InterfaceUpdateCallback { class EmulatedDevices { public: /** - * TODO: Write description - * - * @param npad_id_type + * Contains all input data related to external devices that aren't necesarily a controller + * like keyboard and mouse */ - explicit EmulatedDevices(); + EmulatedDevices(); ~EmulatedDevices(); YUZU_NON_COPYABLE(EmulatedDevices); YUZU_NON_MOVEABLE(EmulatedDevices); - void ReloadFromSettings(); - void ReloadInput(); + /// Removes all callbacks created from input devices void UnloadInput(); + /// Sets the emulated console into configuring mode. Locking all HID service events from being + /// moddified void EnableConfiguration(); + + /// Returns the emulated console to the normal behaivour void DisableConfiguration(); + + /// Returns true if the emulated device is on configuring mode bool IsConfiguring() const; + + /// Reload all input devices + void ReloadInput(); + + /// Overrides current mapped devices with the stored configuration and reloads all input devices + void ReloadFromSettings(); + + /// Saves the current mapped configuration void SaveCurrentConfig(); - void RestoreConfig(); - std::vector GetMappedDevices() const; + /// Reverts any mapped changes made that weren't saved + void RestoreConfig(); + /// Returns the current mapped motion device Common::ParamPackage GetMouseButtonParam(std::size_t index) const; - void SetButtonParam(std::size_t index, Common::ParamPackage param); + /** + * Updates the current mapped mouse button device + * @param ParamPackage with controller data to be mapped + */ + void SetMouseButtonParam(std::size_t index, Common::ParamPackage param); + /// Returns the latest status of button input from the keyboard with parameters KeyboardValues GetKeyboardValues() const; + + /// Returns the latest status of button input from the keyboard modifiers with parameters KeyboardModifierValues GetKeyboardModdifierValues() const; + + /// Returns the latest status of button input from the mouse with parameters MouseButtonValues GetMouseButtonsValues() const; + /// Returns the latest status of button input from the keyboard KeyboardKey GetKeyboard() const; + + /// Returns the latest status of button input from the keyboard modifiers KeyboardModifier GetKeyboardModifier() const; + + /// Returns the latest status of button input from the mouse MouseButton GetMouseButtons() const; + + /// Returns the latest mouse coordinates MousePosition GetMousePosition() const; + /** + * Adds a callback to the list of events + * @param ConsoleUpdateCallback that will be triggered + * @return an unique key corresponding to the callback index in the list + */ int SetCallback(InterfaceUpdateCallback update_callback); + + /** + * Removes a callback from the list stopping any future events to this object + * @param Key corresponding to the callback index in the list + */ void DeleteCallback(int key); private: /** - * Sets the status of a button. Applies toggle properties to the output. - * - * @param A CallbackStatus and a button index number + * Updates the touch status of the console + * @param callback: A CallbackStatus containing the key status + * @param index: key ID to be updated */ void SetKeyboardButton(Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the touch status of the console + * @param callback: A CallbackStatus containing the modifier key status + * @param index: modifier key ID to be updated + */ void SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the touch status of the console + * @param callback: A CallbackStatus containing the button status + * @param index: Button ID of the to be updated + */ void SetMouseButton(Input::CallbackStatus callback, std::size_t index); /** - * Triggers a callback that something has changed - * - * @param Input type of the trigger + * Triggers a callback that something has changed on the device status + * @param Input type of the event to trigger */ void TriggerOnChange(DeviceTriggerType type); @@ -131,6 +181,8 @@ private: mutable std::mutex mutex; std::unordered_map callback_list; int last_callback_key = 0; + + // Stores the current status of all external device input DeviceStatus device_status; }; -- cgit v1.2.3 From 4d308fd0b4fc8f14754c47811e751bf068b330b8 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 18 Oct 2021 23:15:46 -0500 Subject: hid: Fix controller connection/disconnection --- src/core/hid/emulated_console.cpp | 1 - src/core/hid/emulated_controller.cpp | 98 +++++++++++++++++----- src/core/hid/emulated_controller.h | 18 +++- src/core/hid/hid_types.h | 8 +- .../service/hid/controllers/controller_base.cpp | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 77 +++++++++++------ src/core/hle/service/hid/controllers/npad.h | 3 + 7 files changed, 151 insertions(+), 56 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index c65d05041..7f7c8fd59 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -53,7 +53,6 @@ void EmulatedConsole::ReloadInput() { touch_button_params.Set("x", x); touch_button_params.Set("y", y); touch_button_params.Set("touch_id", static_cast(index)); - LOG_ERROR(Common, "{} ", touch_button_params.Serialize()); touch_devices[index] = Input::CreateDeviceFromString(touch_button_params.Serialize()); if (!touch_devices[index]) { diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index b04ab4cd8..7ef6ef118 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -54,6 +54,7 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type } void EmulatedController::ReloadFromSettings() { + //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type)); const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto& player = Settings::values.players.GetValue()[player_index]; @@ -91,6 +92,7 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { + //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto left_side = button_params[Settings::NativeButton::ZL]; @@ -187,11 +189,29 @@ void EmulatedController::UnloadInput() { void EmulatedController::EnableConfiguration() { is_configuring = true; - SaveCurrentConfig(); + temporary_is_connected = is_connected; + temporary_npad_type = npad_type; } void EmulatedController::DisableConfiguration() { is_configuring = false; + + // Apply temporary npad type to the real controller + if (temporary_npad_type != npad_type) { + if (is_connected) { + Disconnect(); + } + SetNpadType(temporary_npad_type); + } + + // Apply temporary connected status to the real controller + if (temporary_is_connected != is_connected) { + if (temporary_is_connected) { + Connect(); + return; + } + Disconnect(); + } } bool EmulatedController::IsConfiguring() const { @@ -199,10 +219,6 @@ bool EmulatedController::IsConfiguring() const { } void EmulatedController::SaveCurrentConfig() { - if (!is_configuring) { - return; - } - const auto player_index = NpadIdTypeToIndex(npad_id_type); auto& player = Settings::values.players.GetValue()[player_index]; player.connected = is_connected; @@ -657,26 +673,47 @@ void EmulatedController::SetLedPattern() { } void EmulatedController::Connect() { - std::lock_guard lock{mutex}; - if (is_connected) { - LOG_WARNING(Service_HID, "Tried to turn on a connected controller {}", npad_id_type); - return; + { + std::lock_guard lock{mutex}; + if (is_configuring) { + temporary_is_connected = true; + TriggerOnChange(ControllerTriggerType::Connected); + return; + } + + if (is_connected) { + return; + } + is_connected = true; } - is_connected = true; + LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Connected); } void EmulatedController::Disconnect() { - std::lock_guard lock{mutex}; - if (!is_connected) { - LOG_WARNING(Service_HID, "Tried to turn off a disconnected controller {}", npad_id_type); - return; + { + std::lock_guard lock{mutex}; + if (is_configuring) { + temporary_is_connected = false; + LOG_ERROR(Service_HID, "Disconnected temporal controller {}", + NpadIdTypeToIndex(npad_id_type)); + TriggerOnChange(ControllerTriggerType::Disconnected); + return; + } + + if (!is_connected) { + return; + } + is_connected = false; } - is_connected = false; + LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Disconnected); } -bool EmulatedController::IsConnected() const { +bool EmulatedController::IsConnected(bool temporary) const { + if (temporary) { + return temporary_is_connected; + } return is_connected; } @@ -688,16 +725,35 @@ NpadIdType EmulatedController::GetNpadIdType() const { return npad_id_type; } -NpadType EmulatedController::GetNpadType() const { +NpadType EmulatedController::GetNpadType(bool temporary) const { + if (temporary) { + return temporary_npad_type; + } return npad_type; } void EmulatedController::SetNpadType(NpadType npad_type_) { - std::lock_guard lock{mutex}; - if (npad_type == npad_type_) { - return; + { + std::lock_guard lock{mutex}; + + if (is_configuring) { + if (temporary_npad_type == npad_type_) { + return; + } + temporary_npad_type = npad_type_; + TriggerOnChange(ControllerTriggerType::Type); + return; + } + + if (npad_type == npad_type_) { + return; + } + if (is_connected) { + LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", + NpadIdTypeToIndex(npad_id_type)); + } + npad_type = npad_type_; } - npad_type = npad_type_; TriggerOnChange(ControllerTriggerType::Type); } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 096fe1705..6a6dc1892 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -139,8 +139,12 @@ public: /// Sets the NpadType for this controller void SetNpadType(NpadType npad_type_); - /// Gets the NpadType for this controller - NpadType GetNpadType() const; + /** + * Gets the NpadType for this controller + * @param Returns the temporary value if true + * @return NpadType set on the controller + */ + NpadType GetNpadType(bool temporary = false) const; /// Sets the connected status to true void Connect(); @@ -148,8 +152,12 @@ public: /// Sets the connected status to false void Disconnect(); - /// Returns true if the controller has the connected status - bool IsConnected() const; + /** + * Is the emulated connected + * @param Returns the temporary value if true + * @return true if the controller has the connected status + */ + bool IsConnected(bool temporary = false) const; /// Returns true if vibration is enabled bool IsVibrationEnabled() const; @@ -323,7 +331,9 @@ private: NpadIdType npad_id_type; NpadType npad_type{NpadType::None}; + NpadType temporary_npad_type{NpadType::None}; bool is_connected{false}; + bool temporary_is_connected{false}; bool is_configuring{false}; bool is_vibration_enabled{true}; f32 motion_sensitivity{0.01f}; diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index f12a14cb8..539436283 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -47,9 +47,9 @@ constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { return 6; case NpadIdType::Player8: return 7; - case NpadIdType::Other: - return 8; case NpadIdType::Handheld: + return 8; + case NpadIdType::Other: return 9; default: return 0; @@ -76,9 +76,9 @@ constexpr NpadIdType IndexToNpadIdType(size_t index) { case 7: return NpadIdType::Player8; case 8: - return NpadIdType::Other; - case 9: return NpadIdType::Handheld; + case 9: + return NpadIdType::Other; default: return NpadIdType::Invalid; } diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index 9d1e6db6a..74a394784 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp @@ -11,7 +11,7 @@ ControllerBase::~ControllerBase() = default; void ControllerBase::ActivateController() { if (is_activated) { - OnRelease(); + return; } is_activated = true; OnInit(); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a2e9ddf4d..144abab65 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -125,18 +125,22 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, return; } + auto& controller = controller_data[controller_idx]; + const auto is_connected = controller.device->IsConnected(); + const auto npad_type = controller.device->GetNpadType(); switch (type) { case Core::HID::ControllerTriggerType::Connected: - InitNewlyAddedController(controller_idx); - break; case Core::HID::ControllerTriggerType::Disconnected: - DisconnectNpadAtIndex(controller_idx); + if (is_connected == controller.is_connected) { + return; + } + UpdateControllerAt(npad_type, controller_idx, is_connected); break; case Core::HID::ControllerTriggerType::Type: { - auto& controller = controller_data[controller_idx]; - if (controller.device->IsConnected()) { - LOG_ERROR(Service_HID, "Controller type changed without turning off the controller"); + if (npad_type == controller.npad_type) { + return; } + // UpdateControllerAt(npad_type, controller_idx, is_connected); break; } default: @@ -146,6 +150,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { auto& controller = controller_data[controller_idx]; + LOG_ERROR(Service_HID, "Connect {} {}", controller_idx, controller.is_connected); const auto controller_type = controller.device->GetNpadType(); auto& shared_memory = controller.shared_memory_entry; if (controller_type == Core::HID::NpadType::None) { @@ -235,20 +240,23 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.battery_level_left = battery_level.left.battery_level; shared_memory.battery_level_right = battery_level.right.battery_level; + controller.is_connected = true; + controller.device->Connect(); SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); + WriteEmptyEntry(controller.shared_memory_entry); } void Controller_NPad::OnInit() { + if (!IsControllerActivated()) { + return; + } + for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; controller.styleset_changed_event = service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); } - if (!IsControllerActivated()) { - return; - } - if (system.HIDCore().GetSupportedStyleTag().raw == 0) { // We want to support all controllers Core::HID::NpadStyleTag style{}; @@ -277,20 +285,33 @@ void Controller_NPad::OnInit() { for (auto& controller : controller_data) { NPadGenericState dummy_pad_state{}; auto& npad = controller.shared_memory_entry; - for (std::size_t i = 0; i < 17; ++i) { - dummy_pad_state.sampling_number = - npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; - npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); - npad.handheld_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); - npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); - npad.palma_lifo.WriteNextEntry(dummy_pad_state); + for (std::size_t i = 0; i < 19; ++i) { + WriteEmptyEntry(npad); } } } +void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) { + NPadGenericState dummy_pad_state{}; + NpadGcTriggerState dummy_gc_state{}; + dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; + npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1; + npad.handheld_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; + npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1; + npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1; + npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1; + npad.palma_lifo.WriteNextEntry(dummy_pad_state); + dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1; + npad.system_ext_lifo.WriteNextEntry(dummy_pad_state); + dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; + npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state); +} + void Controller_NPad::OnRelease() { for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; @@ -359,6 +380,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { return; } + for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; auto& npad = controller.shared_memory_entry; @@ -366,6 +388,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* const auto& controller_type = controller.device->GetNpadType(); if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { + // Refresh shared memory + std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), + &controller.shared_memory_entry, sizeof(NpadInternalState)); continue; } const u32 npad_index = static_cast(i); @@ -830,14 +855,14 @@ void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::si void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index, bool connected) { - auto& controller = controller_data[npad_index].device; + auto& controller = controller_data[npad_index]; if (!connected) { DisconnectNpadAtIndex(npad_index); return; } - controller->SetNpadType(type); - controller->Connect(); + controller.device->SetNpadType(type); + controller.device->Connect(); InitNewlyAddedController(npad_index); } @@ -847,14 +872,13 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { auto& controller = controller_data[npad_index]; + LOG_ERROR(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected); for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { // Send an empty vibration to stop any vibrations. VibrateControllerAtIndex(npad_index, device_idx, {}); controller.vibration[device_idx].device_mounted = false; } - controller.device->Disconnect(); - auto& shared_memory_entry = controller.shared_memory_entry; shared_memory_entry.style_set.raw = 0; // Zero out shared_memory_entry.device_type.raw = 0; @@ -868,7 +892,10 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory_entry.footer_type = AppletFooterUiType::None; + controller.is_connected = false; + controller.device->Disconnect(); SignalStyleSetChangedEvent(IndexToNPad(npad_index)); + WriteEmptyEntry(controller.shared_memory_entry); } void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index b0e2f8430..d805ccb97 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -417,6 +417,8 @@ private: std::array vibration{}; bool unintended_home_button_input_protection{}; + bool is_connected{}; + Core::HID::NpadType npad_type{Core::HID::NpadType::None}; // Current pad state NPadGenericState npad_pad_state{}; @@ -435,6 +437,7 @@ private: void InitNewlyAddedController(std::size_t controller_idx); bool IsControllerSupported(Core::HID::NpadType controller) const; void RequestPadStateUpdate(u32 npad_id); + void WriteEmptyEntry(NpadInternalState& npad); std::atomic press_state{}; -- cgit v1.2.3 From 601ac43495904f3f7666d79a800a8b4eda5a8461 Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 19 Oct 2021 00:12:24 -0500 Subject: core/hid: Only signal when needed --- src/core/hid/emulated_controller.cpp | 259 ++++++++++++++------------ src/core/hid/emulated_controller.h | 6 +- src/core/hid/input_converter.cpp | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 6 +- 4 files changed, 145 insertions(+), 128 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7ef6ef118..e102c9437 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -94,7 +94,6 @@ void EmulatedController::ReloadFromSettings() { void EmulatedController::ReloadInput() { //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function - const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -337,120 +336,130 @@ void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t i if (index >= controller.button_values.size()) { return; } - std::lock_guard lock{mutex}; - bool value_changed = false; - const auto new_status = TransformToButton(callback); - auto& current_status = controller.button_values[index]; - current_status.toggle = new_status.toggle; - - // Update button status with current - if (!current_status.toggle) { - current_status.locked = false; - if (current_status.value != new_status.value) { - current_status.value = new_status.value; - value_changed = true; - } - } else { - // Toggle button and lock status - if (new_status.value && !current_status.locked) { - current_status.locked = true; - current_status.value = !current_status.value; - value_changed = true; - } + { + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = controller.button_values[index]; + current_status.toggle = new_status.toggle; - // Unlock button ready for next press - if (!new_status.value && current_status.locked) { + // Update button status with current + if (!current_status.toggle) { current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } } - } - if (!value_changed) { - return; - } + if (!value_changed) { + return; + } - if (is_configuring) { - controller.npad_button_state.raw = NpadButton::None; - controller.debug_pad_button_state.raw = 0; - TriggerOnChange(ControllerTriggerType::Button); - return; - } + if (is_configuring) { + controller.npad_button_state.raw = NpadButton::None; + controller.debug_pad_button_state.raw = 0; + TriggerOnChange(ControllerTriggerType::Button, false); + return; + } - switch (index) { - case Settings::NativeButton::A: - controller.npad_button_state.a.Assign(current_status.value); - controller.debug_pad_button_state.a.Assign(current_status.value); - break; - case Settings::NativeButton::B: - controller.npad_button_state.b.Assign(current_status.value); - controller.debug_pad_button_state.b.Assign(current_status.value); - break; - case Settings::NativeButton::X: - controller.npad_button_state.x.Assign(current_status.value); - controller.debug_pad_button_state.x.Assign(current_status.value); - break; - case Settings::NativeButton::Y: - controller.npad_button_state.y.Assign(current_status.value); - controller.debug_pad_button_state.y.Assign(current_status.value); - break; - case Settings::NativeButton::LStick: - controller.npad_button_state.stick_l.Assign(current_status.value); - break; - case Settings::NativeButton::RStick: - controller.npad_button_state.stick_r.Assign(current_status.value); - break; - case Settings::NativeButton::L: - controller.npad_button_state.l.Assign(current_status.value); - controller.debug_pad_button_state.l.Assign(current_status.value); - break; - case Settings::NativeButton::R: - controller.npad_button_state.r.Assign(current_status.value); - controller.debug_pad_button_state.r.Assign(current_status.value); - break; - case Settings::NativeButton::ZL: - controller.npad_button_state.zl.Assign(current_status.value); - controller.debug_pad_button_state.zl.Assign(current_status.value); - break; - case Settings::NativeButton::ZR: - controller.npad_button_state.zr.Assign(current_status.value); - controller.debug_pad_button_state.zr.Assign(current_status.value); - break; - case Settings::NativeButton::Plus: - controller.npad_button_state.plus.Assign(current_status.value); - controller.debug_pad_button_state.plus.Assign(current_status.value); - break; - case Settings::NativeButton::Minus: - controller.npad_button_state.minus.Assign(current_status.value); - controller.debug_pad_button_state.minus.Assign(current_status.value); - break; - case Settings::NativeButton::DLeft: - controller.npad_button_state.left.Assign(current_status.value); - controller.debug_pad_button_state.d_left.Assign(current_status.value); - break; - case Settings::NativeButton::DUp: - controller.npad_button_state.up.Assign(current_status.value); - controller.debug_pad_button_state.d_up.Assign(current_status.value); - break; - case Settings::NativeButton::DRight: - controller.npad_button_state.right.Assign(current_status.value); - controller.debug_pad_button_state.d_right.Assign(current_status.value); - break; - case Settings::NativeButton::DDown: - controller.npad_button_state.down.Assign(current_status.value); - controller.debug_pad_button_state.d_down.Assign(current_status.value); - break; - case Settings::NativeButton::SL: - controller.npad_button_state.left_sl.Assign(current_status.value); - controller.npad_button_state.right_sl.Assign(current_status.value); - break; - case Settings::NativeButton::SR: - controller.npad_button_state.left_sr.Assign(current_status.value); - controller.npad_button_state.right_sr.Assign(current_status.value); - break; - case Settings::NativeButton::Home: - case Settings::NativeButton::Screenshot: - break; + switch (index) { + case Settings::NativeButton::A: + controller.npad_button_state.a.Assign(current_status.value); + controller.debug_pad_button_state.a.Assign(current_status.value); + break; + case Settings::NativeButton::B: + controller.npad_button_state.b.Assign(current_status.value); + controller.debug_pad_button_state.b.Assign(current_status.value); + break; + case Settings::NativeButton::X: + controller.npad_button_state.x.Assign(current_status.value); + controller.debug_pad_button_state.x.Assign(current_status.value); + break; + case Settings::NativeButton::Y: + controller.npad_button_state.y.Assign(current_status.value); + controller.debug_pad_button_state.y.Assign(current_status.value); + break; + case Settings::NativeButton::LStick: + controller.npad_button_state.stick_l.Assign(current_status.value); + break; + case Settings::NativeButton::RStick: + controller.npad_button_state.stick_r.Assign(current_status.value); + break; + case Settings::NativeButton::L: + controller.npad_button_state.l.Assign(current_status.value); + controller.debug_pad_button_state.l.Assign(current_status.value); + break; + case Settings::NativeButton::R: + controller.npad_button_state.r.Assign(current_status.value); + controller.debug_pad_button_state.r.Assign(current_status.value); + break; + case Settings::NativeButton::ZL: + controller.npad_button_state.zl.Assign(current_status.value); + controller.debug_pad_button_state.zl.Assign(current_status.value); + break; + case Settings::NativeButton::ZR: + controller.npad_button_state.zr.Assign(current_status.value); + controller.debug_pad_button_state.zr.Assign(current_status.value); + break; + case Settings::NativeButton::Plus: + controller.npad_button_state.plus.Assign(current_status.value); + controller.debug_pad_button_state.plus.Assign(current_status.value); + break; + case Settings::NativeButton::Minus: + controller.npad_button_state.minus.Assign(current_status.value); + controller.debug_pad_button_state.minus.Assign(current_status.value); + break; + case Settings::NativeButton::DLeft: + controller.npad_button_state.left.Assign(current_status.value); + controller.debug_pad_button_state.d_left.Assign(current_status.value); + break; + case Settings::NativeButton::DUp: + controller.npad_button_state.up.Assign(current_status.value); + controller.debug_pad_button_state.d_up.Assign(current_status.value); + break; + case Settings::NativeButton::DRight: + controller.npad_button_state.right.Assign(current_status.value); + controller.debug_pad_button_state.d_right.Assign(current_status.value); + break; + case Settings::NativeButton::DDown: + controller.npad_button_state.down.Assign(current_status.value); + controller.debug_pad_button_state.d_down.Assign(current_status.value); + break; + case Settings::NativeButton::SL: + controller.npad_button_state.left_sl.Assign(current_status.value); + controller.npad_button_state.right_sl.Assign(current_status.value); + break; + case Settings::NativeButton::SR: + controller.npad_button_state.left_sr.Assign(current_status.value); + controller.npad_button_state.right_sr.Assign(current_status.value); + break; + case Settings::NativeButton::Home: + case Settings::NativeButton::Screenshot: + break; + } + } + if (!is_connected) { + if (npad_id_type == NpadIdType::Player1 && npad_type != NpadType::Handheld) { + Connect(); + } + if (npad_id_type == NpadIdType::Handheld && npad_type == NpadType::Handheld) { + Connect(); + } } - TriggerOnChange(ControllerTriggerType::Button); + TriggerOnChange(ControllerTriggerType::Button, true); } void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) { @@ -463,7 +472,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in if (is_configuring) { controller.analog_stick_state.left = {}; controller.analog_stick_state.right = {}; - TriggerOnChange(ControllerTriggerType::Stick); + TriggerOnChange(ControllerTriggerType::Stick, false); return; } @@ -489,7 +498,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in break; } - TriggerOnChange(ControllerTriggerType::Stick); + TriggerOnChange(ControllerTriggerType::Stick, true); } void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) { @@ -502,7 +511,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t if (is_configuring) { controller.gc_trigger_state.left = 0; controller.gc_trigger_state.right = 0; - TriggerOnChange(ControllerTriggerType::Trigger); + TriggerOnChange(ControllerTriggerType::Trigger, false); return; } @@ -520,7 +529,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t break; } - TriggerOnChange(ControllerTriggerType::Trigger); + TriggerOnChange(ControllerTriggerType::Trigger, true); } void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) { @@ -546,7 +555,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i emulated.UpdateOrientation(raw_status.delta_timestamp); if (is_configuring) { - TriggerOnChange(ControllerTriggerType::Motion); + TriggerOnChange(ControllerTriggerType::Motion, false); return; } @@ -557,7 +566,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i motion.orientation = emulated.GetOrientation(); motion.is_at_rest = emulated.IsMoving(motion_sensitivity); - TriggerOnChange(ControllerTriggerType::Motion); + TriggerOnChange(ControllerTriggerType::Motion, true); } void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) { @@ -568,7 +577,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t controller.battery_values[index] = TransformToBattery(callback); if (is_configuring) { - TriggerOnChange(ControllerTriggerType::Battery); + TriggerOnChange(ControllerTriggerType::Battery, false); return; } @@ -593,6 +602,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t case Input::BatteryLevel::Empty: battery_level = 0; break; + case Input::BatteryLevel::None: case Input::BatteryLevel::Full: default: is_powered = true; @@ -623,7 +633,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t }; break; } - TriggerOnChange(ControllerTriggerType::Battery); + TriggerOnChange(ControllerTriggerType::Battery, true); } bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { @@ -677,7 +687,7 @@ void EmulatedController::Connect() { std::lock_guard lock{mutex}; if (is_configuring) { temporary_is_connected = true; - TriggerOnChange(ControllerTriggerType::Connected); + TriggerOnChange(ControllerTriggerType::Connected,false); return; } @@ -687,7 +697,7 @@ void EmulatedController::Connect() { is_connected = true; } LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Connected); + TriggerOnChange(ControllerTriggerType::Connected,true); } void EmulatedController::Disconnect() { @@ -697,7 +707,7 @@ void EmulatedController::Disconnect() { temporary_is_connected = false; LOG_ERROR(Service_HID, "Disconnected temporal controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected); + TriggerOnChange(ControllerTriggerType::Disconnected,false); return; } @@ -707,7 +717,7 @@ void EmulatedController::Disconnect() { is_connected = false; } LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected); + TriggerOnChange(ControllerTriggerType::Disconnected,true); } bool EmulatedController::IsConnected(bool temporary) const { @@ -741,7 +751,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { return; } temporary_npad_type = npad_type_; - TriggerOnChange(ControllerTriggerType::Type); + TriggerOnChange(ControllerTriggerType::Type,false); return; } @@ -754,7 +764,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { } npad_type = npad_type_; } - TriggerOnChange(ControllerTriggerType::Type); + TriggerOnChange(ControllerTriggerType::Type,true); } LedPattern EmulatedController::GetLedPattern() const { @@ -844,9 +854,12 @@ BatteryLevelState EmulatedController::GetBattery() const { return controller.battery_state; } -void EmulatedController::TriggerOnChange(ControllerTriggerType type) { +void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_service_update) { for (const std::pair poller_pair : callback_list) { const ControllerUpdateCallback& poller = poller_pair.second; + if (!is_service_update && poller.is_service) { + continue; + } if (poller.on_change) { poller.on_change(type); } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 6a6dc1892..3a0b20cf8 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -113,6 +113,7 @@ enum class ControllerTriggerType { struct ControllerUpdateCallback { std::function on_change; + bool is_service; }; class EmulatedController { @@ -325,9 +326,10 @@ private: /** * Triggers a callback that something has changed on the controller status - * @param Input type of the event to trigger + * @param type: Input type of the event to trigger + * @param is_service_update: indicates if this event should be sended to only services */ - void TriggerOnChange(ControllerTriggerType type); + void TriggerOnChange(ControllerTriggerType type, bool is_service_update); NpadIdType npad_id_type; NpadType npad_type{NpadType::None}; diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 5834622e9..128a48ec9 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -10,7 +10,7 @@ namespace Core::HID { Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) { - Input::BatteryStatus battery{}; + Input::BatteryStatus battery{Input::BatteryStatus::None}; switch (callback.type) { case Input::InputType::Analog: case Input::InputType::Trigger: { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 144abab65..6b9d6d11c 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -104,7 +104,10 @@ Controller_NPad::Controller_NPad(Core::System& system_, controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE; controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE; Core::HID::ControllerUpdateCallback engine_callback{ - [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }}; + .on_change = [this, + i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, + .is_service = true, + }; controller.callback_key = controller.device->SetCallback(engine_callback); } } @@ -283,7 +286,6 @@ void Controller_NPad::OnInit() { // Prefill controller buffers for (auto& controller : controller_data) { - NPadGenericState dummy_pad_state{}; auto& npad = controller.shared_memory_entry; for (std::size_t i = 0; i < 19; ++i) { WriteEmptyEntry(npad); -- cgit v1.2.3 From c3ff0a8ac0d1c3f9c0791b5263dae53c06ad6048 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 20 Oct 2021 14:41:56 -0500 Subject: core/hid: Fix rumble too strong at 1% --- src/core/hid/emulated_controller.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index e102c9437..7b0c4a49b 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -54,7 +54,6 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type } void EmulatedController::ReloadFromSettings() { - //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type)); const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto& player = Settings::values.players.GetValue()[player_index]; @@ -92,7 +91,7 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { - //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); + // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -640,12 +639,22 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v if (!output_devices[device_index]) { return false; } + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + const f32 strength = static_cast(player.vibration_strength) / 100.0f; + + // Exponential amplification is too strong at low amplitudes. Switch to a linear + // amplification if strength is set below 0.7f + const Input::VibrationAmplificationType type = + strength > 0.7f ? Input::VibrationAmplificationType::Exponential + : Input::VibrationAmplificationType::Linear; const Input::VibrationStatus status = { - .low_amplitude = vibration.high_amplitude, - .low_frequency = vibration.high_amplitude, - .high_amplitude = vibration.high_amplitude, - .high_frequency = vibration.high_amplitude, + .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), + .low_frequency = vibration.low_frequency, + .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), + .high_frequency = vibration.high_frequency, + .type = type, }; return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; } @@ -661,6 +670,7 @@ bool EmulatedController::TestVibration(std::size_t device_index) { .low_frequency = 160.0f, .high_amplitude = 0.001f, .high_frequency = 320.0f, + .type = Input::VibrationAmplificationType::Linear, }; return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; } @@ -687,7 +697,7 @@ void EmulatedController::Connect() { std::lock_guard lock{mutex}; if (is_configuring) { temporary_is_connected = true; - TriggerOnChange(ControllerTriggerType::Connected,false); + TriggerOnChange(ControllerTriggerType::Connected, false); return; } @@ -697,7 +707,7 @@ void EmulatedController::Connect() { is_connected = true; } LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Connected,true); + TriggerOnChange(ControllerTriggerType::Connected, true); } void EmulatedController::Disconnect() { @@ -707,7 +717,7 @@ void EmulatedController::Disconnect() { temporary_is_connected = false; LOG_ERROR(Service_HID, "Disconnected temporal controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected,false); + TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } @@ -717,7 +727,7 @@ void EmulatedController::Disconnect() { is_connected = false; } LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected,true); + TriggerOnChange(ControllerTriggerType::Disconnected, true); } bool EmulatedController::IsConnected(bool temporary) const { @@ -751,7 +761,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { return; } temporary_npad_type = npad_type_; - TriggerOnChange(ControllerTriggerType::Type,false); + TriggerOnChange(ControllerTriggerType::Type, false); return; } @@ -764,7 +774,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { } npad_type = npad_type_; } - TriggerOnChange(ControllerTriggerType::Type,true); + TriggerOnChange(ControllerTriggerType::Type, true); } LedPattern EmulatedController::GetLedPattern() const { -- cgit v1.2.3 From af55dd193533be577d0a3d01f93a4a3a2c27cd5d Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 20 Oct 2021 17:53:14 -0500 Subject: configuration: Migrate controller settings to emulated controller --- src/core/hid/emulated_controller.cpp | 1 - src/core/hid/emulated_controller.h | 2 +- src/core/hid/hid_core.cpp | 21 +++++++++++++++++++++ src/core/hid/hid_core.h | 10 ++++++++-- .../hle/service/am/applets/applet_controller.cpp | 14 +++----------- 5 files changed, 33 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7b0c4a49b..662260327 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -91,7 +91,6 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { - // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 3a0b20cf8..f3ee70726 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -329,7 +329,7 @@ private: * @param type: Input type of the event to trigger * @param is_service_update: indicates if this event should be sended to only services */ - void TriggerOnChange(ControllerTriggerType type, bool is_service_update); + void TriggerOnChange(ControllerTriggerType type, bool is_service_update); NpadIdType npad_id_type; NpadType npad_type{NpadType::None}; diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index ee76db110..bd17081bd 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -111,6 +111,27 @@ NpadStyleTag HIDCore::GetSupportedStyleTag() const { return supported_style_tag; } +s8 HIDCore::GetPlayerCount() const { + s8 active_players = 0; + for (std::size_t player_index = 0; player_index < 8; player_index++) { + const auto* controller = GetEmulatedControllerByIndex(player_index); + if (controller->IsConnected()) { + active_players++; + } + } + return active_players; +} + +NpadIdType HIDCore::GetFirstNpadId() const { + for (std::size_t player_index = 0; player_index < 10; player_index++) { + const auto* controller = GetEmulatedControllerByIndex(player_index); + if (controller->IsConnected()) { + return controller->GetNpadIdType(); + } + } + return NpadIdType::Player1; +} + void HIDCore::ReloadInputDevices() { player_1->ReloadFromSettings(); player_2->ReloadFromSettings(); diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index f11f48b61..196466a72 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -35,10 +35,16 @@ public: void SetSupportedStyleTag(NpadStyleTag style_tag); NpadStyleTag GetSupportedStyleTag() const; - // Reloads all input devices from settings + /// Counts the connected players from P1-P8 + s8 GetPlayerCount() const; + + /// Returns the first connected npad id + NpadIdType GetFirstNpadId() const; + + /// Reloads all input devices from settings void ReloadInputDevices(); - // Removes all callbacks from input common + /// Removes all callbacks from input common void UnloadInputDevices(); private: diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index c1b6cd126..658265a00 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp @@ -243,19 +243,11 @@ void Controller::Execute() { void Controller::ConfigurationComplete() { ControllerSupportResultInfo result_info{}; - const auto& players = Settings::values.players.GetValue(); - // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. // Otherwise, only count connected players from P1-P8. - result_info.player_count = - is_single_mode - ? 1 - : static_cast(std::count_if(players.begin(), players.end() - 2, - [](const auto& player) { return player.connected; })); - - result_info.selected_id = HID::Controller_NPad::IndexToNPad(std::distance( - players.begin(), std::find_if(players.begin(), players.end(), - [](const auto& player) { return player.connected; }))); + result_info.player_count = is_single_mode ? 1 : system.HIDCore().GetPlayerCount(); + + result_info.selected_id = static_cast(system.HIDCore().GetFirstNpadId()); result_info.result = 0; -- cgit v1.2.3 From 85052b8662d9512077780f717fb2e168390ed705 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 20 Oct 2021 23:18:04 -0500 Subject: service/hid: Fix gesture input --- src/core/hid/emulated_console.cpp | 57 ++++++----- src/core/hid/emulated_console.h | 3 + src/core/hid/emulated_controller.cpp | 4 - src/core/hle/service/hid/controllers/gesture.cpp | 124 +++++++++++++---------- src/core/hle/service/hid/controllers/gesture.h | 29 ++++-- 5 files changed, 129 insertions(+), 88 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 7f7c8fd59..e82cf5990 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -20,27 +20,21 @@ void EmulatedConsole::ReloadFromSettings() { ReloadInput(); } -void EmulatedConsole::ReloadInput() { - motion_devices = Input::CreateDevice(motion_params); - if (motion_devices) { - Input::InputCallback motion_callback{ - [this](Input::CallbackStatus callback) { SetMotion(callback); }}; - motion_devices->SetCallback(motion_callback); - } - - // TODO: Fix this mess +void EmulatedConsole::SetTouchParams() { + // TODO(german77): Support any number of fingers std::size_t index = 0; - const std::string mouse_device_string = - fmt::format("engine:mouse,axis_x:10,axis_y:11,button:{}", index); - touch_devices[index] = Input::CreateDeviceFromString(mouse_device_string); - Input::InputCallback trigger_callbackk{ - [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }}; - touch_devices[index]->SetCallback(trigger_callbackk); - - index++; + + // Hardcode mouse, touchscreen and cemuhook parameters + touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; + touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"}; + touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"}; + touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"}; + touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:2,axis_y:3,button:1"}; + const auto button_index = static_cast(Settings::values.touch_from_button_map_index.GetValue()); const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons; + for (const auto& config_entry : touch_buttons) { Common::ParamPackage params{config_entry}; Common::ParamPackage touch_button_params; @@ -53,15 +47,32 @@ void EmulatedConsole::ReloadInput() { touch_button_params.Set("x", x); touch_button_params.Set("y", y); touch_button_params.Set("touch_id", static_cast(index)); - touch_devices[index] = - Input::CreateDeviceFromString(touch_button_params.Serialize()); - if (!touch_devices[index]) { - continue; + touch_params[index] = touch_button_params; + index++; + if (index >= touch_params.size()) { + return; } + } +} - Input::InputCallback trigger_callback{ +void EmulatedConsole::ReloadInput() { + SetTouchParams(); + motion_devices = Input::CreateDevice(motion_params); + if (motion_devices) { + Input::InputCallback motion_callback{ + [this](Input::CallbackStatus callback) { SetMotion(callback); }}; + motion_devices->SetCallback(motion_callback); + } + + std::size_t index = 0; + for (auto& touch_device : touch_devices) { + touch_device = Input::CreateDevice(touch_params[index]); + if (!touch_device) { + continue; + } + Input::InputCallback touch_callback{ [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }}; - touch_devices[index]->SetCallback(trigger_callback); + touch_device->SetCallback(touch_callback); index++; } } diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 7d6cf9506..c48d25794 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -144,6 +144,9 @@ public: void DeleteCallback(int key); private: + /// Creates and stores the touch params + void SetTouchParams(); + /** * Updates the motion status of the console * @param A CallbackStatus containing gyro and accelerometer data diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 662260327..1ff3022c5 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -705,7 +705,6 @@ void EmulatedController::Connect() { } is_connected = true; } - LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Connected, true); } @@ -714,8 +713,6 @@ void EmulatedController::Disconnect() { std::lock_guard lock{mutex}; if (is_configuring) { temporary_is_connected = false; - LOG_ERROR(Service_HID, "Disconnected temporal controller {}", - NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } @@ -725,7 +722,6 @@ void EmulatedController::Disconnect() { } is_connected = false; } - LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Disconnected, true); } diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 2f98cc54b..a26ce5383 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -28,12 +28,10 @@ constexpr f32 Square(s32 num) { Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) { console = system.HIDCore().GetEmulatedConsole(); } - Controller_Gesture::~Controller_Gesture() = default; void Controller_Gesture::OnInit() { - gesture_lifo.entry_count = 0; - gesture_lifo.last_entry_index = 0; + shared_memory.header.entry_count = 0; force_update = true; } @@ -41,27 +39,27 @@ void Controller_Gesture::OnRelease() {} void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - // TODO FIND WTF IS WRONG HERE!!!!!!!! - return; + shared_memory.header.timestamp = core_timing.GetCPUTicks(); + shared_memory.header.total_entry_count = 17; + if (!IsControllerActivated()) { - gesture_lifo.entry_count = 0; - gesture_lifo.last_entry_index = 0; - std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo)); + shared_memory.header.entry_count = 0; + shared_memory.header.last_entry_index = 0; return; } ReadTouchInput(); GestureProperties gesture = GetGestureProperties(); - f32 time_difference = - static_cast(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); + f32 time_difference = static_cast(shared_memory.header.timestamp - last_update_timestamp) / + (1000 * 1000 * 1000); // Only update if necesary if (!ShouldUpdateGesture(gesture, time_difference)) { return; } - last_update_timestamp = gesture_lifo.timestamp; + last_update_timestamp = shared_memory.header.timestamp; UpdateGestureSharedMemory(data, size, gesture, time_difference); } @@ -77,7 +75,7 @@ void Controller_Gesture::ReadTouchInput() { bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; if (force_update) { force_update = false; return true; @@ -105,16 +103,24 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, GestureType type = GestureType::Idle; GestureAttribute attributes{}; - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; + auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + + if (shared_memory.header.entry_count < 16) { + shared_memory.header.entry_count++; + } + + cur_entry.sampling_number = last_entry.sampling_number + 1; + cur_entry.sampling_number2 = cur_entry.sampling_number; - // Reset next state to default - next_state.sampling_number = last_entry.sampling_number + 1; - next_state.delta = {}; - next_state.vel_x = 0; - next_state.vel_y = 0; - next_state.direction = GestureDirection::None; - next_state.rotation_angle = 0; - next_state.scale = 0; + // Reset values to default + cur_entry.delta = {}; + cur_entry.vel_x = 0; + cur_entry.vel_y = 0; + cur_entry.direction = GestureDirection::None; + cur_entry.rotation_angle = 0; + cur_entry.scale = 0; if (gesture.active_points > 0) { if (last_gesture.active_points == 0) { @@ -127,21 +133,20 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, } // Apply attributes - next_state.detection_count = gesture.detection_count; - next_state.type = type; - next_state.attributes = attributes; - next_state.pos = gesture.mid_point; - next_state.point_count = static_cast(gesture.active_points); - next_state.points = gesture.points; + cur_entry.detection_count = gesture.detection_count; + cur_entry.type = type; + cur_entry.attributes = attributes; + cur_entry.pos = gesture.mid_point; + cur_entry.point_count = static_cast(gesture.active_points); + cur_entry.points = gesture.points; last_gesture = gesture; - gesture_lifo.WriteNextEntry(next_state); - std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + const auto& last_entry = GetLastGestureEntry(); gesture.detection_count++; type = GestureType::Touch; @@ -155,7 +160,7 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& typ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + const auto& last_entry = GetLastGestureEntry(); // Promote to pan type if touch moved for (size_t id = 0; id < MAX_POINTS; id++) { @@ -190,7 +195,7 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Gestu void Controller_Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type, GestureAttribute& attributes, f32 time_difference) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + const auto& last_entry = GetLastGestureEntry(); if (last_gesture_props.active_points != 0) { switch (last_entry.type) { @@ -240,18 +245,19 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture, void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type, f32 time_difference) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + const auto& last_entry = GetLastGestureEntry(); - next_state.delta = gesture.mid_point - last_entry.pos; - next_state.vel_x = static_cast(next_state.delta.x) / time_difference; - next_state.vel_y = static_cast(next_state.delta.y) / time_difference; + cur_entry.delta = gesture.mid_point - last_entry.pos; + cur_entry.vel_x = static_cast(cur_entry.delta.x) / time_difference; + cur_entry.vel_y = static_cast(cur_entry.delta.y) / time_difference; last_pan_time_difference = time_difference; // Promote to pinch type if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > pinch_threshold) { type = GestureType::Pinch; - next_state.scale = gesture.average_distance / last_gesture_props.average_distance; + cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance; } const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / @@ -259,21 +265,22 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, // Promote to rotate type if (std::abs(angle_between_two_lines) > angle_threshold) { type = GestureType::Rotate; - next_state.scale = 0; - next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; + cur_entry.scale = 0; + cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; } } void Controller_Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type, f32 time_difference) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; - next_state.vel_x = + auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + const auto& last_entry = GetLastGestureEntry(); + cur_entry.vel_x = static_cast(last_entry.delta.x) / (last_pan_time_difference + time_difference); - next_state.vel_y = + cur_entry.vel_y = static_cast(last_entry.delta.y) / (last_pan_time_difference + time_difference); const f32 curr_vel = - std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); + std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); // Set swipe event with parameters if (curr_vel > swipe_threshold) { @@ -283,33 +290,42 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, // End panning without swipe type = GestureType::Complete; - next_state.vel_x = 0; - next_state.vel_y = 0; + cur_entry.vel_x = 0; + cur_entry.vel_y = 0; force_update = true; } void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type) { - const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; + auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + const auto& last_entry = GetLastGestureEntry(); type = GestureType::Swipe; gesture = last_gesture_props; force_update = true; - next_state.delta = last_entry.delta; + cur_entry.delta = last_entry.delta; - if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { - if (next_state.delta.x > 0) { - next_state.direction = GestureDirection::Right; + if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) { + if (cur_entry.delta.x > 0) { + cur_entry.direction = GestureDirection::Right; return; } - next_state.direction = GestureDirection::Left; + cur_entry.direction = GestureDirection::Left; return; } - if (next_state.delta.y > 0) { - next_state.direction = GestureDirection::Down; + if (cur_entry.delta.y > 0) { + cur_entry.direction = GestureDirection::Down; return; } - next_state.direction = GestureDirection::Up; + cur_entry.direction = GestureDirection::Up; +} + +Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() { + return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; +} + +const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { + return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; } Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 8e6f315a4..6128fb0ad 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -71,6 +71,7 @@ private: // This is nn::hid::GestureState struct GestureState { s64_le sampling_number; + s64_le sampling_number2; s64_le detection_count; GestureType type; GestureDirection direction; @@ -84,7 +85,21 @@ private: s32_le point_count; std::array, 4> points; }; - static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); + static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); + + struct CommonHeader { + s64_le timestamp; + s64_le total_entry_count; + s64_le last_entry_index; + s64_le entry_count; + }; + static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); + + struct SharedMemory { + CommonHeader header; + std::array gesture_states; + }; + static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size"); struct Finger { Common::Point pos{}; @@ -137,17 +152,17 @@ private: void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type); + // Retrieves the last gesture entry, as indicated by shared memory indices. + [[nodiscard]] GestureState& GetLastGestureEntry(); + [[nodiscard]] const GestureState& GetLastGestureEntry() const; + // Returns the average distance, angle and middle point of the active fingers GestureProperties GetGestureProperties(); - // This is nn::hid::detail::GestureLifo - Lifo gesture_lifo{}; - static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); - GestureState next_state{}; - - std::array fingers{}; + SharedMemory shared_memory{}; Core::HID::EmulatedConsole* console; + std::array fingers{}; GestureProperties last_gesture{}; s64_le last_update_timestamp{}; s64_le last_tap_timestamp{}; -- cgit v1.2.3 From 95cf66b6559c3e7a1eb40be919f16217566ffdbc Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 21 Oct 2021 00:49:09 -0500 Subject: service/hid: Use ring buffer for gestures --- src/core/hle/service/hid/controllers/gesture.cpp | 107 ++++++++++------------- src/core/hle/service/hid/controllers/gesture.h | 24 ++--- 2 files changed, 52 insertions(+), 79 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index a26ce5383..a82d04b3b 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -31,7 +31,8 @@ Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(s Controller_Gesture::~Controller_Gesture() = default; void Controller_Gesture::OnInit() { - shared_memory.header.entry_count = 0; + gesture_lifo.entry_count = 0; + gesture_lifo.last_entry_index = 0; force_update = true; } @@ -39,27 +40,25 @@ void Controller_Gesture::OnRelease() {} void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - shared_memory.header.timestamp = core_timing.GetCPUTicks(); - shared_memory.header.total_entry_count = 17; - if (!IsControllerActivated()) { - shared_memory.header.entry_count = 0; - shared_memory.header.last_entry_index = 0; + gesture_lifo.entry_count = 0; + gesture_lifo.last_entry_index = 0; + std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo)); return; } ReadTouchInput(); GestureProperties gesture = GetGestureProperties(); - f32 time_difference = static_cast(shared_memory.header.timestamp - last_update_timestamp) / - (1000 * 1000 * 1000); + f32 time_difference = + static_cast(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); // Only update if necesary if (!ShouldUpdateGesture(gesture, time_difference)) { return; } - last_update_timestamp = shared_memory.header.timestamp; + last_update_timestamp = gesture_lifo.timestamp; UpdateGestureSharedMemory(data, size, gesture, time_difference); } @@ -75,7 +74,7 @@ void Controller_Gesture::ReadTouchInput() { bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) { - const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; + const auto& last_entry = GetLastGestureEntry(); if (force_update) { force_update = false; return true; @@ -103,24 +102,16 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, GestureType type = GestureType::Idle; GestureAttribute attributes{}; - const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; - shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; - - if (shared_memory.header.entry_count < 16) { - shared_memory.header.entry_count++; - } + const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; - - // Reset values to default - cur_entry.delta = {}; - cur_entry.vel_x = 0; - cur_entry.vel_y = 0; - cur_entry.direction = GestureDirection::None; - cur_entry.rotation_angle = 0; - cur_entry.scale = 0; + // Reset next state to default + next_state.sampling_number = last_entry.sampling_number + 1; + next_state.delta = {}; + next_state.vel_x = 0; + next_state.vel_y = 0; + next_state.direction = GestureDirection::None; + next_state.rotation_angle = 0; + next_state.scale = 0; if (gesture.active_points > 0) { if (last_gesture.active_points == 0) { @@ -133,15 +124,16 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, } // Apply attributes - cur_entry.detection_count = gesture.detection_count; - cur_entry.type = type; - cur_entry.attributes = attributes; - cur_entry.pos = gesture.mid_point; - cur_entry.point_count = static_cast(gesture.active_points); - cur_entry.points = gesture.points; + next_state.detection_count = gesture.detection_count; + next_state.type = type; + next_state.attributes = attributes; + next_state.pos = gesture.mid_point; + next_state.point_count = static_cast(gesture.active_points); + next_state.points = gesture.points; last_gesture = gesture; - std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); + gesture_lifo.WriteNextEntry(next_state); + std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); } void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, @@ -245,19 +237,18 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture, void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type, f32 time_difference) { - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; const auto& last_entry = GetLastGestureEntry(); - cur_entry.delta = gesture.mid_point - last_entry.pos; - cur_entry.vel_x = static_cast(cur_entry.delta.x) / time_difference; - cur_entry.vel_y = static_cast(cur_entry.delta.y) / time_difference; + next_state.delta = gesture.mid_point - last_entry.pos; + next_state.vel_x = static_cast(next_state.delta.x) / time_difference; + next_state.vel_y = static_cast(next_state.delta.y) / time_difference; last_pan_time_difference = time_difference; // Promote to pinch type if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > pinch_threshold) { type = GestureType::Pinch; - cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance; + next_state.scale = gesture.average_distance / last_gesture_props.average_distance; } const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / @@ -265,22 +256,21 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, // Promote to rotate type if (std::abs(angle_between_two_lines) > angle_threshold) { type = GestureType::Rotate; - cur_entry.scale = 0; - cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; + next_state.scale = 0; + next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; } } void Controller_Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type, f32 time_difference) { - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; const auto& last_entry = GetLastGestureEntry(); - cur_entry.vel_x = + next_state.vel_x = static_cast(last_entry.delta.x) / (last_pan_time_difference + time_difference); - cur_entry.vel_y = + next_state.vel_y = static_cast(last_entry.delta.y) / (last_pan_time_difference + time_difference); const f32 curr_vel = - std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); + std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); // Set swipe event with parameters if (curr_vel > swipe_threshold) { @@ -290,42 +280,37 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, // End panning without swipe type = GestureType::Complete; - cur_entry.vel_x = 0; - cur_entry.vel_y = 0; + next_state.vel_x = 0; + next_state.vel_y = 0; force_update = true; } void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, GestureType& type) { - auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; const auto& last_entry = GetLastGestureEntry(); type = GestureType::Swipe; gesture = last_gesture_props; force_update = true; - cur_entry.delta = last_entry.delta; + next_state.delta = last_entry.delta; - if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) { - if (cur_entry.delta.x > 0) { - cur_entry.direction = GestureDirection::Right; + if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { + if (next_state.delta.x > 0) { + next_state.direction = GestureDirection::Right; return; } - cur_entry.direction = GestureDirection::Left; + next_state.direction = GestureDirection::Left; return; } - if (cur_entry.delta.y > 0) { - cur_entry.direction = GestureDirection::Down; + if (next_state.delta.y > 0) { + next_state.direction = GestureDirection::Down; return; } - cur_entry.direction = GestureDirection::Up; -} - -Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() { - return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; + next_state.direction = GestureDirection::Up; } const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { - return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; + return gesture_lifo.ReadCurrentEntry().state; } Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 6128fb0ad..6f5abaa4f 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -71,7 +71,6 @@ private: // This is nn::hid::GestureState struct GestureState { s64_le sampling_number; - s64_le sampling_number2; s64_le detection_count; GestureType type; GestureDirection direction; @@ -85,21 +84,7 @@ private: s32_le point_count; std::array, 4> points; }; - static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); - - struct CommonHeader { - s64_le timestamp; - s64_le total_entry_count; - s64_le last_entry_index; - s64_le entry_count; - }; - static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); - - struct SharedMemory { - CommonHeader header; - std::array gesture_states; - }; - static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size"); + static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); struct Finger { Common::Point pos{}; @@ -153,13 +138,16 @@ private: GestureType& type); // Retrieves the last gesture entry, as indicated by shared memory indices. - [[nodiscard]] GestureState& GetLastGestureEntry(); [[nodiscard]] const GestureState& GetLastGestureEntry() const; // Returns the average distance, angle and middle point of the active fingers GestureProperties GetGestureProperties(); - SharedMemory shared_memory{}; + // This is nn::hid::detail::GestureLifo + Lifo gesture_lifo{}; + static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); + GestureState next_state{}; + Core::HID::EmulatedConsole* console; std::array fingers{}; -- cgit v1.2.3 From b5e72de753ae4de5c5fae7087abb00dc4242451d Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 21 Oct 2021 13:56:52 -0500 Subject: kraken: Address comments from review review fixes --- src/core/frontend/applets/controller.cpp | 51 +++++++++++---------------- src/core/frontend/applets/controller.h | 8 ++--- src/core/hid/emulated_console.cpp | 2 -- src/core/hid/emulated_controller.cpp | 12 +++++-- src/core/hid/emulated_controller.h | 1 - src/core/hid/hid_core.cpp | 4 +-- src/core/hid/hid_core.h | 3 ++ src/core/hle/service/am/applets/applets.cpp | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 10 +++--- src/core/hle/service/hid/controllers/npad.h | 2 +- src/core/hle/service/hid/hid.cpp | 3 +- 11 files changed, 47 insertions(+), 51 deletions(-) (limited to 'src/core') diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index ca1edce15..30500ef1e 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -5,16 +5,16 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/frontend/applets/controller.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/hid.h" -#include "core/hle/service/sm/sm.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" namespace Core::Frontend { ControllerApplet::~ControllerApplet() = default; -DefaultControllerApplet::DefaultControllerApplet(Service::SM::ServiceManager& service_manager_) - : service_manager{service_manager_} {} +DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) + : hid_core{hid_core_} {} DefaultControllerApplet::~DefaultControllerApplet() = default; @@ -22,24 +22,20 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb const ControllerParameters& parameters) const { LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); - auto& npad = - service_manager.GetService("hid") - ->GetAppletResource() - ->GetController(Service::HID::HidController::NPad); - - auto& players = Settings::values.players.GetValue(); - const std::size_t min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; // Disconnect Handheld first. - npad.DisconnectNpadAtIndex(8); + auto* handheld =hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + handheld->Disconnect(); // Deduce the best configuration based on the input parameters. - for (std::size_t index = 0; index < players.size() - 2; ++index) { + for (std::size_t index = 0; index < hid_core.available_controllers - 2; ++index) { + auto* controller = hid_core.GetEmulatedControllerByIndex(index); + // First, disconnect all controllers regardless of the value of keep_controllers_connected. // This makes it easy to connect the desired controllers. - npad.DisconnectNpadAtIndex(index); + controller->Disconnect(); // Only connect the minimum number of required players. if (index >= min_supported_players) { @@ -49,32 +45,27 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb // Connect controllers based on the following priority list from highest to lowest priority: // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld if (parameters.allow_pro_controller) { - npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( - Settings::ControllerType::ProController), - index); + controller->SetNpadType(Core::HID::NpadType::ProController); + controller->Connect(); } else if (parameters.allow_dual_joycons) { - npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( - Settings::ControllerType::DualJoyconDetached), - index); + controller->SetNpadType(Core::HID::NpadType::JoyconDual); + controller->Connect(); } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { // Assign left joycons to even player indices and right joycons to odd player indices. // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and // a right Joycon for Player 2 in 2 Player Assist mode. if (index % 2 == 0) { - npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( - Settings::ControllerType::LeftJoycon), - index); + controller->SetNpadType(Core::HID::NpadType::JoyconLeft); + controller->Connect(); } else { - npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( - Settings::ControllerType::RightJoycon), - index); + controller->SetNpadType(Core::HID::NpadType::JoyconRight); + controller->Connect(); } } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && !Settings::values.use_docked_mode.GetValue()) { // We should *never* reach here under any normal circumstances. - npad.AddNewControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad( - Settings::ControllerType::Handheld), - index); + controller->SetNpadType(Core::HID::NpadType::Handheld); + controller->Connect(); } else { UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); } diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h index b0626a0f9..014bc8901 100644 --- a/src/core/frontend/applets/controller.h +++ b/src/core/frontend/applets/controller.h @@ -8,8 +8,8 @@ #include "common/common_types.h" -namespace Service::SM { -class ServiceManager; +namespace Core::HID { +class HIDCore; } namespace Core::Frontend { @@ -44,14 +44,14 @@ public: class DefaultControllerApplet final : public ControllerApplet { public: - explicit DefaultControllerApplet(Service::SM::ServiceManager& service_manager_); + explicit DefaultControllerApplet(HID::HIDCore& hid_core_); ~DefaultControllerApplet() override; void ReconfigureControllers(std::function callback, const ControllerParameters& parameters) const override; private: - Service::SM::ServiceManager& service_manager; + HID::HIDCore& hid_core; }; } // namespace Core::Frontend diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index e82cf5990..540fd107b 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included -#include - #include "core/hid/emulated_console.h" #include "core/hid/input_converter.h" diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 1ff3022c5..d59758e99 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included -#include - #include "core/hid/emulated_controller.h" #include "core/hid/input_converter.h" @@ -635,6 +633,9 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t } bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { + if (device_index >= output_devices.size()) { + return false; + } if (!output_devices[device_index]) { return false; } @@ -659,6 +660,9 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v } bool EmulatedController::TestVibration(std::size_t device_index) { + if (device_index >= output_devices.size()) { + return false; + } if (!output_devices[device_index]) { return false; } @@ -733,7 +737,9 @@ bool EmulatedController::IsConnected(bool temporary) const { } bool EmulatedController::IsVibrationEnabled() const { - return is_vibration_enabled; + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + return player.vibration_enabled; } NpadIdType EmulatedController::GetNpadIdType() const { diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index f3ee70726..50f21ccd9 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -337,7 +337,6 @@ private: bool is_connected{false}; bool temporary_is_connected{false}; bool is_configuring{false}; - bool is_vibration_enabled{true}; f32 motion_sensitivity{0.01f}; ButtonParams button_params; diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index bd17081bd..cc1b3c295 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -113,7 +113,7 @@ NpadStyleTag HIDCore::GetSupportedStyleTag() const { s8 HIDCore::GetPlayerCount() const { s8 active_players = 0; - for (std::size_t player_index = 0; player_index < 8; player_index++) { + for (std::size_t player_index = 0; player_index < available_controllers -2; player_index++) { const auto* controller = GetEmulatedControllerByIndex(player_index); if (controller->IsConnected()) { active_players++; @@ -123,7 +123,7 @@ s8 HIDCore::GetPlayerCount() const { } NpadIdType HIDCore::GetFirstNpadId() const { - for (std::size_t player_index = 0; player_index < 10; player_index++) { + for (std::size_t player_index = 0; player_index < available_controllers; player_index++) { const auto* controller = GetEmulatedControllerByIndex(player_index); if (controller->IsConnected()) { return controller->GetNpadIdType(); diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 196466a72..a4a66a3a4 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -47,6 +47,9 @@ public: /// Removes all callbacks from input common void UnloadInputDevices(); + /// Number of emulated controllers + const std::size_t available_controllers{10}; + private: std::unique_ptr player_1; std::unique_ptr player_2; diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 7320b1c0f..134ac1ee2 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -231,7 +231,7 @@ void AppletManager::SetDefaultAppletFrontendSet() { void AppletManager::SetDefaultAppletsIfMissing() { if (frontend.controller == nullptr) { frontend.controller = - std::make_unique(system.ServiceManager()); + std::make_unique(system.HIDCore()); } if (frontend.error == nullptr) { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 6b9d6d11c..62b324080 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -608,15 +608,15 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_fullkey_state.sampling_number = npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_handheld_state.sampling_number = - npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_dual_left_state.sampling_number = - npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_dual_right_state.sampling_number = - npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_left_lifo_state.sampling_number = - npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_right_lifo_state.sampling_number = - npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index d805ccb97..1c6ea6f88 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -342,7 +342,7 @@ private: INSERT_PADDING_BYTES(0x4); }; - // This is nn::hid::server::NpadGcTriggerState + // This is nn::hid::system::AppletFooterUiType enum class AppletFooterUiType : u8 { None = 0, HandheldNone = 1, diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 5391334f4..ac48f96d3 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -8,7 +8,6 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/hardware_properties.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" @@ -34,7 +33,7 @@ namespace Service::HID { // Updating period for each HID device. -// Period time is obtained by measuring the number of samples in a second +// Period time is obtained by measuring the number of samples in a second on HW using a homebrew constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; -- cgit v1.2.3 From 21819da8cd7da60be8f8ba82dc940c2496a5317e Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 22 Oct 2021 12:34:44 -0500 Subject: yuzu: Fix loading input profiles --- src/core/hid/motion_input.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp index 93f37b77b..c25fea966 100644 --- a/src/core/hid/motion_input.cpp +++ b/src/core/hid/motion_input.cpp @@ -73,6 +73,8 @@ void MotionInput::UpdateRotation(u64 elapsed_time) { rotations += gyro * sample_period; } +// Based on Madgwick's implementation of Mayhony's AHRS algorithm. +// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs void MotionInput::UpdateOrientation(u64 elapsed_time) { if (!IsCalibrated(0.1f)) { ResetOrientation(); -- cgit v1.2.3 From e2e5f1beaf602f801bdd93d24c3cfc7862131890 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 22 Oct 2021 22:31:37 -0500 Subject: service/hid: Match shared memory closer to HW --- src/core/hle/service/hid/controllers/npad.cpp | 58 ++++++++++++++++++--------- src/core/hle/service/hid/controllers/npad.h | 43 ++++++++++++++++---- 2 files changed, 75 insertions(+), 26 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 62b324080..aad298364 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -123,8 +123,8 @@ Controller_NPad::~Controller_NPad() { void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { if (type == Core::HID::ControllerTriggerType::All) { - ControllerUpdate(Core::HID::ControllerTriggerType::Type, controller_idx); ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); + ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); return; } @@ -139,11 +139,15 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, } UpdateControllerAt(npad_type, controller_idx, is_connected); break; - case Core::HID::ControllerTriggerType::Type: { - if (npad_type == controller.npad_type) { + case Core::HID::ControllerTriggerType::Battery: { + if (!controller.is_connected) { return; } - // UpdateControllerAt(npad_type, controller_idx, is_connected); + auto& shared_memory = controller.shared_memory_entry; + const auto& battery_level = controller.device->GetBattery(); + shared_memory.battery_level_dual = battery_level.dual.battery_level; + shared_memory.battery_level_left = battery_level.left.battery_level; + shared_memory.battery_level_right = battery_level.right.battery_level; break; } default: @@ -153,7 +157,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { auto& controller = controller_data[controller_idx]; - LOG_ERROR(Service_HID, "Connect {} {}", controller_idx, controller.is_connected); + LOG_WARNING(Service_HID, "Connect {} {}", controller_idx, controller.is_connected); const auto controller_type = controller.device->GetNpadType(); auto& shared_memory = controller.shared_memory_entry; if (controller_type == Core::HID::NpadType::None) { @@ -277,20 +281,29 @@ void Controller_NPad::OnInit() { std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i].device; - if (controller->IsConnected()) { - AddNewControllerAt(controller->GetNpadType(), i); - } - } - // Prefill controller buffers for (auto& controller : controller_data) { auto& npad = controller.shared_memory_entry; + npad.fullkey_color = { + .attribute = ColorAttribute::NoController, + }; + npad.joycon_color = { + .attribute = ColorAttribute::NoController, + }; + // HW seems to initialize the first 19 entries for (std::size_t i = 0; i < 19; ++i) { WriteEmptyEntry(npad); } } + + // Connect controllers + for (auto& controller : controller_data) { + const auto& device = controller.device; + if (device->IsConnected()) { + const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType()); + AddNewControllerAt(device->GetNpadType(), index); + } + } } void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) { @@ -618,8 +631,14 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_right_lifo_state.sampling_number = npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); - npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); + if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { + // This buffer only is updated on handheld on HW + npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); + } else { + // Hanheld doesn't update this buffer on HW + npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); + } + npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); @@ -864,7 +883,6 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t n } controller.device->SetNpadType(type); - controller.device->Connect(); InitNewlyAddedController(npad_index); } @@ -874,7 +892,7 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { auto& controller = controller_data[npad_index]; - LOG_ERROR(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected); + LOG_WARNING(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected); for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { // Send an empty vibration to stop any vibrations. VibrateControllerAtIndex(npad_index, device_idx, {}); @@ -889,8 +907,12 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { shared_memory_entry.battery_level_dual = 0; shared_memory_entry.battery_level_left = 0; shared_memory_entry.battery_level_right = 0; - shared_memory_entry.fullkey_color = {}; - shared_memory_entry.joycon_color = {}; + shared_memory_entry.fullkey_color = { + .attribute = ColorAttribute::NoController, + }; + shared_memory_entry.joycon_color = { + .attribute = ColorAttribute::NoController, + }; shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory_entry.footer_type = AppletFooterUiType::None; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 1c6ea6f88..7c534a32f 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -334,10 +334,7 @@ private: }; }; - struct NfcXcdHandle { - INSERT_PADDING_BYTES(0x60); - }; - + // This is nn::hid::system::AppletFooterUiAttributesSet struct AppletFooterUiAttributes { INSERT_PADDING_BYTES(0x4); }; @@ -368,6 +365,31 @@ private: Lagon = 21, }; + // This is nn::hid::NpadLarkType + enum class NpadLarkType : u32 { + Invalid, + H1, + H2, + NL, + NR, + }; + + // This is nn::hid::NpadLuciaType + enum class NpadLuciaType : u32 { + Invalid, + J, + E, + U, + }; + + // This is nn::hid::NpadLagerType + enum class NpadLagerType : u32 { + Invalid, + J, + E, + U, + }; + // This is nn::hid::detail::NpadInternalState struct NpadInternalState { Core::HID::NpadStyleTag style_set; @@ -396,11 +418,16 @@ private: Core::HID::BatteryLevel battery_level_right; AppletFooterUiAttributes footer_attributes; AppletFooterUiType footer_type; - // nfc_states needs to be checked switchbrew doesn't match with HW - NfcXcdHandle nfc_states; - INSERT_PADDING_BYTES(0x18); // Unknown + // GetXcdHandleForNpadWithNfc needs to be checked switchbrew doesn't match with HW + INSERT_PADDING_BYTES(0x78); // Unknown Lifo gc_trigger_lifo; - INSERT_PADDING_BYTES(0xc1f); // Unknown + NpadLarkType lark_type_l; + NpadLarkType lark_type_r; + NpadLuciaType lucia_type; + NpadLagerType lager_type; + INSERT_PADDING_BYTES( + 0x8); // FW 13.x Investigate there is some sort of bitflag related to joycons + INSERT_PADDING_BYTES(0xc08); // Unknown }; static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); -- cgit v1.2.3 From b564f024f0be5023cf13fb2fca953ea6c1feeeb6 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 22 Oct 2021 23:04:06 -0500 Subject: Morph review first wave --- src/core/core.h | 2 +- src/core/frontend/applets/controller.cpp | 5 +-- src/core/hid/emulated_console.cpp | 4 +- src/core/hid/emulated_console.h | 10 ++--- src/core/hid/emulated_controller.cpp | 6 +-- src/core/hid/emulated_controller.h | 22 +++++----- src/core/hid/emulated_devices.cpp | 4 +- src/core/hid/hid_core.cpp | 8 ++-- src/core/hid/hid_types.h | 48 +++++++++++----------- src/core/hid/input_converter.cpp | 12 +++--- .../hle/service/hid/controllers/console_sixaxis.h | 14 +++---- src/core/hle/service/hid/controllers/debug_pad.h | 4 +- src/core/hle/service/hid/controllers/gesture.cpp | 9 ++-- src/core/hle/service/hid/controllers/gesture.h | 33 +++++++-------- src/core/hle/service/hid/controllers/keyboard.h | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 4 +- src/core/hle/service/hid/controllers/npad.h | 22 +++++----- src/core/hle/service/hid/controllers/stubbed.h | 8 ++-- .../hle/service/hid/controllers/touchscreen.cpp | 4 +- src/core/hle/service/hid/controllers/touchscreen.h | 14 ++----- src/core/hle/service/hid/controllers/xpad.h | 6 +-- src/core/hle/service/hid/ring_lifo.h | 10 ++--- 22 files changed, 116 insertions(+), 135 deletions(-) (limited to 'src/core') diff --git a/src/core/core.h b/src/core/core.h index 5a031efb0..645e5c241 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -289,7 +289,7 @@ public: /// Provides a constant reference to the kernel instance. [[nodiscard]] const Kernel::KernelCore& Kernel() const; - /// Gets a mutable reference to the HID interface + /// Gets a mutable reference to the HID interface. [[nodiscard]] HID::HIDCore& HIDCore(); /// Gets an immutable reference to the HID interface. diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 30500ef1e..212ace892 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -13,8 +13,7 @@ namespace Core::Frontend { ControllerApplet::~ControllerApplet() = default; -DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) - : hid_core{hid_core_} {} +DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) : hid_core{hid_core_} {} DefaultControllerApplet::~DefaultControllerApplet() = default; @@ -26,7 +25,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb parameters.enable_single_mode ? 1 : parameters.min_players; // Disconnect Handheld first. - auto* handheld =hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); handheld->Disconnect(); // Deduce the best configuration based on the input parameters. diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 540fd107b..d1d4a5355 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -6,7 +6,7 @@ #include "core/hid/input_converter.h" namespace Core::HID { -EmulatedConsole::EmulatedConsole() {} +EmulatedConsole::EmulatedConsole() = default; EmulatedConsole::~EmulatedConsole() = default; @@ -191,7 +191,7 @@ TouchFingerState EmulatedConsole::GetTouch() const { } void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { - for (const std::pair poller_pair : callback_list) { + for (const auto& poller_pair : callback_list) { const ConsoleUpdateCallback& poller = poller_pair.second; if (poller.on_change) { poller.on_change(type); diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index c48d25794..f26f24f2e 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -20,7 +20,7 @@ namespace Core::HID { struct ConsoleMotionInfo { - Input::MotionStatus raw_status; + Input::MotionStatus raw_status{}; MotionInput emulated{}; }; @@ -34,21 +34,21 @@ using ConsoleMotionValues = ConsoleMotionInfo; using TouchValues = std::array; struct TouchFinger { - u64_le last_touch{}; + u64 last_touch{}; Common::Point position{}; - u32_le id{}; - bool pressed{}; + u32 id{}; TouchAttribute attribute{}; + bool pressed{}; }; // Contains all motion related data that is used on the services struct ConsoleMotion { - bool is_at_rest{}; Common::Vec3f accel{}; Common::Vec3f gyro{}; Common::Vec3f rotation{}; std::array orientation{}; Common::Quaternion quaternion{}; + bool is_at_rest{}; }; using TouchFingerState = std::array; diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index d59758e99..228f80183 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -865,10 +865,10 @@ BatteryLevelState EmulatedController::GetBattery() const { return controller.battery_state; } -void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_service_update) { - for (const std::pair poller_pair : callback_list) { +void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { + for (const auto& poller_pair : callback_list) { const ControllerUpdateCallback& poller = poller_pair.second; - if (!is_service_update && poller.is_service) { + if (!is_npad_service_update && poller.is_npad_service) { continue; } if (poller.on_change) { diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 50f21ccd9..d66768549 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -20,7 +20,7 @@ namespace Core::HID { struct ControllerMotionInfo { - Input::MotionStatus raw_status; + Input::MotionStatus raw_status{}; MotionInput emulated{}; }; @@ -51,28 +51,28 @@ using BatteryValues = std::array; using VibrationValues = std::array; struct AnalogSticks { - AnalogStickState left; - AnalogStickState right; + AnalogStickState left{}; + AnalogStickState right{}; }; struct ControllerColors { - NpadControllerColor fullkey; - NpadControllerColor left; - NpadControllerColor right; + NpadControllerColor fullkey{}; + NpadControllerColor left{}; + NpadControllerColor right{}; }; struct BatteryLevelState { - NpadPowerInfo dual; - NpadPowerInfo left; - NpadPowerInfo right; + NpadPowerInfo dual{}; + NpadPowerInfo left{}; + NpadPowerInfo right{}; }; struct ControllerMotion { - bool is_at_rest; Common::Vec3f accel{}; Common::Vec3f gyro{}; Common::Vec3f rotation{}; std::array orientation{}; + bool is_at_rest{}; }; using MotionState = std::array; @@ -113,7 +113,7 @@ enum class ControllerTriggerType { struct ControllerUpdateCallback { std::function on_change; - bool is_service; + bool is_npad_service; }; class EmulatedController { diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 54a753d8a..1c4065cd8 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -9,7 +9,7 @@ namespace Core::HID { -EmulatedDevices::EmulatedDevices() {} +EmulatedDevices::EmulatedDevices() = default; EmulatedDevices::~EmulatedDevices() = default; @@ -332,7 +332,7 @@ MousePosition EmulatedDevices::GetMousePosition() const { } void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { - for (const std::pair poller_pair : callback_list) { + for (const auto& poller_pair : callback_list) { const InterfaceUpdateCallback& poller = poller_pair.second; if (poller.on_change) { poller.on_change(type); diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index cc1b3c295..3cb26e1e7 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -113,8 +113,8 @@ NpadStyleTag HIDCore::GetSupportedStyleTag() const { s8 HIDCore::GetPlayerCount() const { s8 active_players = 0; - for (std::size_t player_index = 0; player_index < available_controllers -2; player_index++) { - const auto* controller = GetEmulatedControllerByIndex(player_index); + for (std::size_t player_index = 0; player_index < available_controllers - 2; ++player_index) { + const auto* const controller = GetEmulatedControllerByIndex(player_index); if (controller->IsConnected()) { active_players++; } @@ -123,8 +123,8 @@ s8 HIDCore::GetPlayerCount() const { } NpadIdType HIDCore::GetFirstNpadId() const { - for (std::size_t player_index = 0; player_index < available_controllers; player_index++) { - const auto* controller = GetEmulatedControllerByIndex(player_index); + for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) { + const auto* const controller = GetEmulatedControllerByIndex(player_index); if (controller->IsConnected()) { return controller->GetNpadIdType(); } diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 539436283..59ec593b8 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -100,7 +100,7 @@ enum class NpadType : u8 { // This is nn::hid::NpadStyleTag struct NpadStyleTag { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> fullkey; BitField<1, 1, u32> handheld; @@ -132,35 +132,35 @@ static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size" // This is nn::hid::TouchState struct TouchState { - u64_le delta_time; + u64 delta_time; TouchAttribute attribute; - u32_le finger; - Common::Point position; - u32_le diameter_x; - u32_le diameter_y; - u32_le rotation_angle; + u32 finger; + Common::Point position; + u32 diameter_x; + u32 diameter_y; + u32 rotation_angle; }; static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); // This is nn::hid::NpadControllerColor struct NpadControllerColor { - u32_le body; - u32_le button; + u32 body; + u32 button; }; static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); // This is nn::hid::AnalogStickState struct AnalogStickState { - s32_le x; - s32_le y; + s32 x; + s32 y; }; static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); // This is nn::hid::server::NpadGcTriggerState struct NpadGcTriggerState { - s64_le sampling_number{}; - s32_le left{}; - s32_le right{}; + s64 sampling_number{}; + s32 left{}; + s32 right{}; }; static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); @@ -286,7 +286,7 @@ static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect siz // This is nn::hid::DebugPadButton struct DebugPadButton { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> a; BitField<1, 1, u32> b; BitField<2, 1, u32> x; @@ -345,7 +345,7 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor // This is nn::hid::KeyboardModifier struct KeyboardModifier { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> control; BitField<1, 1, u32> shift; BitField<2, 1, u32> left_alt; @@ -383,7 +383,7 @@ static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size"); // This is nn::hid::MouseAttribute struct MouseAttribute { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> transferable; BitField<1, 1, u32> is_connected; }; @@ -392,13 +392,13 @@ static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size" // This is nn::hid::detail::MouseState struct MouseState { - s64_le sampling_number; - s32_le x; - s32_le y; - s32_le delta_x; - s32_le delta_y; - s32_le delta_wheel_x; - s32_le delta_wheel_y; + s64 sampling_number; + s32 x; + s32 y; + s32 delta_x; + s32 delta_y; + s32 delta_wheel_x; + s32 delta_wheel_y; MouseButton button; MouseAttribute attribute; }; diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 128a48ec9..b3c8913ce 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -142,8 +142,8 @@ Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) { } SanitizeStick(status.x, status.y, true); - const Input::AnalogProperties& properties_x = status.x.properties; - const Input::AnalogProperties& properties_y = status.y.properties; + const auto& properties_x = status.x.properties; + const auto& properties_y = status.y.properties; const float x = status.x.value; const float y = status.y.value; @@ -213,7 +213,7 @@ Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) { } SanitizeAnalog(status.analog, true); - const Input::AnalogProperties& properties = status.analog.properties; + const auto& properties = status.analog.properties; float& value = status.analog.value; // Set button status @@ -231,7 +231,7 @@ Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) { } void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) { - const Input::AnalogProperties& properties = analog.properties; + const auto& properties = analog.properties; float& raw_value = analog.raw_value; float& value = analog.value; @@ -271,8 +271,8 @@ void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) { } void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value) { - const Input::AnalogProperties& properties_x = analog_x.properties; - const Input::AnalogProperties& properties_y = analog_y.properties; + const auto& properties_x = analog_x.properties; + const auto& properties_y = analog_y.properties; float& raw_x = analog_x.raw_value; float& raw_y = analog_y.raw_value; float& x = analog_x.value; diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index 6d18d2ce0..95729e6b2 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -35,8 +35,8 @@ public: private: struct SevenSixAxisState { INSERT_PADDING_WORDS(4); // unused - s64_le sampling_number{}; - s64_le sampling_number2{}; + s64 sampling_number{}; + s64 sampling_number2{}; u64 unknown{}; Common::Vec3f accel{}; Common::Vec3f gyro{}; @@ -45,10 +45,10 @@ private: static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size"); struct CommonHeader { - s64_le timestamp; - s64_le total_entry_count; - s64_le last_entry_index; - s64_le entry_count; + s64 timestamp; + s64 total_entry_count; + s64 last_entry_index; + s64 entry_count; }; static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); @@ -61,7 +61,7 @@ private: // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat struct ConsoleSharedMemory { - u64_le sampling_number{}; + u64 sampling_number{}; bool is_seven_six_axis_sensor_at_rest{}; f32 verticalization_error{}; Common::Vec3f gyro_bias{}; diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 11b6c669b..bd0f15eaa 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -38,7 +38,7 @@ private: // This is nn::hid::DebugPadAttribute struct DebugPadAttribute { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> connected; }; }; @@ -46,7 +46,7 @@ private: // This is nn::hid::DebugPadState struct DebugPadState { - s64_le sampling_number; + s64 sampling_number; DebugPadAttribute attribute; Core::HID::DebugPadButton pad_state; Core::HID::AnalogStickState r_stick; diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index a82d04b3b..7a7bc68a2 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -65,10 +65,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u void Controller_Gesture::ReadTouchInput() { const auto touch_status = console->GetTouch(); for (std::size_t id = 0; id < fingers.size(); ++id) { - const Core::HID::TouchFinger& status = touch_status[id]; - Finger& finger = fingers[id]; - finger.pos = status.position; - finger.pressed = status.pressed; + fingers[id] = touch_status[id]; } } @@ -315,14 +312,14 @@ const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry( Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { GestureProperties gesture; - std::array active_fingers; + std::array active_fingers; const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), [](const auto& finger) { return finger.pressed; }); gesture.active_points = static_cast(std::distance(active_fingers.begin(), end_iter)); for (size_t id = 0; id < gesture.active_points; ++id) { - const auto& [active_x, active_y] = active_fingers[id].pos; + const auto& [active_x, active_y] = active_fingers[id].position; gesture.points[id] = { .x = static_cast(active_x * Layout::ScreenUndocked::Width), .y = static_cast(active_y * Layout::ScreenUndocked::Height), diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 6f5abaa4f..58139a5cf 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -60,7 +60,7 @@ private: // This is nn::hid::GestureAttribute struct GestureAttribute { union { - u32_le raw{}; + u32 raw{}; BitField<4, 1, u32> is_new_touch; BitField<8, 1, u32> is_double_tap; @@ -70,33 +70,28 @@ private: // This is nn::hid::GestureState struct GestureState { - s64_le sampling_number; - s64_le detection_count; + s64 sampling_number; + s64 detection_count; GestureType type; GestureDirection direction; - Common::Point pos; - Common::Point delta; + Common::Point pos; + Common::Point delta; f32 vel_x; f32 vel_y; GestureAttribute attributes; f32 scale; f32 rotation_angle; - s32_le point_count; - std::array, 4> points; + s32 point_count; + std::array, 4> points; }; static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); - struct Finger { - Common::Point pos{}; - bool pressed{}; - }; - struct GestureProperties { - std::array, MAX_POINTS> points{}; + std::array, MAX_POINTS> points{}; std::size_t active_points{}; - Common::Point mid_point{}; - s64_le detection_count{}; - u64_le delta_time{}; + Common::Point mid_point{}; + s64 detection_count{}; + u64 delta_time{}; f32 average_distance{}; f32 angle{}; }; @@ -150,10 +145,10 @@ private: Core::HID::EmulatedConsole* console; - std::array fingers{}; + std::array fingers{}; GestureProperties last_gesture{}; - s64_le last_update_timestamp{}; - s64_le last_tap_timestamp{}; + s64 last_update_timestamp{}; + s64 last_tap_timestamp{}; f32 last_pan_time_difference{}; bool force_update{false}; bool enable_press_and_tap{false}; diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 6919e092a..aba4f123e 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -37,7 +37,7 @@ public: private: // This is nn::hid::detail::KeyboardState struct KeyboardState { - s64_le sampling_number; + s64 sampling_number; Core::HID::KeyboardModifier modifier; Core::HID::KeyboardKey key; }; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index aad298364..7bf31f63a 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -106,7 +106,7 @@ Controller_NPad::Controller_NPad(Core::System& system_, Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, - .is_service = true, + .is_npad_service = true, }; controller.callback_key = controller.device->SetCallback(engine_callback); } @@ -157,7 +157,6 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { auto& controller = controller_data[controller_idx]; - LOG_WARNING(Service_HID, "Connect {} {}", controller_idx, controller.is_connected); const auto controller_type = controller.device->GetNpadType(); auto& shared_memory = controller.shared_memory_entry; if (controller_type == Core::HID::NpadType::None) { @@ -892,7 +891,6 @@ void Controller_NPad::DisconnectNpad(u32 npad_id) { void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { auto& controller = controller_data[npad_index]; - LOG_WARNING(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected); for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { // Send an empty vibration to stop any vibrations. VibrateControllerAtIndex(npad_index, device_idx, {}); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 7c534a32f..0a2dc6992 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -195,7 +195,7 @@ public: private: // This is nn::hid::detail::ColorAttribute - enum class ColorAttribute : u32_le { + enum class ColorAttribute : u32 { Ok = 0, ReadError = 1, NoController = 2, @@ -220,7 +220,7 @@ private: // This is nn::hid::NpadAttribute struct NpadAttribute { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> is_connected; BitField<1, 1, u32> is_wired; BitField<2, 1, u32> is_left_connected; @@ -251,7 +251,7 @@ private: // This is nn::hid::SixAxisSensorAttribute struct SixAxisSensorAttribute { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> is_connected; BitField<1, 1, u32> is_interpolated; }; @@ -260,8 +260,8 @@ private: // This is nn::hid::SixAxisSensorState struct SixAxisSensorState { - s64_le delta_time{}; - s64_le sampling_number{}; + s64 delta_time{}; + s64 sampling_number{}; Common::Vec3f accel{}; Common::Vec3f gyro{}; Common::Vec3f rotation{}; @@ -273,16 +273,16 @@ private: // This is nn::hid::server::NpadGcTriggerState struct NpadGcTriggerState { - s64_le sampling_number{}; - s32_le l_analog{}; - s32_le r_analog{}; + s64 sampling_number{}; + s32 l_analog{}; + s32 r_analog{}; }; static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); // This is nn::hid::NpadSystemProperties struct NPadSystemProperties { union { - s64_le raw{}; + s64 raw{}; BitField<0, 1, s64> is_charging_joy_dual; BitField<1, 1, s64> is_charging_joy_left; BitField<2, 1, s64> is_charging_joy_right; @@ -303,7 +303,7 @@ private: // This is nn::hid::NpadSystemButtonProperties struct NpadSystemButtonProperties { union { - s32_le raw{}; + s32 raw{}; BitField<0, 1, s32> is_home_button_protection_enabled; }; }; @@ -313,7 +313,7 @@ private: // This is nn::hid::system::DeviceType struct DeviceType { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, s32> fullkey; BitField<1, 1, s32> debug_pad; BitField<2, 1, s32> handheld_left; diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index 29f95a100..10aecad4c 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -26,10 +26,10 @@ public: private: struct CommonHeader { - s64_le timestamp; - s64_le total_entry_count; - s64_le last_entry_index; - s64_le entry_count; + s64 timestamp; + s64 total_entry_count; + s64 last_entry_index; + s64 entry_count; }; static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index e0a44d06b..5ba8d96a8 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -66,7 +66,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin } } - std::array active_fingers; + std::array active_fingers; const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), [](const auto& finger) { return finger.pressed; }); const auto active_fingers_count = @@ -76,7 +76,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; - next_state.entry_count = static_cast(active_fingers_count); + next_state.entry_count = static_cast(active_fingers_count); for (std::size_t id = 0; id < MAX_FINGERS; ++id) { auto& touch_entry = next_state.states[id]; diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index bcf79237d..fa4dfa1a2 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -50,27 +50,19 @@ private: // This is nn::hid::TouchScreenState struct TouchScreenState { - s64_le sampling_number; - s32_le entry_count; + s64 sampling_number; + s32 entry_count; INSERT_PADDING_BYTES(4); // Reserved std::array states; }; static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); - struct Finger { - u64_le last_touch{}; - Common::Point position; - u32_le id{}; - bool pressed{}; - Core::HID::TouchAttribute attribute; - }; - // This is nn::hid::detail::TouchScreenLifo Lifo touch_screen_lifo{}; static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); TouchScreenState next_state{}; - std::array fingers; + std::array fingers; Core::HID::EmulatedConsole* console; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index a5421f93b..75e0d2911 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -31,7 +31,7 @@ private: // This is nn::hid::BasicXpadAttributeSet struct BasicXpadAttributeSet { union { - u32_le raw{}; + u32 raw{}; BitField<0, 1, u32> is_connected; BitField<1, 1, u32> is_wired; BitField<2, 1, u32> is_left_connected; @@ -45,7 +45,7 @@ private: // This is nn::hid::BasicXpadButtonSet struct BasicXpadButtonSet { union { - u32_le raw{}; + u32 raw{}; // Button states BitField<0, 1, u32> a; BitField<1, 1, u32> b; @@ -93,7 +93,7 @@ private: // This is nn::hid::detail::BasicXpadState struct BasicXpadState { - s64_le sampling_number; + s64 sampling_number; BasicXpadAttributeSet attributes; BasicXpadButtonSet pad_states; Core::HID::AnalogStickState l_stick; diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h index 1cc2a194f..f68d82762 100644 --- a/src/core/hle/service/hid/ring_lifo.h +++ b/src/core/hle/service/hid/ring_lifo.h @@ -12,16 +12,16 @@ constexpr std::size_t max_entry_size = 17; template struct AtomicStorage { - s64_le sampling_number; + s64 sampling_number; State state; }; template struct Lifo { - s64_le timestamp{}; - s64_le total_entry_count = max_entry_size; - s64_le last_entry_index{}; - s64_le entry_count{}; + s64 timestamp{}; + s64 total_entry_count = max_entry_size; + s64 last_entry_index{}; + s64 entry_count{}; std::array, max_entry_size> entries{}; const AtomicStorage& ReadCurrentEntry() const { -- cgit v1.2.3 From 464c4d26ac8e7af6302390684445b357e5cda4e4 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 11:22:20 -0500 Subject: settings: Fix mouse and keyboard mappings --- src/core/hid/emulated_controller.cpp | 8 ++++---- src/core/hid/emulated_devices.cpp | 19 ++++++++++++------- src/core/hid/emulated_devices.h | 3 +++ 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 228f80183..bd0b89c05 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -246,7 +246,7 @@ std::vector EmulatedController::GetMappedDevices() const { devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { return param.Get("engine", "") == param_.Get("engine", "") && param.Get("guid", "") == param_.Get("guid", "") && - param.Get("port", "") == param_.Get("port", ""); + param.Get("port", 0) == param_.Get("port", 0); }); if (devices_it != devices.end()) { continue; @@ -254,7 +254,7 @@ std::vector EmulatedController::GetMappedDevices() const { Common::ParamPackage device{}; device.Set("engine", param.Get("engine", "")); device.Set("guid", param.Get("guid", "")); - device.Set("port", param.Get("port", "")); + device.Set("port", param.Get("port", 0)); devices.push_back(device); } @@ -269,7 +269,7 @@ std::vector EmulatedController::GetMappedDevices() const { devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { return param.Get("engine", "") == param_.Get("engine", "") && param.Get("guid", "") == param_.Get("guid", "") && - param.Get("port", "") == param_.Get("port", ""); + param.Get("port", 0) == param_.Get("port", 0); }); if (devices_it != devices.end()) { continue; @@ -277,7 +277,7 @@ std::vector EmulatedController::GetMappedDevices() const { Common::ParamPackage device{}; device.Set("engine", param.Get("engine", "")); device.Set("guid", param.Get("guid", "")); - device.Set("port", param.Get("port", "")); + device.Set("port", param.Get("port", 0)); devices.push_back(device); } return devices; diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 1c4065cd8..5afd83f62 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -162,17 +162,22 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz return; } - // TODO(german77): Do this properly - // switch (index) { - // case Settings::NativeKeyboard::A: - // interface_status.keyboard_state.a.Assign(current_status.value); - // break; - // .... - // } + UpdateKey(index, current_status.value); TriggerOnChange(DeviceTriggerType::Keyboard); } +void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { + constexpr u8 KEYS_PER_BYTE = 8; + auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE]; + const u8 mask = 1 << (key_index % KEYS_PER_BYTE); + if (status) { + entry = entry | mask; + } else { + entry = entry & ~mask; + } +} + void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) { if (index >= device_status.keyboard_moddifier_values.size()) { return; diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index c6c19fae4..7ed95eac6 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -143,6 +143,9 @@ public: void DeleteCallback(int key); private: + /// Helps assigning a value to keyboard_state + void UpdateKey(std::size_t key_index, bool status); + /** * Updates the touch status of the console * @param callback: A CallbackStatus containing the key status -- cgit v1.2.3 From f01dac3bf934657059b77bae3630201110f83e3d Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 20:27:00 -0500 Subject: service/hid: Fix memory allocated incorrectly --- src/core/hle/service/hid/controllers/debug_pad.cpp | 6 +++--- src/core/hle/service/hid/controllers/gesture.cpp | 2 +- src/core/hle/service/hid/controllers/keyboard.cpp | 2 +- src/core/hle/service/hid/controllers/mouse.cpp | 2 +- src/core/hle/service/hid/controllers/xpad.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index b2b4edf51..5b1946f13 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -12,7 +12,7 @@ #include "core/hle/service/hid/controllers/debug_pad.h" namespace Service::HID { - +constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; constexpr s32 HID_JOYSTICK_MAX = 0x7fff; [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; @@ -32,7 +32,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, if (!IsControllerActivated()) { debug_pad_lifo.entry_count = 0; debug_pad_lifo.last_entry_index = 0; - std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo)); return; } @@ -51,7 +51,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, } debug_pad_lifo.WriteNextEntry(next_state); - std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo)); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 7a7bc68a2..47760b4f8 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -43,7 +43,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u if (!IsControllerActivated()) { gesture_lifo.entry_count = 0; gesture_lifo.last_entry_index = 0; - std::memcpy(data, &gesture_lifo, sizeof(gesture_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index db0f56b92..632679a17 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -29,7 +29,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, if (!IsControllerActivated()) { keyboard_lifo.entry_count = 0; keyboard_lifo.last_entry_index = 0; - std::memcpy(data, &keyboard_lifo, sizeof(keyboard_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 2f607bfe9..6d3bd0a2b 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -29,7 +29,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { mouse_lifo.entry_count = 0; mouse_lifo.last_entry_index = 0; - std::memcpy(data, &mouse_lifo, sizeof(mouse_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index 29a412ff9..aa9f044f1 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -22,7 +22,7 @@ void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (!IsControllerActivated()) { basic_xpad_lifo.entry_count = 0; basic_xpad_lifo.last_entry_index = 0; - std::memcpy(data, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); + std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); return; } -- cgit v1.2.3 From c6c32daf40ae1c720f0a2897c538bb1117371ea5 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 20:28:54 -0500 Subject: input_common: Add manual update options to input devices --- src/core/hid/emulated_controller.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index bd0b89c05..48add394b 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -122,6 +122,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback button_callback{ [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; button_devices[index]->SetCallback(button_callback); + button_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < stick_devices.size(); ++index) { @@ -131,6 +132,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback stick_callback{ [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; stick_devices[index]->SetCallback(stick_callback); + stick_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < trigger_devices.size(); ++index) { @@ -140,6 +142,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback trigger_callback{ [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }}; trigger_devices[index]->SetCallback(trigger_callback); + trigger_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < battery_devices.size(); ++index) { @@ -149,6 +152,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback battery_callback{ [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }}; battery_devices[index]->SetCallback(battery_callback); + battery_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < motion_devices.size(); ++index) { @@ -158,6 +162,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback motion_callback{ [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; motion_devices[index]->SetCallback(motion_callback); + motion_devices[index]->ForceUpdate(); } } @@ -843,6 +848,10 @@ AnalogSticks EmulatedController::GetSticks() const { if (is_configuring) { return {}; } + // Some drivers like stick from buttons need constant refreshing + for (auto& device : stick_devices) { + device->SoftUpdate(); + } return controller.analog_stick_state; } -- cgit v1.2.3 From 064ddacf49aa7155e26add55983b81fdda997077 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 23:23:54 -0500 Subject: core/hid: Rework battery mappings --- src/core/hid/emulated_controller.cpp | 50 ++++++++++++++++----------- src/core/hid/emulated_controller.h | 28 ++++++++++----- src/core/hid/emulated_devices.cpp | 2 +- src/core/hid/input_converter.cpp | 4 +++ src/core/hle/service/hid/controllers/npad.cpp | 11 ++++-- 5 files changed, 63 insertions(+), 32 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 48add394b..83ced5635 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -87,11 +87,23 @@ void EmulatedController::ReloadFromSettings() { ReloadInput(); } +void EmulatedController::LoadDevices() { + const auto left_joycon = button_params[Settings::NativeButton::ZL]; + const auto right_joycon = button_params[Settings::NativeButton::ZR]; -void EmulatedController::ReloadInput() { - // If you load any device here add the equivalent to the UnloadInput() function - const auto left_side = button_params[Settings::NativeButton::ZL]; - const auto right_side = button_params[Settings::NativeButton::ZR]; + // Triggers for GC controllers + trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; + trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; + + battery_params[LeftIndex] = left_joycon; + battery_params[RightIndex] = right_joycon; + battery_params[LeftIndex].Set("battery", true); + battery_params[RightIndex].Set("battery", true); + + output_params[LeftIndex] = left_joycon; + output_params[RightIndex] = right_joycon; + output_params[LeftIndex].Set("output", true); + output_params[RightIndex].Set("output", true); std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, button_params.begin() + Settings::NativeButton::BUTTON_NS_END, @@ -102,19 +114,17 @@ void EmulatedController::ReloadInput() { std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, motion_devices.begin(), Input::CreateDevice); + std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), + Input::CreateDevice); + std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(), + Input::CreateDevice); + std::transform(output_params.begin(), output_params.end(), output_devices.begin(), + Input::CreateDevice); +} - trigger_devices[0] = - Input::CreateDevice(button_params[Settings::NativeButton::ZL]); - trigger_devices[1] = - Input::CreateDevice(button_params[Settings::NativeButton::ZR]); - - battery_devices[0] = Input::CreateDevice(left_side); - battery_devices[1] = Input::CreateDevice(right_side); - - button_params[Settings::NativeButton::ZL].Set("output", true); - output_devices[0] = - Input::CreateDevice(button_params[Settings::NativeButton::ZL]); - +void EmulatedController::ReloadInput() { + // If you load any device here add the equivalent to the UnloadInput() function + LoadDevices(); for (std::size_t index = 0; index < button_devices.size(); ++index) { if (!button_devices[index]) { continue; @@ -241,7 +251,7 @@ void EmulatedController::RestoreConfig() { ReloadFromSettings(); } -std::vector EmulatedController::GetMappedDevices() const { +std::vector EmulatedController::GetMappedDevices(DeviceIndex device_index) const { std::vector devices; for (const auto& param : button_params) { if (!param.Has("engine")) { @@ -612,21 +622,21 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t } switch (index) { - case 0: + case LeftIndex: controller.battery_state.left = { .is_powered = is_powered, .is_charging = is_charging, .battery_level = battery_level, }; break; - case 1: + case RightIndex: controller.battery_state.right = { .is_powered = is_powered, .is_charging = is_charging, .battery_level = battery_level, }; break; - case 2: + case DualIndex: controller.battery_state.dual = { .is_powered = is_powered, .is_charging = is_charging, diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index d66768549..eb705a241 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -18,7 +18,7 @@ #include "core/hid/motion_input.h" namespace Core::HID { - +const std::size_t max_emulated_controllers = 2; struct ControllerMotionInfo { Input::MotionStatus raw_status{}; MotionInput emulated{}; @@ -32,23 +32,23 @@ using ControllerMotionDevices = std::array, Settings::NativeMotion::NumMotions>; using TriggerDevices = std::array, Settings::NativeTrigger::NumTriggers>; -using BatteryDevices = std::array, 2>; -using OutputDevices = std::array, 2>; +using BatteryDevices = std::array, max_emulated_controllers>; +using OutputDevices = std::array, max_emulated_controllers>; using ButtonParams = std::array; using StickParams = std::array; using ControllerMotionParams = std::array; using TriggerParams = std::array; -using BatteryParams = std::array; -using OutputParams = std::array; +using BatteryParams = std::array; +using OutputParams = std::array; using ButtonValues = std::array; using SticksValues = std::array; using TriggerValues = std::array; using ControllerMotionValues = std::array; -using ColorValues = std::array; -using BatteryValues = std::array; -using VibrationValues = std::array; +using ColorValues = std::array; +using BatteryValues = std::array; +using VibrationValues = std::array; struct AnalogSticks { AnalogStickState left{}; @@ -75,6 +75,13 @@ struct ControllerMotion { bool is_at_rest{}; }; +enum DeviceIndex : u8 { + LeftIndex, + RightIndex, + DualIndex, + AllDevices, +}; + using MotionState = std::array; struct ControllerStatus { @@ -189,7 +196,7 @@ public: void RestoreConfig(); /// Returns a vector of mapped devices from the mapped button and stick parameters - std::vector GetMappedDevices() const; + std::vector GetMappedDevices(DeviceIndex device_index) const; // Returns the current mapped button device Common::ParamPackage GetButtonParam(std::size_t index) const; @@ -289,6 +296,9 @@ public: void DeleteCallback(int key); private: + /// creates input devices from params + void LoadDevices(); + /** * Updates the button status of the controller * @param callback: A CallbackStatus containing the button status diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 5afd83f62..eb59c310c 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -174,7 +174,7 @@ void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { if (status) { entry = entry | mask; } else { - entry = entry & ~mask; + entry = static_cast(entry & ~mask); } } diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index b3c8913ce..e2598f367 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -33,6 +33,10 @@ Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) { } break; } + case Input::InputType::Button: + battery = callback.button_status.value ? Input::BatteryLevel::Charging + : Input::BatteryLevel::Critical; + break; case Input::InputType::Battery: battery = callback.battery_status; break; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 7bf31f63a..9f84e20c2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -101,8 +101,9 @@ Controller_NPad::Controller_NPad(Core::System& system_, for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; controller.device = system.HIDCore().GetEmulatedControllerByIndex(i); - controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE; - controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE; + controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE; + controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value = + DEFAULT_VIBRATION_VALUE; Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, @@ -285,9 +286,12 @@ void Controller_NPad::OnInit() { auto& npad = controller.shared_memory_entry; npad.fullkey_color = { .attribute = ColorAttribute::NoController, + .fullkey = {}, }; npad.joycon_color = { .attribute = ColorAttribute::NoController, + .left = {}, + .right = {}, }; // HW seems to initialize the first 19 entries for (std::size_t i = 0; i < 19; ++i) { @@ -907,9 +911,12 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { shared_memory_entry.battery_level_right = 0; shared_memory_entry.fullkey_color = { .attribute = ColorAttribute::NoController, + .fullkey = {}, }; shared_memory_entry.joycon_color = { .attribute = ColorAttribute::NoController, + .left = {}, + .right = {}, }; shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory_entry.footer_type = AppletFooterUiType::None; -- cgit v1.2.3 From 7348e205d94e2fff777781498a2ef7931163703a Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 26 Oct 2021 23:37:46 -0500 Subject: input_common: Add multiple vibration curves --- src/core/hid/emulated_controller.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 83ced5635..916368c68 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -251,7 +251,8 @@ void EmulatedController::RestoreConfig() { ReloadFromSettings(); } -std::vector EmulatedController::GetMappedDevices(DeviceIndex device_index) const { +std::vector EmulatedController::GetMappedDevices( + DeviceIndex device_index) const { std::vector devices; for (const auto& param : button_params) { if (!param.Has("engine")) { @@ -658,6 +659,10 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v const auto& player = Settings::values.players.GetValue()[player_index]; const f32 strength = static_cast(player.vibration_strength) / 100.0f; + if (!player.vibration_enabled) { + return false; + } + // Exponential amplification is too strong at low amplitudes. Switch to a linear // amplification if strength is set below 0.7f const Input::VibrationAmplificationType type = @@ -860,6 +865,9 @@ AnalogSticks EmulatedController::GetSticks() const { } // Some drivers like stick from buttons need constant refreshing for (auto& device : stick_devices) { + if (!device) { + continue; + } device->SoftUpdate(); } return controller.analog_stick_state; -- cgit v1.2.3 From c085e54316c5520ed7d58a92a7faa9e896bb6c71 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 27 Oct 2021 00:20:28 -0500 Subject: core/hid: Add TAS input --- src/core/hid/emulated_controller.cpp | 72 ++++++++++++++++++++++++++++++++++++ src/core/hid/emulated_controller.h | 9 +++++ 2 files changed, 81 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 916368c68..2b051ccaf 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -105,6 +105,8 @@ void EmulatedController::LoadDevices() { output_params[LeftIndex].Set("output", true); output_params[RightIndex].Set("output", true); + LoadTASParams(); + std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, button_params.begin() + Settings::NativeButton::BUTTON_NS_END, button_devices.begin(), Input::CreateDevice); @@ -120,6 +122,51 @@ void EmulatedController::LoadDevices() { Input::CreateDevice); std::transform(output_params.begin(), output_params.end(), output_devices.begin(), Input::CreateDevice); + + // Initialize TAS devices + std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), + Input::CreateDevice); + std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(), + Input::CreateDevice); +} + +void EmulatedController::LoadTASParams() { + const auto player_index = NpadIdTypeToIndex(npad_id_type); + Common::ParamPackage common_params{}; + common_params.Set("engine", "tas"); + common_params.Set("pad", static_cast(player_index)); + for (auto& param : tas_button_params) { + param = common_params; + } + for (auto& param : tas_stick_params) { + param = common_params; + } + + tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); + tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); + tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); + tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3); + tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4); + tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5); + tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6); + tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7); + tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8); + tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9); + tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10); + tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11); + tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12); + tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13); + tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14); + tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15); + tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16); + tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17); + tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18); + tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19); + + tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); + tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); + tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); + tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); } void EmulatedController::ReloadInput() { @@ -174,6 +221,25 @@ void EmulatedController::ReloadInput() { motion_devices[index]->SetCallback(motion_callback); motion_devices[index]->ForceUpdate(); } + + // Register TAS devices. No need to force update + for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { + if (!tas_button_devices[index]) { + continue; + } + Input::InputCallback button_callback{ + [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + tas_button_devices[index]->SetCallback(button_callback); + } + + for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) { + if (!tas_stick_devices[index]) { + continue; + } + Input::InputCallback stick_callback{ + [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + tas_stick_devices[index]->SetCallback(stick_callback); + } } void EmulatedController::UnloadInput() { @@ -195,6 +261,12 @@ void EmulatedController::UnloadInput() { for (auto& output : output_devices) { output.reset(); } + for (auto& button : tas_button_devices) { + button.reset(); + } + for (auto& stick : tas_stick_devices) { + stick.reset(); + } } void EmulatedController::EnableConfiguration() { diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index eb705a241..eec51e34a 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -299,6 +299,9 @@ private: /// creates input devices from params void LoadDevices(); + /// Set the params for TAS devices + void LoadTASParams(); + /** * Updates the button status of the controller * @param callback: A CallbackStatus containing the button status @@ -363,6 +366,12 @@ private: BatteryDevices battery_devices; OutputDevices output_devices; + // TAS related variables + ButtonParams tas_button_params; + StickParams tas_stick_params; + ButtonDevices tas_button_devices; + StickDevices tas_stick_devices; + mutable std::mutex mutex; std::unordered_map callback_list; int last_callback_key = 0; -- cgit v1.2.3 From 2d3a63b28969089746e43ed232dc74630fbfc3b2 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 27 Oct 2021 18:06:13 -0500 Subject: core/hid: Update structs to 13.1.0 --- src/core/hid/hid_types.h | 10 ++++ src/core/hid/input_interpreter.cpp | 14 ++--- src/core/hid/input_interpreter.h | 2 +- src/core/hle/service/hid/controllers/debug_pad.cpp | 4 +- src/core/hle/service/hid/controllers/gesture.cpp | 8 +-- src/core/hle/service/hid/controllers/keyboard.cpp | 4 +- src/core/hle/service/hid/controllers/mouse.cpp | 6 +-- src/core/hle/service/hid/controllers/npad.cpp | 15 +++--- src/core/hle/service/hid/controllers/npad.h | 60 +++++++++++++++++++--- .../hle/service/hid/controllers/touchscreen.cpp | 4 +- src/core/hle/service/hid/controllers/xpad.cpp | 4 +- src/core/hle/service/hid/ring_lifo.h | 26 +++++----- 12 files changed, 107 insertions(+), 50 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 59ec593b8..f8a0d5edd 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -231,7 +231,12 @@ enum class NpadButton : u64 { RightSR = 1U << 27, Palma = 1U << 28, + Verification = 1U << 29, HandheldLeftB = 1U << 30, + LagonCLeft = 1U << 31, + LagonCUp = 1ULL << 32, + LagonCRight = 1ULL << 33, + LagonCDown = 1ULL << 34, }; DECLARE_ENUM_FLAG_OPERATORS(NpadButton); @@ -278,7 +283,12 @@ struct NpadButtonState { BitField<27, 1, u64> right_sr; BitField<28, 1, u64> palma; + BitField<29, 1, u64> verification; BitField<30, 1, u64> handheld_left_b; + BitField<31, 1, u64> lagon_c_left; + BitField<32, 1, u64> lagon_c_up; + BitField<33, 1, u64> lagon_c_right; + BitField<34, 1, u64> lagon_c_down; }; }; static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size."); diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp index 7e7c1816f..870422d82 100644 --- a/src/core/hid/input_interpreter.cpp +++ b/src/core/hid/input_interpreter.cpp @@ -20,7 +20,7 @@ InputInterpreter::InputInterpreter(Core::System& system) InputInterpreter::~InputInterpreter() = default; void InputInterpreter::PollInput() { - const u32 button_state = npad.GetAndResetPressState(); + const u64 button_state = npad.GetAndResetPressState(); previous_index = current_index; current_index = (current_index + 1) % button_states.size(); @@ -32,7 +32,7 @@ void InputInterpreter::ResetButtonStates() { previous_index = 0; current_index = 0; - button_states[0] = 0xFFFFFFFF; + button_states[0] = 0xFFFFFFFFFFFFFFFF; for (std::size_t i = 1; i < button_states.size(); ++i) { button_states[i] = 0; @@ -40,22 +40,22 @@ void InputInterpreter::ResetButtonStates() { } bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { - return (button_states[current_index] & static_cast(button)) != 0; + return (button_states[current_index] & static_cast(button)) != 0; } bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { - const bool current_press = (button_states[current_index] & static_cast(button)) != 0; - const bool previous_press = (button_states[previous_index] & static_cast(button)) != 0; + const bool current_press = (button_states[current_index] & static_cast(button)) != 0; + const bool previous_press = (button_states[previous_index] & static_cast(button)) != 0; return current_press && !previous_press; } bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { - u32 held_buttons{button_states[0]}; + u64 held_buttons{button_states[0]}; for (std::size_t i = 1; i < button_states.size(); ++i) { held_buttons &= button_states[i]; } - return (held_buttons & static_cast(button)) != 0; + return (held_buttons & static_cast(button)) != 0; } diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h index 1791cf9b7..1c2e02142 100644 --- a/src/core/hid/input_interpreter.h +++ b/src/core/hid/input_interpreter.h @@ -105,7 +105,7 @@ private: Service::HID::Controller_NPad& npad; /// Stores 9 consecutive button states polled from HID. - std::array button_states{}; + std::array button_states{}; std::size_t previous_index{}; std::size_t current_index{}; diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 5b1946f13..345134357 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -30,8 +30,8 @@ void Controller_DebugPad::OnRelease() {} void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { if (!IsControllerActivated()) { - debug_pad_lifo.entry_count = 0; - debug_pad_lifo.last_entry_index = 0; + debug_pad_lifo.buffer_count = 0; + debug_pad_lifo.buffer_tail = 0; std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 47760b4f8..00df50f32 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -31,8 +31,8 @@ Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(s Controller_Gesture::~Controller_Gesture() = default; void Controller_Gesture::OnInit() { - gesture_lifo.entry_count = 0; - gesture_lifo.last_entry_index = 0; + gesture_lifo.buffer_count = 0; + gesture_lifo.buffer_tail = 0; force_update = true; } @@ -41,8 +41,8 @@ void Controller_Gesture::OnRelease() {} void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { if (!IsControllerActivated()) { - gesture_lifo.entry_count = 0; - gesture_lifo.last_entry_index = 0; + gesture_lifo.buffer_count = 0; + gesture_lifo.buffer_tail = 0; std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 632679a17..f4d49965f 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -27,8 +27,8 @@ void Controller_Keyboard::OnRelease() {} void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { if (!IsControllerActivated()) { - keyboard_lifo.entry_count = 0; - keyboard_lifo.last_entry_index = 0; + keyboard_lifo.buffer_count = 0; + keyboard_lifo.buffer_tail = 0; std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 6d3bd0a2b..7ec75e8c8 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -24,11 +24,9 @@ void Controller_Mouse::OnRelease() {} void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - mouse_lifo.timestamp = core_timing.GetCPUTicks(); - if (!IsControllerActivated()) { - mouse_lifo.entry_count = 0; - mouse_lifo.last_entry_index = 0; + mouse_lifo.buffer_count = 0; + mouse_lifo.buffer_tail = 0; std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 9f84e20c2..9f82f872a 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -101,7 +101,8 @@ Controller_NPad::Controller_NPad(Core::System& system_, for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; controller.device = system.HIDCore().GetEmulatedControllerByIndex(i); - controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE; + controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = + DEFAULT_VIBRATION_VALUE; controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE; Core::HID::ControllerUpdateCallback engine_callback{ @@ -178,7 +179,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_minus.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; - shared_memory.footer_type = AppletFooterUiType::SwitchProController; + shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; break; case Core::HID::NpadType::Handheld: shared_memory.style_set.handheld.Assign(1); @@ -188,7 +189,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_minus.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; + shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; break; case Core::HID::NpadType::JoyconDual: shared_memory.style_set.joycon_dual.Assign(1); @@ -198,7 +199,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_minus.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory.footer_type = AppletFooterUiType::JoyDual; + shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; break; case Core::HID::NpadType::JoyconLeft: shared_memory.style_set.joycon_left.Assign(1); @@ -206,7 +207,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.use_minus.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; - shared_memory.footer_type = AppletFooterUiType::JoyLeftHorizontal; + shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; break; case Core::HID::NpadType::JoyconRight: shared_memory.style_set.joycon_right.Assign(1); @@ -214,7 +215,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.use_plus.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; - shared_memory.footer_type = AppletFooterUiType::JoyRightHorizontal; + shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; break; case Core::HID::NpadType::GameCube: shared_memory.style_set.gamecube.Assign(1); @@ -919,7 +920,7 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { .right = {}, }; shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory_entry.footer_type = AppletFooterUiType::None; + shared_memory_entry.applet_footer.type = AppletFooterUiType::None; controller.is_connected = false; controller.device->Disconnect(); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 0a2dc6992..af4934c55 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -330,10 +330,43 @@ private: BitField<13, 1, s32> handheld_lark_nes_left; BitField<14, 1, s32> handheld_lark_nes_right; BitField<15, 1, s32> lucia; + BitField<16, 1, s32> lagon; + BitField<17, 1, s32> lager; BitField<31, 1, s32> system; }; }; + // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl + struct NfcXcdDeviceHandleStateImpl { + u64 handle; + bool is_available; + bool is_activated; + INSERT_PADDING_BYTES(0x6); // Reserved + u64 sampling_number; + }; + static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, + "NfcXcdDeviceHandleStateImpl is an invalid size"); + + // nn::hid::detail::NfcXcdDeviceHandleStateImplAtomicStorage + struct NfcXcdDeviceHandleStateImplAtomicStorage { + u64 sampling_number; + NfcXcdDeviceHandleStateImpl nfc_xcd_device_handle_state; + }; + static_assert(sizeof(NfcXcdDeviceHandleStateImplAtomicStorage) == 0x20, + "NfcXcdDeviceHandleStateImplAtomicStorage is an invalid size"); + + // This is nn::hid::detail::NfcXcdDeviceHandleState + struct NfcXcdDeviceHandleState { + // TODO(german77): Make this struct a ring lifo object + INSERT_PADDING_BYTES(0x8); // Unused + s64 total_buffer_count = max_buffer_size; + s64 buffer_tail{}; + s64 buffer_count{}; + std::array nfc_xcd_device_handle_storage; + }; + static_assert(sizeof(NfcXcdDeviceHandleState) == 0x60, + "NfcXcdDeviceHandleState is an invalid size"); + // This is nn::hid::system::AppletFooterUiAttributesSet struct AppletFooterUiAttributes { INSERT_PADDING_BYTES(0x4); @@ -365,6 +398,14 @@ private: Lagon = 21, }; + struct AppletFooterUi { + AppletFooterUiAttributes attributes; + AppletFooterUiType type; + INSERT_PADDING_BYTES(0x5B); // Reserved + }; + static_assert(sizeof(AppletFooterUi) == 0x60, + "AppletFooterUi is an invalid size"); + // This is nn::hid::NpadLarkType enum class NpadLarkType : u32 { Invalid, @@ -382,6 +423,11 @@ private: U, }; + // This is nn::hid::NpadLagonType + enum class NpadLagonType : u32 { + Invalid, + }; + // This is nn::hid::NpadLagerType enum class NpadLagerType : u32 { Invalid, @@ -416,17 +462,19 @@ private: Core::HID::BatteryLevel battery_level_dual; Core::HID::BatteryLevel battery_level_left; Core::HID::BatteryLevel battery_level_right; - AppletFooterUiAttributes footer_attributes; - AppletFooterUiType footer_type; - // GetXcdHandleForNpadWithNfc needs to be checked switchbrew doesn't match with HW - INSERT_PADDING_BYTES(0x78); // Unknown + union { + NfcXcdDeviceHandleState nfc_xcd_device_handle; + AppletFooterUi applet_footer; + }; + INSERT_PADDING_BYTES(0x20); // Unknown Lifo gc_trigger_lifo; - NpadLarkType lark_type_l; + NpadLarkType lark_type_l_and_main; NpadLarkType lark_type_r; NpadLuciaType lucia_type; + NpadLagonType lagon_type; NpadLagerType lager_type; INSERT_PADDING_BYTES( - 0x8); // FW 13.x Investigate there is some sort of bitflag related to joycons + 0x4); // FW 13.x Investigate there is some sort of bitflag related to joycons INSERT_PADDING_BYTES(0xc08); // Unknown }; static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 5ba8d96a8..9ae2bf2b1 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -30,8 +30,8 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin touch_screen_lifo.timestamp = core_timing.GetCPUTicks(); if (!IsControllerActivated()) { - touch_screen_lifo.entry_count = 0; - touch_screen_lifo.last_entry_index = 0; + touch_screen_lifo.buffer_count = 0; + touch_screen_lifo.buffer_tail = 0; std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo)); return; } diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index aa9f044f1..a2ed1e7c2 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -20,8 +20,8 @@ void Controller_XPad::OnRelease() {} void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { if (!IsControllerActivated()) { - basic_xpad_lifo.entry_count = 0; - basic_xpad_lifo.last_entry_index = 0; + basic_xpad_lifo.buffer_count = 0; + basic_xpad_lifo.buffer_tail = 0; std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); return; } diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h index f68d82762..382350a2d 100644 --- a/src/core/hle/service/hid/ring_lifo.h +++ b/src/core/hle/service/hid/ring_lifo.h @@ -8,7 +8,7 @@ #include "common/swap.h" namespace Service::HID { -constexpr std::size_t max_entry_size = 17; +constexpr std::size_t max_buffer_size = 17; template struct AtomicStorage { @@ -19,13 +19,13 @@ struct AtomicStorage { template struct Lifo { s64 timestamp{}; - s64 total_entry_count = max_entry_size; - s64 last_entry_index{}; - s64 entry_count{}; - std::array, max_entry_size> entries{}; + s64 total_buffer_count = max_buffer_size; + s64 buffer_tail{}; + s64 buffer_count{}; + std::array, max_buffer_size> entries{}; const AtomicStorage& ReadCurrentEntry() const { - return entries[last_entry_index]; + return entries[buffer_tail]; } const AtomicStorage& ReadPreviousEntry() const { @@ -33,21 +33,21 @@ struct Lifo { } std::size_t GetPreviuousEntryIndex() const { - return (last_entry_index + total_entry_count - 1) % total_entry_count; + return (buffer_tail + total_buffer_count - 1) % total_buffer_count; } std::size_t GetNextEntryIndex() const { - return (last_entry_index + 1) % total_entry_count; + return (buffer_tail + 1) % total_buffer_count; } void WriteNextEntry(const State& new_state) { - if (entry_count < total_entry_count - 1) { - entry_count++; + if (buffer_count < total_buffer_count - 1) { + buffer_count++; } - last_entry_index = GetNextEntryIndex(); + buffer_tail = GetNextEntryIndex(); const auto& previous_entry = ReadPreviousEntry(); - entries[last_entry_index].sampling_number = previous_entry.sampling_number + 1; - entries[last_entry_index].state = new_state; + entries[buffer_tail].sampling_number = previous_entry.sampling_number + 1; + entries[buffer_tail].state = new_state; } }; -- cgit v1.2.3 From 5f69fdbfccdf68ddb5bb22de32321fa352b22c0a Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 12:12:52 -0500 Subject: core/hid: Explain better what a temporary value does --- src/core/hid/emulated_controller.cpp | 38 +++++++++++++++++++----------------- src/core/hid/emulated_controller.h | 14 +++++++------ 2 files changed, 28 insertions(+), 24 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 2b051ccaf..3c3fa16d6 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -88,8 +88,9 @@ void EmulatedController::ReloadFromSettings() { ReloadInput(); } void EmulatedController::LoadDevices() { - const auto left_joycon = button_params[Settings::NativeButton::ZL]; - const auto right_joycon = button_params[Settings::NativeButton::ZR]; + // TODO(german77): Use more buttons to detect the correct device + const auto left_joycon = button_params[Settings::NativeButton::A]; + const auto right_joycon = button_params[Settings::NativeButton::DRight]; // Triggers for GC controllers trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; @@ -142,6 +143,7 @@ void EmulatedController::LoadTASParams() { param = common_params; } + // TODO(german77): Replace this with an input profile or something better tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); @@ -271,24 +273,24 @@ void EmulatedController::UnloadInput() { void EmulatedController::EnableConfiguration() { is_configuring = true; - temporary_is_connected = is_connected; - temporary_npad_type = npad_type; + tmp_is_connected = is_connected; + tmp_npad_type = npad_type; } void EmulatedController::DisableConfiguration() { is_configuring = false; // Apply temporary npad type to the real controller - if (temporary_npad_type != npad_type) { + if (tmp_npad_type != npad_type) { if (is_connected) { Disconnect(); } - SetNpadType(temporary_npad_type); + SetNpadType(tmp_npad_type); } // Apply temporary connected status to the real controller - if (temporary_is_connected != is_connected) { - if (temporary_is_connected) { + if (tmp_is_connected != is_connected) { + if (tmp_is_connected) { Connect(); return; } @@ -791,7 +793,7 @@ void EmulatedController::Connect() { { std::lock_guard lock{mutex}; if (is_configuring) { - temporary_is_connected = true; + tmp_is_connected = true; TriggerOnChange(ControllerTriggerType::Connected, false); return; } @@ -808,7 +810,7 @@ void EmulatedController::Disconnect() { { std::lock_guard lock{mutex}; if (is_configuring) { - temporary_is_connected = false; + tmp_is_connected = false; TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } @@ -821,9 +823,9 @@ void EmulatedController::Disconnect() { TriggerOnChange(ControllerTriggerType::Disconnected, true); } -bool EmulatedController::IsConnected(bool temporary) const { - if (temporary) { - return temporary_is_connected; +bool EmulatedController::IsConnected(bool get_temporary_value) const { + if (get_temporary_value) { + return tmp_is_connected; } return is_connected; } @@ -838,9 +840,9 @@ NpadIdType EmulatedController::GetNpadIdType() const { return npad_id_type; } -NpadType EmulatedController::GetNpadType(bool temporary) const { - if (temporary) { - return temporary_npad_type; +NpadType EmulatedController::GetNpadType(bool get_temporary_value) const { + if (get_temporary_value) { + return tmp_npad_type; } return npad_type; } @@ -850,10 +852,10 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { std::lock_guard lock{mutex}; if (is_configuring) { - if (temporary_npad_type == npad_type_) { + if (tmp_npad_type == npad_type_) { return; } - temporary_npad_type = npad_type_; + tmp_npad_type = npad_type_; TriggerOnChange(ControllerTriggerType::Type, false); return; } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index eec51e34a..fea401365 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -149,10 +149,10 @@ public: /** * Gets the NpadType for this controller - * @param Returns the temporary value if true + * @param If true tmp_npad_type will be returned * @return NpadType set on the controller */ - NpadType GetNpadType(bool temporary = false) const; + NpadType GetNpadType(bool get_temporary_value = false) const; /// Sets the connected status to true void Connect(); @@ -162,10 +162,10 @@ public: /** * Is the emulated connected - * @param Returns the temporary value if true + * @param If true tmp_is_connected will be returned * @return true if the controller has the connected status */ - bool IsConnected(bool temporary = false) const; + bool IsConnected(bool get_temporary_value = false) const; /// Returns true if vibration is enabled bool IsVibrationEnabled() const; @@ -346,12 +346,14 @@ private: NpadIdType npad_id_type; NpadType npad_type{NpadType::None}; - NpadType temporary_npad_type{NpadType::None}; bool is_connected{false}; - bool temporary_is_connected{false}; bool is_configuring{false}; f32 motion_sensitivity{0.01f}; + // Temporary values to avoid doing changes while the controller is on configuration mode + NpadType tmp_npad_type{NpadType::None}; + bool tmp_is_connected{false}; + ButtonParams button_params; StickParams stick_params; ControllerMotionParams motion_params; -- cgit v1.2.3 From 61d9eb9f690d6afe141f24ba75c99b54e122dfa3 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 20:16:10 -0500 Subject: input_common: Revert deleted TAS functions --- src/core/hid/emulated_controller.cpp | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 3c3fa16d6..69568f4e9 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -127,7 +127,7 @@ void EmulatedController::LoadDevices() { // Initialize TAS devices std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), Input::CreateDevice); - std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(), + std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), Input::CreateDevice); } @@ -135,7 +135,7 @@ void EmulatedController::LoadTASParams() { const auto player_index = NpadIdTypeToIndex(npad_id_type); Common::ParamPackage common_params{}; common_params.Set("engine", "tas"); - common_params.Set("pad", static_cast(player_index)); + common_params.Set("port", static_cast(player_index)); for (auto& param : tas_button_params) { param = common_params; } @@ -144,26 +144,26 @@ void EmulatedController::LoadTASParams() { } // TODO(german77): Replace this with an input profile or something better - tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); - tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); - tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); - tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3); - tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4); - tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5); - tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6); - tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7); - tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8); - tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9); - tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10); - tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11); - tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12); - tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13); - tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14); - tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15); - tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16); - tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17); - tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18); - tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19); + tas_button_params[Settings::NativeButton::A].Set("button", 0); + tas_button_params[Settings::NativeButton::B].Set("button", 1); + tas_button_params[Settings::NativeButton::X].Set("button", 2); + tas_button_params[Settings::NativeButton::Y].Set("button", 3); + tas_button_params[Settings::NativeButton::LStick].Set("button", 4); + tas_button_params[Settings::NativeButton::RStick].Set("button", 5); + tas_button_params[Settings::NativeButton::L].Set("button", 6); + tas_button_params[Settings::NativeButton::R].Set("button", 7); + tas_button_params[Settings::NativeButton::ZL].Set("button", 8); + tas_button_params[Settings::NativeButton::ZR].Set("button", 9); + tas_button_params[Settings::NativeButton::Plus].Set("button", 10); + tas_button_params[Settings::NativeButton::Minus].Set("button", 11); + tas_button_params[Settings::NativeButton::DLeft].Set("button", 12); + tas_button_params[Settings::NativeButton::DUp].Set("button", 13); + tas_button_params[Settings::NativeButton::DRight].Set("button", 14); + tas_button_params[Settings::NativeButton::DDown].Set("button", 15); + tas_button_params[Settings::NativeButton::SL].Set("button", 16); + tas_button_params[Settings::NativeButton::SR].Set("button", 17); + tas_button_params[Settings::NativeButton::Home].Set("button", 18); + tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19); tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); -- cgit v1.2.3 From 2b1b0c2a30e242b08ec120e09803ec54d5445703 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 22:23:10 -0500 Subject: kraken: Address comments from review start lion review --- src/core/hid/emulated_console.cpp | 17 +++-- src/core/hid/emulated_console.h | 15 ++-- src/core/hid/emulated_controller.cpp | 88 +++++++++++----------- src/core/hid/emulated_controller.h | 42 ++++++----- src/core/hid/emulated_devices.cpp | 37 +++++---- src/core/hid/emulated_devices.h | 28 ++++--- src/core/hid/input_converter.cpp | 75 +++++++++--------- src/core/hid/input_converter.h | 17 +++-- src/core/hle/service/hid/controllers/debug_pad.cpp | 3 - src/core/hle/service/hid/controllers/keyboard.cpp | 1 - src/core/hle/service/hid/controllers/npad.h | 3 +- src/core/hle/service/hid/ring_lifo.h | 6 +- 12 files changed, 178 insertions(+), 154 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index d1d4a5355..c259de0f1 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -55,21 +55,21 @@ void EmulatedConsole::SetTouchParams() { void EmulatedConsole::ReloadInput() { SetTouchParams(); - motion_devices = Input::CreateDevice(motion_params); + motion_devices = Common::Input::CreateDevice(motion_params); if (motion_devices) { - Input::InputCallback motion_callback{ - [this](Input::CallbackStatus callback) { SetMotion(callback); }}; + Common::Input::InputCallback motion_callback{ + [this](Common::Input::CallbackStatus callback) { SetMotion(callback); }}; motion_devices->SetCallback(motion_callback); } std::size_t index = 0; for (auto& touch_device : touch_devices) { - touch_device = Input::CreateDevice(touch_params[index]); + touch_device = Common::Input::CreateDevice(touch_params[index]); if (!touch_device) { continue; } - Input::InputCallback touch_callback{ - [this, index](Input::CallbackStatus callback) { SetTouch(callback, index); }}; + Common::Input::InputCallback touch_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetTouch(callback, index); }}; touch_device->SetCallback(touch_callback); index++; } @@ -117,7 +117,7 @@ void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { ReloadInput(); } -void EmulatedConsole::SetMotion(Input::CallbackStatus callback) { +void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) { std::lock_guard lock{mutex}; auto& raw_status = console.motion_values.raw_status; auto& emulated = console.motion_values.emulated; @@ -152,7 +152,8 @@ void EmulatedConsole::SetMotion(Input::CallbackStatus callback) { TriggerOnChange(ConsoleTriggerType::Motion); } -void EmulatedConsole::SetTouch(Input::CallbackStatus callback, [[maybe_unused]] std::size_t index) { +void EmulatedConsole::SetTouch(Common::Input::CallbackStatus callback, + [[maybe_unused]] std::size_t index) { if (index >= console.touch_values.size()) { return; } diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index f26f24f2e..9aec482a6 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -4,10 +4,13 @@ #pragma once +#include #include +#include #include #include +#include "common/common_types.h" #include "common/input.h" #include "common/param_package.h" #include "common/point.h" @@ -20,18 +23,18 @@ namespace Core::HID { struct ConsoleMotionInfo { - Input::MotionStatus raw_status{}; + Common::Input::MotionStatus raw_status{}; MotionInput emulated{}; }; -using ConsoleMotionDevices = std::unique_ptr; -using TouchDevices = std::array, 16>; +using ConsoleMotionDevices = std::unique_ptr; +using TouchDevices = std::array, 16>; using ConsoleMotionParams = Common::ParamPackage; using TouchParams = std::array; using ConsoleMotionValues = ConsoleMotionInfo; -using TouchValues = std::array; +using TouchValues = std::array; struct TouchFinger { u64 last_touch{}; @@ -151,14 +154,14 @@ private: * Updates the motion status of the console * @param A CallbackStatus containing gyro and accelerometer data */ - void SetMotion(Input::CallbackStatus callback); + void SetMotion(Common::Input::CallbackStatus callback); /** * Updates the touch status of the console * @param callback: A CallbackStatus containing the touch position * @param index: Finger ID to be updated */ - void SetTouch(Input::CallbackStatus callback, std::size_t index); + void SetTouch(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the console status diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 69568f4e9..49893cdbd 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -110,25 +110,25 @@ void EmulatedController::LoadDevices() { std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, button_params.begin() + Settings::NativeButton::BUTTON_NS_END, - button_devices.begin(), Input::CreateDevice); + button_devices.begin(), Common::Input::CreateDevice); std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, - stick_devices.begin(), Input::CreateDevice); + stick_devices.begin(), Common::Input::CreateDevice); std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, - motion_devices.begin(), Input::CreateDevice); + motion_devices.begin(), Common::Input::CreateDevice); std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(), - Input::CreateDevice); + Common::Input::CreateDevice); std::transform(output_params.begin(), output_params.end(), output_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); // Initialize TAS devices std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); } void EmulatedController::LoadTASParams() { @@ -178,8 +178,8 @@ void EmulatedController::ReloadInput() { if (!button_devices[index]) { continue; } - Input::InputCallback button_callback{ - [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; button_devices[index]->SetCallback(button_callback); button_devices[index]->ForceUpdate(); } @@ -188,8 +188,8 @@ void EmulatedController::ReloadInput() { if (!stick_devices[index]) { continue; } - Input::InputCallback stick_callback{ - [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + Common::Input::InputCallback stick_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; stick_devices[index]->SetCallback(stick_callback); stick_devices[index]->ForceUpdate(); } @@ -198,8 +198,8 @@ void EmulatedController::ReloadInput() { if (!trigger_devices[index]) { continue; } - Input::InputCallback trigger_callback{ - [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }}; + Common::Input::InputCallback trigger_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }}; trigger_devices[index]->SetCallback(trigger_callback); trigger_devices[index]->ForceUpdate(); } @@ -208,8 +208,8 @@ void EmulatedController::ReloadInput() { if (!battery_devices[index]) { continue; } - Input::InputCallback battery_callback{ - [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }}; + Common::Input::InputCallback battery_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetBattery(callback, index); }}; battery_devices[index]->SetCallback(battery_callback); battery_devices[index]->ForceUpdate(); } @@ -218,8 +218,8 @@ void EmulatedController::ReloadInput() { if (!motion_devices[index]) { continue; } - Input::InputCallback motion_callback{ - [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; + Common::Input::InputCallback motion_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetMotion(callback, index); }}; motion_devices[index]->SetCallback(motion_callback); motion_devices[index]->ForceUpdate(); } @@ -229,8 +229,8 @@ void EmulatedController::ReloadInput() { if (!tas_button_devices[index]) { continue; } - Input::InputCallback button_callback{ - [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; tas_button_devices[index]->SetCallback(button_callback); } @@ -238,8 +238,8 @@ void EmulatedController::ReloadInput() { if (!tas_stick_devices[index]) { continue; } - Input::InputCallback stick_callback{ - [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + Common::Input::InputCallback stick_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; tas_stick_devices[index]->SetCallback(stick_callback); } } @@ -418,7 +418,7 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage ReloadInput(); } -void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.button_values.size()) { return; } @@ -548,7 +548,7 @@ void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t i TriggerOnChange(ControllerTriggerType::Button, true); } -void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.stick_values.size()) { return; } @@ -587,7 +587,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in TriggerOnChange(ControllerTriggerType::Stick, true); } -void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.trigger_values.size()) { return; } @@ -618,7 +618,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t TriggerOnChange(ControllerTriggerType::Trigger, true); } -void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.motion_values.size()) { return; } @@ -655,7 +655,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i TriggerOnChange(ControllerTriggerType::Motion, true); } -void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.battery_values.size()) { return; } @@ -671,25 +671,25 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t bool is_powered = false; BatteryLevel battery_level = 0; switch (controller.battery_values[index]) { - case Input::BatteryLevel::Charging: + case Common::Input::BatteryLevel::Charging: is_charging = true; is_powered = true; battery_level = 6; break; - case Input::BatteryLevel::Medium: + case Common::Input::BatteryLevel::Medium: battery_level = 6; break; - case Input::BatteryLevel::Low: + case Common::Input::BatteryLevel::Low: battery_level = 4; break; - case Input::BatteryLevel::Critical: + case Common::Input::BatteryLevel::Critical: battery_level = 2; break; - case Input::BatteryLevel::Empty: + case Common::Input::BatteryLevel::Empty: battery_level = 0; break; - case Input::BatteryLevel::None: - case Input::BatteryLevel::Full: + case Common::Input::BatteryLevel::None: + case Common::Input::BatteryLevel::Full: default: is_powered = true; battery_level = 8; @@ -739,18 +739,19 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v // Exponential amplification is too strong at low amplitudes. Switch to a linear // amplification if strength is set below 0.7f - const Input::VibrationAmplificationType type = - strength > 0.7f ? Input::VibrationAmplificationType::Exponential - : Input::VibrationAmplificationType::Linear; + const Common::Input::VibrationAmplificationType type = + strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential + : Common::Input::VibrationAmplificationType::Linear; - const Input::VibrationStatus status = { + const Common::Input::VibrationStatus status = { .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), .low_frequency = vibration.low_frequency, .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), .high_frequency = vibration.high_frequency, .type = type, }; - return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; + return output_devices[device_index]->SetVibration(status) == + Common::Input::VibrationError::None; } bool EmulatedController::TestVibration(std::size_t device_index) { @@ -762,14 +763,15 @@ bool EmulatedController::TestVibration(std::size_t device_index) { } // Send a slight vibration to test for rumble support - constexpr Input::VibrationStatus status = { + constexpr Common::Input::VibrationStatus status = { .low_amplitude = 0.001f, .low_frequency = 160.0f, .high_amplitude = 0.001f, .high_frequency = 320.0f, - .type = Input::VibrationAmplificationType::Linear, + .type = Common::Input::VibrationAmplificationType::Linear, }; - return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; + return output_devices[device_index]->SetVibration(status) == + Common::Input::VibrationError::None; } void EmulatedController::SetLedPattern() { @@ -779,7 +781,7 @@ void EmulatedController::SetLedPattern() { } const LedPattern pattern = GetLedPattern(); - const Input::LedStatus status = { + const Common::Input::LedStatus status = { .led_1 = pattern.position1 != 0, .led_2 = pattern.position2 != 0, .led_3 = pattern.position3 != 0, diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index fea401365..dd9a93364 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -4,10 +4,13 @@ #pragma once +#include #include +#include #include #include +#include "common/common_types.h" #include "common/input.h" #include "common/param_package.h" #include "common/point.h" @@ -20,20 +23,22 @@ namespace Core::HID { const std::size_t max_emulated_controllers = 2; struct ControllerMotionInfo { - Input::MotionStatus raw_status{}; + Common::Input::MotionStatus raw_status{}; MotionInput emulated{}; }; using ButtonDevices = - std::array, Settings::NativeButton::NumButtons>; + std::array, Settings::NativeButton::NumButtons>; using StickDevices = - std::array, Settings::NativeAnalog::NumAnalogs>; + std::array, Settings::NativeAnalog::NumAnalogs>; using ControllerMotionDevices = - std::array, Settings::NativeMotion::NumMotions>; + std::array, Settings::NativeMotion::NumMotions>; using TriggerDevices = - std::array, Settings::NativeTrigger::NumTriggers>; -using BatteryDevices = std::array, max_emulated_controllers>; -using OutputDevices = std::array, max_emulated_controllers>; + std::array, Settings::NativeTrigger::NumTriggers>; +using BatteryDevices = + std::array, max_emulated_controllers>; +using OutputDevices = + std::array, max_emulated_controllers>; using ButtonParams = std::array; using StickParams = std::array; @@ -42,13 +47,14 @@ using TriggerParams = std::array; using OutputParams = std::array; -using ButtonValues = std::array; -using SticksValues = std::array; -using TriggerValues = std::array; +using ButtonValues = std::array; +using SticksValues = std::array; +using TriggerValues = + std::array; using ControllerMotionValues = std::array; -using ColorValues = std::array; -using BatteryValues = std::array; -using VibrationValues = std::array; +using ColorValues = std::array; +using BatteryValues = std::array; +using VibrationValues = std::array; struct AnalogSticks { AnalogStickState left{}; @@ -307,35 +313,35 @@ private: * @param callback: A CallbackStatus containing the button status * @param index: Button ID of the to be updated */ - void SetButton(Input::CallbackStatus callback, std::size_t index); + void SetButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the analog stick status of the controller * @param callback: A CallbackStatus containing the analog stick status * @param index: stick ID of the to be updated */ - void SetStick(Input::CallbackStatus callback, std::size_t index); + void SetStick(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the trigger status of the controller * @param callback: A CallbackStatus containing the trigger status * @param index: trigger ID of the to be updated */ - void SetTrigger(Input::CallbackStatus callback, std::size_t index); + void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the motion status of the controller * @param callback: A CallbackStatus containing gyro and accelerometer data * @param index: motion ID of the to be updated */ - void SetMotion(Input::CallbackStatus callback, std::size_t index); + void SetMotion(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the battery status of the controller * @param callback: A CallbackStatus containing the battery status * @param index: Button ID of the to be updated */ - void SetBattery(Input::CallbackStatus callback, std::size_t index); + void SetBattery(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the controller status diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index eb59c310c..c76a86b6c 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included +#include #include #include "core/hid/emulated_devices.h" @@ -25,21 +26,25 @@ void EmulatedDevices::ReloadFromSettings() { void EmulatedDevices::ReloadInput() { std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN, mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END, - mouse_button_devices.begin(), Input::CreateDevice); + mouse_button_devices.begin(), + Common::Input::CreateDevice); std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(), - keyboard_devices.begin(), Input::CreateDeviceFromString); + keyboard_devices.begin(), + Common::Input::CreateDeviceFromString); std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(), keyboard_modifier_devices.begin(), - Input::CreateDeviceFromString); + Common::Input::CreateDeviceFromString); for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { if (!mouse_button_devices[index]) { continue; } - Input::InputCallback button_callback{ - [this, index](Input::CallbackStatus callback) { SetMouseButton(callback, index); }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { + SetMouseButton(callback, index); + }}; mouse_button_devices[index]->SetCallback(button_callback); } @@ -47,8 +52,10 @@ void EmulatedDevices::ReloadInput() { if (!keyboard_devices[index]) { continue; } - Input::InputCallback button_callback{ - [this, index](Input::CallbackStatus callback) { SetKeyboardButton(callback, index); }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { + SetKeyboardButton(callback, index); + }}; keyboard_devices[index]->SetCallback(button_callback); } @@ -56,9 +63,10 @@ void EmulatedDevices::ReloadInput() { if (!keyboard_modifier_devices[index]) { continue; } - Input::InputCallback button_callback{[this, index](Input::CallbackStatus callback) { - SetKeyboardModifier(callback, index); - }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { + SetKeyboardModifier(callback, index); + }}; keyboard_modifier_devices[index]->SetCallback(button_callback); } } @@ -122,7 +130,7 @@ void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackag ReloadInput(); } -void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::size_t index) { +void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= device_status.keyboard_values.size()) { return; } @@ -170,7 +178,7 @@ void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::siz void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { constexpr u8 KEYS_PER_BYTE = 8; auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE]; - const u8 mask = 1 << (key_index % KEYS_PER_BYTE); + const u8 mask = static_cast(1 << (key_index % KEYS_PER_BYTE)); if (status) { entry = entry | mask; } else { @@ -178,7 +186,8 @@ void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { } } -void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) { +void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback, + std::size_t index) { if (index >= device_status.keyboard_moddifier_values.size()) { return; } @@ -247,7 +256,7 @@ void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::s TriggerOnChange(DeviceTriggerType::KeyboardModdifier); } -void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t index) { +void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= device_status.mouse_button_values.size()) { return; } diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 7ed95eac6..418b2f9b5 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -4,10 +4,13 @@ #pragma once +#include #include +#include #include #include +#include "common/common_types.h" #include "common/input.h" #include "common/param_package.h" #include "common/settings.h" @@ -16,21 +19,22 @@ namespace Core::HID { -using KeyboardDevices = - std::array, Settings::NativeKeyboard::NumKeyboardKeys>; -using KeyboardModifierDevices = - std::array, Settings::NativeKeyboard::NumKeyboardMods>; -using MouseButtonDevices = - std::array, Settings::NativeMouseButton::NumMouseButtons>; +using KeyboardDevices = std::array, + Settings::NativeKeyboard::NumKeyboardKeys>; +using KeyboardModifierDevices = std::array, + Settings::NativeKeyboard::NumKeyboardMods>; +using MouseButtonDevices = std::array, + Settings::NativeMouseButton::NumMouseButtons>; using MouseButtonParams = std::array; -using KeyboardValues = std::array; +using KeyboardValues = + std::array; using KeyboardModifierValues = - std::array; + std::array; using MouseButtonValues = - std::array; + std::array; struct MousePosition { s32 x; @@ -151,21 +155,21 @@ private: * @param callback: A CallbackStatus containing the key status * @param index: key ID to be updated */ - void SetKeyboardButton(Input::CallbackStatus callback, std::size_t index); + void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the touch status of the console * @param callback: A CallbackStatus containing the modifier key status * @param index: modifier key ID to be updated */ - void SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index); + void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the touch status of the console * @param callback: A CallbackStatus containing the button status * @param index: Button ID of the to be updated */ - void SetMouseButton(Input::CallbackStatus callback, std::size_t index); + void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the device status diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index e2598f367..14204917e 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -9,35 +9,35 @@ namespace Core::HID { -Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) { - Input::BatteryStatus battery{Input::BatteryStatus::None}; +Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback) { + Common::Input::BatteryStatus battery{Common::Input::BatteryStatus::None}; switch (callback.type) { - case Input::InputType::Analog: - case Input::InputType::Trigger: { + case Common::Input::InputType::Analog: + case Common::Input::InputType::Trigger: { const auto value = TransformToTrigger(callback).analog.value; - battery = Input::BatteryLevel::Empty; + battery = Common::Input::BatteryLevel::Empty; if (value > 0.2f) { - battery = Input::BatteryLevel::Critical; + battery = Common::Input::BatteryLevel::Critical; } if (value > 0.4f) { - battery = Input::BatteryLevel::Low; + battery = Common::Input::BatteryLevel::Low; } if (value > 0.6f) { - battery = Input::BatteryLevel::Medium; + battery = Common::Input::BatteryLevel::Medium; } if (value > 0.8f) { - battery = Input::BatteryLevel::Full; + battery = Common::Input::BatteryLevel::Full; } if (value >= 1.0f) { - battery = Input::BatteryLevel::Charging; + battery = Common::Input::BatteryLevel::Charging; } break; } - case Input::InputType::Button: - battery = callback.button_status.value ? Input::BatteryLevel::Charging - : Input::BatteryLevel::Critical; + case Common::Input::InputType::Button: + battery = callback.button_status.value ? Common::Input::BatteryLevel::Charging + : Common::Input::BatteryLevel::Critical; break; - case Input::InputType::Battery: + case Common::Input::InputType::Battery: battery = callback.battery_status; break; default: @@ -48,14 +48,14 @@ Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback) { return battery; } -Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback) { - Input::ButtonStatus status{}; +Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback) { + Common::Input::ButtonStatus status{}; switch (callback.type) { - case Input::InputType::Analog: - case Input::InputType::Trigger: + case Common::Input::InputType::Analog: + case Common::Input::InputType::Trigger: status.value = TransformToTrigger(callback).pressed; break; - case Input::InputType::Button: + case Common::Input::InputType::Button: status = callback.button_status; break; default: @@ -70,15 +70,15 @@ Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback) { return status; } -Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) { - Input::MotionStatus status{}; +Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback) { + Common::Input::MotionStatus status{}; switch (callback.type) { - case Input::InputType::Button: { + case Common::Input::InputType::Button: { if (TransformToButton(callback).value) { std::random_device device; std::mt19937 gen(device()); std::uniform_int_distribution distribution(-1000, 1000); - Input::AnalogProperties properties{ + Common::Input::AnalogProperties properties{ .deadzone = 0.0, .range = 1.0f, .offset = 0.0, @@ -116,7 +116,7 @@ Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) { } break; } - case Input::InputType::Motion: + case Common::Input::InputType::Motion: status = callback.motion_status; break; default: @@ -133,11 +133,11 @@ Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback) { return status; } -Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) { - Input::StickStatus status{}; +Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback) { + Common::Input::StickStatus status{}; switch (callback.type) { - case Input::InputType::Stick: + case Common::Input::InputType::Stick: status = callback.stick_status; break; default: @@ -160,11 +160,11 @@ Input::StickStatus TransformToStick(const Input::CallbackStatus& callback) { return status; } -Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback) { - Input::TouchStatus status{}; +Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback) { + Common::Input::TouchStatus status{}; switch (callback.type) { - case Input::InputType::Touch: + case Common::Input::InputType::Touch: status = callback.touch_status; break; default: @@ -192,22 +192,22 @@ Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback) { return status; } -Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) { - Input::TriggerStatus status{}; +Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback) { + Common::Input::TriggerStatus status{}; float& raw_value = status.analog.raw_value; bool calculate_button_value = true; switch (callback.type) { - case Input::InputType::Analog: + case Common::Input::InputType::Analog: status.analog.properties = callback.analog_status.properties; raw_value = callback.analog_status.raw_value; break; - case Input::InputType::Button: + case Common::Input::InputType::Button: status.analog.properties.range = 1.0f; status.analog.properties.inverted = callback.button_status.inverted; raw_value = callback.button_status.value ? 1.0f : 0.0f; break; - case Input::InputType::Trigger: + case Common::Input::InputType::Trigger: status = callback.trigger_status; calculate_button_value = false; break; @@ -234,7 +234,7 @@ Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback) { return status; } -void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) { +void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { const auto& properties = analog.properties; float& raw_value = analog.raw_value; float& value = analog.value; @@ -274,7 +274,8 @@ void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value) { } } -void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value) { +void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, + bool clamp_value) { const auto& properties_x = analog_x.properties; const auto& properties_y = analog_y.properties; float& raw_x = analog_x.raw_value; diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h index 3cc32e26a..b38e657b0 100644 --- a/src/core/hid/input_converter.h +++ b/src/core/hid/input_converter.h @@ -16,7 +16,7 @@ namespace Core::HID { * @param Supported callbacks: Analog, Battery, Trigger. * @return A valid BatteryStatus object. */ -Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback); +Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback); /** * Converts raw input data into a valid button status. Applies invert properties to the output. @@ -24,7 +24,7 @@ Input::BatteryStatus TransformToBattery(const Input::CallbackStatus& callback); * @param Supported callbacks: Analog, Button, Trigger. * @return A valid TouchStatus object. */ -Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback); +Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback); /** * Converts raw input data into a valid motion status. @@ -32,7 +32,7 @@ Input::ButtonStatus TransformToButton(const Input::CallbackStatus& callback); * @param Supported callbacks: Motion. * @return A valid TouchStatus object. */ -Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback); +Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback); /** * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert @@ -41,7 +41,7 @@ Input::MotionStatus TransformToMotion(const Input::CallbackStatus& callback); * @param Supported callbacks: Stick. * @return A valid StickStatus object. */ -Input::StickStatus TransformToStick(const Input::CallbackStatus& callback); +Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback); /** * Converts raw input data into a valid touch status. @@ -49,7 +49,7 @@ Input::StickStatus TransformToStick(const Input::CallbackStatus& callback); * @param Supported callbacks: Touch. * @return A valid TouchStatus object. */ -Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback); +Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback); /** * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and @@ -58,20 +58,21 @@ Input::TouchStatus TransformToTouch(const Input::CallbackStatus& callback); * @param Supported callbacks: Analog, Button, Trigger. * @return A valid TriggerStatus object. */ -Input::TriggerStatus TransformToTrigger(const Input::CallbackStatus& callback); +Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); /** * Converts raw analog data into a valid analog value * @param An analog object containing raw data and properties, bool that determines if the value * needs to be clamped between -1.0f and 1.0f. */ -void SanitizeAnalog(Input::AnalogStatus& analog, bool clamp_value); +void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value); /** * Converts raw stick data into a valid stick value * @param Two analog objects containing raw data and properties, bool that determines if the value * needs to be clamped into the unit circle. */ -void SanitizeStick(Input::AnalogStatus& analog_x, Input::AnalogStatus& analog_y, bool clamp_value); +void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, + bool clamp_value); } // namespace Core::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 345134357..b009ed086 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -13,9 +13,6 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; -constexpr s32 HID_JOYSTICK_MAX = 0x7fff; -[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; -enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} { controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other); diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index f4d49965f..60dc62f2c 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -12,7 +12,6 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; -constexpr u8 KEYS_PER_BYTE = 8; Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} { emulated_devices = system.HIDCore().GetEmulatedDevices(); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index af4934c55..4a9c9cc1a 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -403,8 +403,7 @@ private: AppletFooterUiType type; INSERT_PADDING_BYTES(0x5B); // Reserved }; - static_assert(sizeof(AppletFooterUi) == 0x60, - "AppletFooterUi is an invalid size"); + static_assert(sizeof(AppletFooterUi) == 0x60, "AppletFooterUi is an invalid size"); // This is nn::hid::NpadLarkType enum class NpadLarkType : u32 { diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h index 382350a2d..6209ed0d1 100644 --- a/src/core/hle/service/hid/ring_lifo.h +++ b/src/core/hle/service/hid/ring_lifo.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "common/common_types.h" #include "common/swap.h" @@ -29,10 +31,10 @@ struct Lifo { } const AtomicStorage& ReadPreviousEntry() const { - return entries[GetPreviuousEntryIndex()]; + return entries[GetPreviousEntryIndex()]; } - std::size_t GetPreviuousEntryIndex() const { + std::size_t GetPreviousEntryIndex() const { return (buffer_tail + total_buffer_count - 1) % total_buffer_count; } -- cgit v1.2.3 From 730f07830247cfcdc551c253d30c6717fc16316c Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 31 Oct 2021 10:41:44 -0500 Subject: settings: Fix Debug controller type options --- src/core/hid/emulated_console.cpp | 3 ++- src/core/hid/emulated_controller.cpp | 11 ++++++++--- src/core/hid/input_converter.cpp | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index c259de0f1..012909954 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -166,9 +166,10 @@ void EmulatedConsole::SetTouch(Common::Input::CallbackStatus callback, return; } + // TODO(german77): Remap touch id in sequential order console.touch_state[index] = { .position = {console.touch_values[index].x.value, console.touch_values[index].y.value}, - .id = console.touch_values[index].id, + .id = static_cast(console.touch_values[index].id), .pressed = console.touch_values[index].pressed.value, }; diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 49893cdbd..9a1864279 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -77,7 +77,12 @@ void EmulatedController::ReloadFromSettings() { controller.colors_state.fullkey = controller.colors_state.left; - SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + // Other or debug controller should always be a pro controller + if (npad_id_type != NpadIdType::Other) { + SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + } else { + SetNpadType(NpadType::ProController); + } if (player.connected) { Connect(); @@ -606,12 +611,12 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std: switch (index) { case Settings::NativeTrigger::LTrigger: controller.gc_trigger_state.left = static_cast(trigger.analog.value * HID_TRIGGER_MAX); - controller.npad_button_state.zl.Assign(trigger.pressed); + controller.npad_button_state.zl.Assign(trigger.pressed.value); break; case Settings::NativeTrigger::RTrigger: controller.gc_trigger_state.right = static_cast(trigger.analog.value * HID_TRIGGER_MAX); - controller.npad_button_state.zr.Assign(trigger.pressed); + controller.npad_button_state.zr.Assign(trigger.pressed.value); break; } diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 14204917e..5b123bd3a 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -53,7 +53,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu switch (callback.type) { case Common::Input::InputType::Analog: case Common::Input::InputType::Trigger: - status.value = TransformToTrigger(callback).pressed; + status.value = TransformToTrigger(callback).pressed.value; break; case Common::Input::InputType::Button: status = callback.button_status; @@ -222,7 +222,7 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta // Set button status if (calculate_button_value) { - status.pressed = value > properties.threshold; + status.pressed.value = value > properties.threshold; } // Adjust if value is inverted -- cgit v1.2.3 From 77fa4d4bf60526826ef8b53ee3870f7d2a761976 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 1 Nov 2021 14:17:53 -0600 Subject: second commit lion review --- src/core/hid/emulated_console.cpp | 5 +++-- src/core/hid/emulated_controller.cpp | 5 +++-- src/core/hid/emulated_devices.cpp | 5 +++-- src/core/hid/hid_core.cpp | 3 +++ src/core/hid/hid_core.h | 10 +++++++--- src/core/hid/input_converter.h | 12 ++++++++++-- src/core/hle/service/am/applets/applet_controller.cpp | 2 ++ src/core/hle/service/hid/controllers/console_sixaxis.cpp | 1 + src/core/hle/service/hid/controllers/debug_pad.cpp | 1 + src/core/hle/service/hid/controllers/gesture.h | 5 +---- src/core/hle/service/hid/controllers/keyboard.cpp | 1 + src/core/hle/service/hid/controllers/mouse.cpp | 1 + src/core/hle/service/hid/controllers/npad.cpp | 2 ++ src/core/hle/service/hid/controllers/npad.h | 6 +++++- src/core/hle/service/hid/controllers/touchscreen.h | 1 + 15 files changed, 44 insertions(+), 16 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 012909954..dfbaa3f8c 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -209,10 +209,11 @@ int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { void EmulatedConsole::DeleteCallback(int key) { std::lock_guard lock{mutex}; - if (!callback_list.contains(key)) { + const auto& iterator = callback_list.find(key); + if (iterator == callback_list.end()) { LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); return; } - callback_list.erase(key); + callback_list.erase(iterator); } } // namespace Core::HID diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 9a1864279..7bab00bb1 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -993,10 +993,11 @@ int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { void EmulatedController::DeleteCallback(int key) { std::lock_guard lock{mutex}; - if (!callback_list.contains(key)) { + const auto& iterator = callback_list.find(key); + if (iterator == callback_list.end()) { LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); return; } - callback_list.erase(key); + callback_list.erase(iterator); } } // namespace Core::HID diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index c76a86b6c..e97470240 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -362,10 +362,11 @@ int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { void EmulatedDevices::DeleteCallback(int key) { std::lock_guard lock{mutex}; - if (!callback_list.contains(key)) { + const auto& iterator = callback_list.find(key); + if (iterator == callback_list.end()) { LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); return; } - callback_list.erase(key); + callback_list.erase(iterator); } } // namespace Core::HID diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index 3cb26e1e7..741a69c3c 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -3,6 +3,9 @@ // Refer to the license.txt file included. #include "common/assert.h" +#include "core/hid/emulated_console.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" namespace Core::HID { diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index a4a66a3a4..1fe2fd89b 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -6,9 +6,13 @@ #include -#include "core/hid/emulated_console.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/emulated_devices.h" +#include "core/hid/hid_types.h" + +namespace Core::HID { +class EmulatedConsole; +class EmulatedController; +class EmulatedDevices; +} // namespace Core::HID namespace Core::HID { diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h index b38e657b0..2a722b39f 100644 --- a/src/core/hid/input_converter.h +++ b/src/core/hid/input_converter.h @@ -4,9 +4,17 @@ #pragma once -namespace Input { +namespace Common::Input { struct CallbackStatus; -}; +enum class BatteryLevel : u32; +using BatteryStatus = BatteryLevel; +struct AnalogStatus; +struct ButtonStatus; +struct MotionStatus; +struct StickStatus; +struct TouchStatus; +struct TriggerStatus; +}; // namespace Common::Input namespace Core::HID { diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 658265a00..374e0c7f4 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp @@ -10,6 +10,8 @@ #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/controller.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_controller.h" diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index 1d351fde0..2bebcf0d0 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -5,6 +5,7 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hid/emulated_console.h" #include "core/hle/service/hid/controllers/console_sixaxis.h" namespace Service::HID { diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index b009ed086..86b95f2c8 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -7,6 +7,7 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/debug_pad.h" diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 58139a5cf..9bffde438 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -8,13 +8,10 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "common/point.h" +#include "core/hid/emulated_console.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - namespace Service::HID { class Controller_Gesture final : public ControllerBase { public: diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 60dc62f2c..acea68e24 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -7,6 +7,7 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/keyboard.h" diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 7ec75e8c8..21f7e48bb 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -7,6 +7,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/mouse.h" diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 9f82f872a..0b5a23696 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -12,6 +12,8 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_writable_event.h" diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 4a9c9cc1a..871d245fd 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -12,11 +12,15 @@ #include "common/common_types.h" #include "common/quaternion.h" #include "common/settings.h" -#include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" +namespace Core::HID { +class EmulatedController; +enum class ControllerTriggerType; +} // namespace Core::HID + namespace Kernel { class KEvent; class KReadableEvent; diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index fa4dfa1a2..50dadd25f 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -9,6 +9,7 @@ #include "common/common_types.h" #include "common/point.h" #include "common/swap.h" +#include "core/hid/emulated_console.h" #include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" -- cgit v1.2.3 From 136eb9c4c2b2425c2dd45a79cf444dee7170714d Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 1 Nov 2021 19:49:14 -0600 Subject: core/hid: Fully emulate motion from button --- src/core/hid/emulated_controller.cpp | 11 ++++- src/core/hid/emulated_controller.h | 1 + src/core/hid/input_converter.cpp | 78 ++++++++++++++++++++---------------- src/core/hid/motion_input.h | 16 ++++++++ 4 files changed, 70 insertions(+), 36 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7bab00bb1..2db2b4da0 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -644,6 +644,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: }); emulated.UpdateRotation(raw_status.delta_timestamp); emulated.UpdateOrientation(raw_status.delta_timestamp); + force_update_motion = raw_status.force_update; if (is_configuring) { TriggerOnChange(ControllerTriggerType::Motion, false); @@ -653,7 +654,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: auto& motion = controller.motion_state[index]; motion.accel = emulated.GetAcceleration(); motion.gyro = emulated.GetGyroscope(); - motion.rotation = emulated.GetGyroscope(); + motion.rotation = emulated.GetRotations(); motion.orientation = emulated.GetOrientation(); motion.is_at_rest = emulated.IsMoving(motion_sensitivity); @@ -962,6 +963,14 @@ NpadGcTriggerState EmulatedController::GetTriggers() const { } MotionState EmulatedController::GetMotions() const { + if (force_update_motion) { + for (auto& device : motion_devices) { + if (!device) { + continue; + } + device->ForceUpdate(); + } + } return controller.motion_state; } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index dd9a93364..2f7afff56 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -355,6 +355,7 @@ private: bool is_connected{false}; bool is_configuring{false}; f32 motion_sensitivity{0.01f}; + bool force_update_motion{false}; // Temporary values to avoid doing changes while the controller is on configuration mode NpadType tmp_npad_type{NpadType::None}; diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 5b123bd3a..480b862fd 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -74,45 +74,53 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu Common::Input::MotionStatus status{}; switch (callback.type) { case Common::Input::InputType::Button: { + Common::Input::AnalogProperties properties{ + .deadzone = 0.0f, + .range = 1.0f, + .offset = 0.0f, + }; + status.delta_timestamp = 5000; + status.force_update = true; + status.accel.x = { + .value = 0.0f, + .raw_value = 0.0f, + .properties = properties, + }; + status.accel.y = { + .value = 0.0f, + .raw_value = 0.0f, + .properties = properties, + }; + status.accel.z = { + .value = 0.0f, + .raw_value = -1.0f, + .properties = properties, + }; + status.gyro.x = { + .value = 0.0f, + .raw_value = 0.0f, + .properties = properties, + }; + status.gyro.y = { + .value = 0.0f, + .raw_value = 0.0f, + .properties = properties, + }; + status.gyro.z = { + .value = 0.0f, + .raw_value = 0.0f, + .properties = properties, + }; if (TransformToButton(callback).value) { std::random_device device; std::mt19937 gen(device()); std::uniform_int_distribution distribution(-1000, 1000); - Common::Input::AnalogProperties properties{ - .deadzone = 0.0, - .range = 1.0f, - .offset = 0.0, - }; - status.accel.x = { - .value = 0, - .raw_value = static_cast(distribution(gen)) * 0.001f, - .properties = properties, - }; - status.accel.y = { - .value = 0, - .raw_value = static_cast(distribution(gen)) * 0.001f, - .properties = properties, - }; - status.accel.z = { - .value = 0, - .raw_value = static_cast(distribution(gen)) * 0.001f, - .properties = properties, - }; - status.gyro.x = { - .value = 0, - .raw_value = static_cast(distribution(gen)) * 0.001f, - .properties = properties, - }; - status.gyro.y = { - .value = 0, - .raw_value = static_cast(distribution(gen)) * 0.001f, - .properties = properties, - }; - status.gyro.z = { - .value = 0, - .raw_value = static_cast(distribution(gen)) * 0.001f, - .properties = properties, - }; + status.accel.x.raw_value = static_cast(distribution(gen)) * 0.001f; + status.accel.y.raw_value = static_cast(distribution(gen)) * 0.001f; + status.accel.z.raw_value = static_cast(distribution(gen)) * 0.001f; + status.gyro.x.raw_value = static_cast(distribution(gen)) * 0.001f; + status.gyro.y.raw_value = static_cast(distribution(gen)) * 0.001f; + status.gyro.z.raw_value = static_cast(distribution(gen)) * 0.001f; } break; } diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h index 3deef5ac3..5b5b420bb 100644 --- a/src/core/hid/motion_input.h +++ b/src/core/hid/motion_input.h @@ -56,15 +56,31 @@ private: Common::Vec3f integral_error; Common::Vec3f derivative_error; + // Quaternion containing the device orientation Common::Quaternion quat{{0.0f, 0.0f, -1.0f}, 0.0f}; + + // Number of full rotations in each axis Common::Vec3f rotations; + + // Acceleration vector measurement in G force Common::Vec3f accel; + + // Gyroscope vector measurement in radians/s. Common::Vec3f gyro; + + // Vector to be substracted from gyro measurements Common::Vec3f gyro_drift; + // Minimum gyro amplitude to detect if the device is moving f32 gyro_threshold = 0.0f; + + // Number of invalid sequential data u32 reset_counter = 0; + + // If the provided data is invalid the device will be autocalibrated bool reset_enabled = true; + + // Use accelerometer values to calculate position bool only_accelerometer = true; }; -- cgit v1.2.3 From 157e0b85fdd805e02d234dccf1ce578e3159adee Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 2 Nov 2021 22:50:30 -0600 Subject: core/hid: Prevent Emulated controller from flapping with multiple inputs devices --- src/core/hid/emulated_controller.cpp | 68 ++++++++++++++++++++++++++++++------ src/core/hid/emulated_controller.h | 6 ++-- 2 files changed, 61 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 2db2b4da0..6fe3744fd 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -183,8 +183,11 @@ void EmulatedController::ReloadInput() { if (!button_devices[index]) { continue; } + const auto uuid = Common::UUID{button_params[index].Get("guid", "")}; Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; + [this, index, uuid](Common::Input::CallbackStatus callback) { + SetButton(callback, index, uuid); + }}; button_devices[index]->SetCallback(button_callback); button_devices[index]->ForceUpdate(); } @@ -193,8 +196,11 @@ void EmulatedController::ReloadInput() { if (!stick_devices[index]) { continue; } + const auto uuid = Common::UUID{stick_params[index].Get("guid", "")}; Common::Input::InputCallback stick_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; + [this, index, uuid](Common::Input::CallbackStatus callback) { + SetStick(callback, index, uuid); + }}; stick_devices[index]->SetCallback(stick_callback); stick_devices[index]->ForceUpdate(); } @@ -203,8 +209,11 @@ void EmulatedController::ReloadInput() { if (!trigger_devices[index]) { continue; } + const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")}; Common::Input::InputCallback trigger_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }}; + [this, index, uuid](Common::Input::CallbackStatus callback) { + SetTrigger(callback, index, uuid); + }}; trigger_devices[index]->SetCallback(trigger_callback); trigger_devices[index]->ForceUpdate(); } @@ -229,13 +238,18 @@ void EmulatedController::ReloadInput() { motion_devices[index]->ForceUpdate(); } + // Use a common UUID for TAS + const auto tas_uuid = Common::UUID{0x0, 0x7A5}; + // Register TAS devices. No need to force update for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { if (!tas_button_devices[index]) { continue; } Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; + [this, index, tas_uuid](Common::Input::CallbackStatus callback) { + SetButton(callback, index, tas_uuid); + }}; tas_button_devices[index]->SetCallback(button_callback); } @@ -244,7 +258,9 @@ void EmulatedController::ReloadInput() { continue; } Common::Input::InputCallback stick_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; + [this, index, tas_uuid](Common::Input::CallbackStatus callback) { + SetStick(callback, index, tas_uuid); + }}; tas_stick_devices[index]->SetCallback(stick_callback); } } @@ -423,7 +439,8 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage ReloadInput(); } -void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index, + Common::UUID uuid) { if (index >= controller.button_values.size()) { return; } @@ -432,7 +449,16 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: bool value_changed = false; const auto new_status = TransformToButton(callback); auto& current_status = controller.button_values[index]; + + // Only read button values that have the same uuid or are pressed once + if (current_status.uuid != uuid) { + if (!new_status.value) { + return; + } + } + current_status.toggle = new_status.toggle; + current_status.uuid = uuid; // Update button status with current if (!current_status.toggle) { @@ -553,12 +579,23 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: TriggerOnChange(ControllerTriggerType::Button, true); } -void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index, + Common::UUID uuid) { if (index >= controller.stick_values.size()) { return; } std::lock_guard lock{mutex}; - controller.stick_values[index] = TransformToStick(callback); + const auto stick_value = TransformToStick(callback); + + // Only read stick values that have the same uuid or are over the threshold to avoid flapping + if (controller.stick_values[index].uuid != uuid) { + if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) { + return; + } + } + + controller.stick_values[index] = stick_value; + controller.stick_values[index].uuid = uuid; if (is_configuring) { controller.analog_stick_state.left = {}; @@ -592,12 +629,23 @@ void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::s TriggerOnChange(ControllerTriggerType::Stick, true); } -void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, + Common::UUID uuid) { if (index >= controller.trigger_values.size()) { return; } std::lock_guard lock{mutex}; - controller.trigger_values[index] = TransformToTrigger(callback); + const auto trigger_value = TransformToTrigger(callback); + + // Only read trigger values that have the same uuid or are pressed once + if (controller.stick_values[index].uuid != uuid) { + if (!trigger_value.pressed.value) { + return; + } + } + + controller.trigger_values[index] = trigger_value; + controller.trigger_values[index].uuid = uuid; if (is_configuring) { controller.gc_trigger_state.left = 0; diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 2f7afff56..9a8bdf14d 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -313,21 +313,21 @@ private: * @param callback: A CallbackStatus containing the button status * @param index: Button ID of the to be updated */ - void SetButton(Common::Input::CallbackStatus callback, std::size_t index); + void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the analog stick status of the controller * @param callback: A CallbackStatus containing the analog stick status * @param index: stick ID of the to be updated */ - void SetStick(Common::Input::CallbackStatus callback, std::size_t index); + void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the trigger status of the controller * @param callback: A CallbackStatus containing the trigger status * @param index: trigger ID of the to be updated */ - void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index); + void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the motion status of the controller -- cgit v1.2.3 From 84c58666a4dbb6d46e132514e4d91437fb689fa0 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 3 Nov 2021 22:35:45 -0600 Subject: config: Cleanup and documentation --- src/core/hid/emulated_console.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index dfbaa3f8c..b51c72eae 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -11,7 +11,7 @@ EmulatedConsole::EmulatedConsole() = default; EmulatedConsole::~EmulatedConsole() = default; void EmulatedConsole::ReloadFromSettings() { - // Using first motion device from player 1. No need to assign a special config at the moment + // Using first motion device from player 1. No need to assign any unique config at the moment const auto& player = Settings::values.players.GetValue()[0]; motion_params = Common::ParamPackage(player.motions[0]); @@ -33,6 +33,7 @@ void EmulatedConsole::SetTouchParams() { static_cast(Settings::values.touch_from_button_map_index.GetValue()); const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons; + // Map the rest of the fingers from touch from button configuration for (const auto& config_entry : touch_buttons) { Common::ParamPackage params{config_entry}; Common::ParamPackage touch_button_params; @@ -54,7 +55,9 @@ void EmulatedConsole::SetTouchParams() { } void EmulatedConsole::ReloadInput() { + // If you load any device here add the equivalent to the UnloadInput() function SetTouchParams(); + motion_devices = Common::Input::CreateDevice(motion_params); if (motion_devices) { Common::Input::InputCallback motion_callback{ @@ -62,6 +65,7 @@ void EmulatedConsole::ReloadInput() { motion_devices->SetCallback(motion_callback); } + // Unique index for identifying touch device source std::size_t index = 0; for (auto& touch_device : touch_devices) { touch_device = Common::Input::CreateDevice(touch_params[index]); -- cgit v1.2.3 From 5d0f3540c4b085103afa27d6120ea29e0324a5a2 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 4 Nov 2021 12:08:54 -0600 Subject: core/hid: Rename NpadType to NpadStyleIndex --- src/core/frontend/applets/controller.cpp | 10 +- src/core/hid/emulated_controller.cpp | 44 ++++----- src/core/hid/emulated_controller.h | 18 ++-- src/core/hid/hid_types.h | 13 ++- src/core/hle/service/hid/controllers/npad.cpp | 129 +++++++++++++------------- src/core/hle/service/hid/controllers/npad.h | 11 ++- src/core/hle/service/hid/hid.cpp | 14 +-- 7 files changed, 125 insertions(+), 114 deletions(-) (limited to 'src/core') diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 212ace892..6dbd38ffa 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -44,26 +44,26 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb // Connect controllers based on the following priority list from highest to lowest priority: // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld if (parameters.allow_pro_controller) { - controller->SetNpadType(Core::HID::NpadType::ProController); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); controller->Connect(); } else if (parameters.allow_dual_joycons) { - controller->SetNpadType(Core::HID::NpadType::JoyconDual); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual); controller->Connect(); } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { // Assign left joycons to even player indices and right joycons to odd player indices. // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and // a right Joycon for Player 2 in 2 Player Assist mode. if (index % 2 == 0) { - controller->SetNpadType(Core::HID::NpadType::JoyconLeft); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft); controller->Connect(); } else { - controller->SetNpadType(Core::HID::NpadType::JoyconRight); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight); controller->Connect(); } } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && !Settings::values.use_docked_mode.GetValue()) { // We should *never* reach here under any normal circumstances. - controller->SetNpadType(Core::HID::NpadType::Handheld); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); controller->Connect(); } else { UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 6fe3744fd..a200992f2 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -13,38 +13,38 @@ EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type( EmulatedController::~EmulatedController() = default; -NpadType EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { +NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { switch (type) { case Settings::ControllerType::ProController: - return NpadType::ProController; + return NpadStyleIndex::ProController; case Settings::ControllerType::DualJoyconDetached: - return NpadType::JoyconDual; + return NpadStyleIndex::JoyconDual; case Settings::ControllerType::LeftJoycon: - return NpadType::JoyconLeft; + return NpadStyleIndex::JoyconLeft; case Settings::ControllerType::RightJoycon: - return NpadType::JoyconRight; + return NpadStyleIndex::JoyconRight; case Settings::ControllerType::Handheld: - return NpadType::Handheld; + return NpadStyleIndex::Handheld; case Settings::ControllerType::GameCube: - return NpadType::GameCube; + return NpadStyleIndex::GameCube; default: - return NpadType::ProController; + return NpadStyleIndex::ProController; } } -Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type) { +Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { switch (type) { - case NpadType::ProController: + case NpadStyleIndex::ProController: return Settings::ControllerType::ProController; - case NpadType::JoyconDual: + case NpadStyleIndex::JoyconDual: return Settings::ControllerType::DualJoyconDetached; - case NpadType::JoyconLeft: + case NpadStyleIndex::JoyconLeft: return Settings::ControllerType::LeftJoycon; - case NpadType::JoyconRight: + case NpadStyleIndex::JoyconRight: return Settings::ControllerType::RightJoycon; - case NpadType::Handheld: + case NpadStyleIndex::Handheld: return Settings::ControllerType::Handheld; - case NpadType::GameCube: + case NpadStyleIndex::GameCube: return Settings::ControllerType::GameCube; default: return Settings::ControllerType::ProController; @@ -79,9 +79,9 @@ void EmulatedController::ReloadFromSettings() { // Other or debug controller should always be a pro controller if (npad_id_type != NpadIdType::Other) { - SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); } else { - SetNpadType(NpadType::ProController); + SetNpadStyleIndex(NpadStyleIndex::ProController); } if (player.connected) { @@ -306,7 +306,7 @@ void EmulatedController::DisableConfiguration() { if (is_connected) { Disconnect(); } - SetNpadType(tmp_npad_type); + SetNpadStyleIndex(tmp_npad_type); } // Apply temporary connected status to the real controller @@ -569,10 +569,10 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: } } if (!is_connected) { - if (npad_id_type == NpadIdType::Player1 && npad_type != NpadType::Handheld) { + if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { Connect(); } - if (npad_id_type == NpadIdType::Handheld && npad_type == NpadType::Handheld) { + if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) { Connect(); } } @@ -896,14 +896,14 @@ NpadIdType EmulatedController::GetNpadIdType() const { return npad_id_type; } -NpadType EmulatedController::GetNpadType(bool get_temporary_value) const { +NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { if (get_temporary_value) { return tmp_npad_type; } return npad_type; } -void EmulatedController::SetNpadType(NpadType npad_type_) { +void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { { std::lock_guard lock{mutex}; diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 9a8bdf14d..fa2e89c0b 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -142,23 +142,23 @@ public: YUZU_NON_MOVEABLE(EmulatedController); /// Converts the controller type from settings to npad type - static NpadType MapSettingsTypeToNPad(Settings::ControllerType type); + static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type); /// Converts npad type to the equivalent of controller type from settings - static Settings::ControllerType MapNPadToSettingsType(NpadType type); + static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type); /// Gets the NpadIdType for this controller NpadIdType GetNpadIdType() const; - /// Sets the NpadType for this controller - void SetNpadType(NpadType npad_type_); + /// Sets the NpadStyleIndex for this controller + void SetNpadStyleIndex(NpadStyleIndex npad_type_); /** - * Gets the NpadType for this controller + * Gets the NpadStyleIndex for this controller * @param If true tmp_npad_type will be returned - * @return NpadType set on the controller + * @return NpadStyleIndex set on the controller */ - NpadType GetNpadType(bool get_temporary_value = false) const; + NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; /// Sets the connected status to true void Connect(); @@ -351,14 +351,14 @@ private: void TriggerOnChange(ControllerTriggerType type, bool is_service_update); NpadIdType npad_id_type; - NpadType npad_type{NpadType::None}; + NpadStyleIndex npad_type{NpadStyleIndex::None}; bool is_connected{false}; bool is_configuring{false}; f32 motion_sensitivity{0.01f}; bool force_update_motion{false}; // Temporary values to avoid doing changes while the controller is on configuration mode - NpadType tmp_npad_type{NpadType::None}; + NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; bool tmp_is_connected{false}; ButtonParams button_params; diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index f8a0d5edd..7e4f6a804 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -84,8 +84,8 @@ constexpr NpadIdType IndexToNpadIdType(size_t index) { } } -// This is nn::hid::NpadType -enum class NpadType : u8 { +// This is nn::hid::NpadStyleIndex +enum class NpadStyleIndex : u8 { None = 0, ProController = 3, Handheld = 4, @@ -94,7 +94,14 @@ enum class NpadType : u8 { JoyconRight = 7, GameCube = 8, Pokeball = 9, - MaxNpadType = 10, + NES = 10, + HandheldNES = 11, + SNES = 12, + N64 = 13, + SegaGenesis = 14, + SystemExt = 32, + System = 33, + MaxNpadType = 34, }; // This is nn::hid::NpadStyleTag diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 0b5a23696..e4a3d9163 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -93,7 +93,7 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) { bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { return IsNpadIdValid(device_handle.npad_id) && - device_handle.npad_type < Core::HID::NpadType::MaxNpadType && + device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType && device_handle.device_index < DeviceIndex::MaxDeviceIndex; } @@ -134,7 +134,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, auto& controller = controller_data[controller_idx]; const auto is_connected = controller.device->IsConnected(); - const auto npad_type = controller.device->GetNpadType(); + const auto npad_type = controller.device->GetNpadStyleIndex(); switch (type) { case Core::HID::ControllerTriggerType::Connected: case Core::HID::ControllerTriggerType::Disconnected: @@ -161,9 +161,9 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { auto& controller = controller_data[controller_idx]; - const auto controller_type = controller.device->GetNpadType(); + const auto controller_type = controller.device->GetNpadStyleIndex(); auto& shared_memory = controller.shared_memory_entry; - if (controller_type == Core::HID::NpadType::None) { + if (controller_type == Core::HID::NpadStyleIndex::None) { controller.styleset_changed_event->GetWritableEvent().Signal(); return; } @@ -171,10 +171,10 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.device_type.raw = 0; shared_memory.system_properties.raw = 0; switch (controller_type) { - case Core::HID::NpadType::None: + case Core::HID::NpadStyleIndex::None: UNREACHABLE(); break; - case Core::HID::NpadType::ProController: + case Core::HID::NpadStyleIndex::ProController: shared_memory.style_set.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); @@ -183,7 +183,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; break; - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: shared_memory.style_set.handheld.Assign(1); shared_memory.device_type.handheld_left.Assign(1); shared_memory.device_type.handheld_right.Assign(1); @@ -193,7 +193,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; break; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: shared_memory.style_set.joycon_dual.Assign(1); shared_memory.device_type.joycon_left.Assign(1); shared_memory.device_type.joycon_right.Assign(1); @@ -203,7 +203,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; break; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: shared_memory.style_set.joycon_left.Assign(1); shared_memory.device_type.joycon_left.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1); @@ -211,7 +211,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: shared_memory.style_set.joycon_right.Assign(1); shared_memory.device_type.joycon_right.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1); @@ -219,14 +219,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: shared_memory.style_set.gamecube.Assign(1); // The GC Controller behaves like a wired Pro Controller shared_memory.device_type.fullkey.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); break; - case Core::HID::NpadType::Pokeball: + case Core::HID::NpadStyleIndex::Pokeball: shared_memory.style_set.palma.Assign(1); shared_memory.device_type.palma.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; @@ -307,7 +307,7 @@ void Controller_NPad::OnInit() { const auto& device = controller.device; if (device->IsConnected()) { const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType()); - AddNewControllerAt(device->GetNpadType(), index); + AddNewControllerAt(device->GetNpadStyleIndex(), index); } } } @@ -347,7 +347,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { std::lock_guard lock{mutex}; const auto controller_idx = NPadIdToIndex(npad_id); auto& controller = controller_data[controller_idx]; - const auto controller_type = controller.device->GetNpadType(); + const auto controller_type = controller.device->GetNpadStyleIndex(); if (!controller.device->IsConnected()) { return; } @@ -359,7 +359,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { using btn = Core::HID::NpadButton; pad_entry.npad_buttons.raw = btn::None; - if (controller_type != Core::HID::NpadType::JoyconLeft) { + if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | btn::StickRRight | btn::StickRDown; @@ -367,7 +367,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { pad_entry.r_stick = stick_state.right; } - if (controller_type != Core::HID::NpadType::JoyconRight) { + if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { constexpr btn left_button_mask = btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; @@ -375,17 +375,17 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { pad_entry.l_stick = stick_state.left; } - if (controller_type == Core::HID::NpadType::JoyconLeft) { + if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) { pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); } - if (controller_type == Core::HID::NpadType::JoyconRight) { + if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) { pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); } - if (controller_type == Core::HID::NpadType::GameCube) { + if (controller_type == Core::HID::NpadStyleIndex::GameCube) { const auto& trigger_state = controller.device->GetTriggers(); trigger_entry.l_analog = trigger_state.left; trigger_entry.r_analog = trigger_state.right; @@ -406,9 +406,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* auto& controller = controller_data[i]; auto& npad = controller.shared_memory_entry; - const auto& controller_type = controller.device->GetNpadType(); + const auto& controller_type = controller.device->GetNpadStyleIndex(); - if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { + if (controller_type == Core::HID::NpadStyleIndex::None || + !controller.device->IsConnected()) { // Refresh shared memory std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), &controller.shared_memory_entry, sizeof(NpadInternalState)); @@ -426,10 +427,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* libnx_state.connection_status.raw = 0; libnx_state.connection_status.is_connected.Assign(1); switch (controller_type) { - case Core::HID::NpadType::None: + case Core::HID::NpadStyleIndex::None: UNREACHABLE(); break; - case Core::HID::NpadType::ProController: + case Core::HID::NpadStyleIndex::ProController: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_wired.Assign(1); @@ -439,7 +440,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.fullkey_lifo.WriteNextEntry(pad_state); break; - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_wired.Assign(1); @@ -457,7 +458,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.handheld_lifo.WriteNextEntry(pad_state); break; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_left_connected.Assign(1); @@ -469,7 +470,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.joy_dual_lifo.WriteNextEntry(pad_state); break; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_left_connected.Assign(1); @@ -479,7 +480,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.joy_left_lifo.WriteNextEntry(pad_state); break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_right_connected.Assign(1); @@ -489,7 +490,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.joy_right_lifo.WriteNextEntry(pad_state); break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_wired.Assign(1); @@ -502,7 +503,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* npad.fullkey_lifo.WriteNextEntry(pad_state); npad.gc_trigger_lifo.WriteNextEntry(trigger_state); break; - case Core::HID::NpadType::Pokeball: + case Core::HID::NpadStyleIndex::Pokeball: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.sampling_number = @@ -534,9 +535,10 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; - const auto& controller_type = controller.device->GetNpadType(); + const auto& controller_type = controller.device->GetNpadStyleIndex(); - if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) { + if (controller_type == Core::HID::NpadStyleIndex::None || + !controller.device->IsConnected()) { continue; } @@ -557,10 +559,10 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing } switch (controller_type) { - case Core::HID::NpadType::None: + case Core::HID::NpadStyleIndex::None: UNREACHABLE(); break; - case Core::HID::NpadType::ProController: + case Core::HID::NpadStyleIndex::ProController: sixaxis_fullkey_state.attribute.raw = 0; if (sixaxis_sensors_enabled) { sixaxis_fullkey_state.attribute.is_connected.Assign(1); @@ -570,7 +572,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_fullkey_state.orientation = motion_state[0].orientation; } break; - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: sixaxis_handheld_state.attribute.raw = 0; if (sixaxis_sensors_enabled) { sixaxis_handheld_state.attribute.is_connected.Assign(1); @@ -580,7 +582,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_handheld_state.orientation = motion_state[0].orientation; } break; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: sixaxis_dual_left_state.attribute.raw = 0; sixaxis_dual_right_state.attribute.raw = 0; if (sixaxis_sensors_enabled) { @@ -600,7 +602,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_dual_right_state.orientation = motion_state[1].orientation; } break; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: sixaxis_left_lifo_state.attribute.raw = 0; if (sixaxis_sensors_enabled) { sixaxis_left_lifo_state.attribute.is_connected.Assign(1); @@ -610,7 +612,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_left_lifo_state.orientation = motion_state[0].orientation; } break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: sixaxis_right_lifo_state.attribute.raw = 0; if (sixaxis_sensors_enabled) { sixaxis_right_lifo_state.attribute.is_connected.Assign(1); @@ -779,11 +781,11 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han } // Some games try to send mismatched parameters in the device handle, block these. - if ((controller.device->GetNpadType() == Core::HID::NpadType::JoyconLeft && - (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconRight || + if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && + (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || vibration_device_handle.device_index == DeviceIndex::Right)) || - (controller.device->GetNpadType() == Core::HID::NpadType::JoyconRight && - (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconLeft || + (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && + (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || vibration_device_handle.device_index == DeviceIndex::Left))) { return; } @@ -876,11 +878,12 @@ void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { controller.styleset_changed_event->GetWritableEvent().Signal(); } -void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index) { +void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, + std::size_t npad_index) { UpdateControllerAt(controller, npad_index, true); } -void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index, +void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, std::size_t npad_index, bool connected) { auto& controller = controller_data[npad_index]; if (!connected) { @@ -888,7 +891,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t n return; } - controller.device->SetNpadType(type); + controller.device->SetNpadStyleIndex(type); InitNewlyAddedController(npad_index); } @@ -971,13 +974,13 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { // If the controllers at both npad indices form a pair of left and right joycons, merge them. // Otherwise, do nothing. - if ((controller_1->GetNpadType() == Core::HID::NpadType::JoyconLeft && - controller_2->GetNpadType() == Core::HID::NpadType::JoyconRight) || - (controller_2->GetNpadType() == Core::HID::NpadType::JoyconLeft && - controller_1->GetNpadType() == Core::HID::NpadType::JoyconRight)) { + if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && + controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) || + (controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && + controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) { // Disconnect the joycon at the second id and connect the dual joycon at the first index. DisconnectNpad(npad_id_2); - AddNewControllerAt(Core::HID::NpadType::JoyconDual, npad_index_1); + AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_index_1); } } @@ -1000,8 +1003,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { const auto npad_index_2 = NPadIdToIndex(npad_id_2); const auto& controller_1 = controller_data[npad_index_1].device; const auto& controller_2 = controller_data[npad_index_2].device; - const auto type_index_1 = controller_1->GetNpadType(); - const auto type_index_2 = controller_2->GetNpadType(); + const auto type_index_1 = controller_1->GetNpadStyleIndex(); + const auto type_index_2 = controller_2->GetNpadStyleIndex(); if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) { return false; @@ -1039,9 +1042,9 @@ void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { void Controller_NPad::ClearAllConnectedControllers() { for (auto& controller : controller_data) { if (controller.device->IsConnected() && - controller.device->GetNpadType() != Core::HID::NpadType::None) { - controller.device->SetNpadType(Core::HID::NpadType::None); + controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { controller.device->Disconnect(); + controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); } } } @@ -1054,7 +1057,7 @@ void Controller_NPad::DisconnectAllConnectedControllers() { void Controller_NPad::ConnectAllDisconnectedControllers() { for (auto& controller : controller_data) { - if (controller.device->GetNpadType() != Core::HID::NpadType::None && + if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && !controller.device->IsConnected()) { controller.device->Connect(); } @@ -1063,8 +1066,8 @@ void Controller_NPad::ConnectAllDisconnectedControllers() { void Controller_NPad::ClearAllControllers() { for (auto& controller : controller_data) { - controller.device->SetNpadType(Core::HID::NpadType::None); controller.device->Disconnect(); + controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); } } @@ -1072,8 +1075,8 @@ u32 Controller_NPad::GetAndResetPressState() { return press_state.exchange(0); } -bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) const { - if (controller == Core::HID::NpadType::Handheld) { +bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { + if (controller == Core::HID::NpadStyleIndex::Handheld) { const bool support_handheld = std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) != supported_npad_id_types.end(); @@ -1093,17 +1096,17 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) cons [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { Core::HID::NpadStyleTag style = GetSupportedStyleSet(); switch (controller) { - case Core::HID::NpadType::ProController: + case Core::HID::NpadStyleIndex::ProController: return style.fullkey; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: return style.joycon_dual; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: return style.joycon_left; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: return style.joycon_right; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: return style.gamecube; - case Core::HID::NpadType::Pokeball: + case Core::HID::NpadStyleIndex::Pokeball: return style.palma; default: return false; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 871d245fd..512fb5afc 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -96,7 +96,7 @@ public: }; struct DeviceHandle { - Core::HID::NpadType npad_type; + Core::HID::NpadStyleIndex npad_type; u8 npad_id; DeviceIndex device_index; INSERT_PADDING_BYTES_NOINIT(1); @@ -160,9 +160,10 @@ public: void SignalStyleSetChangedEvent(u32 npad_id) const; // Adds a new controller at an index. - void AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index); + void AddNewControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index); // Adds a new controller at an index with connection status. - void UpdateControllerAt(Core::HID::NpadType controller, std::size_t npad_index, bool connected); + void UpdateControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index, + bool connected); void DisconnectNpad(u32 npad_id); void DisconnectNpadAtIndex(std::size_t index); @@ -496,7 +497,7 @@ private: std::array vibration{}; bool unintended_home_button_input_protection{}; bool is_connected{}; - Core::HID::NpadType npad_type{Core::HID::NpadType::None}; + Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; // Current pad state NPadGenericState npad_pad_state{}; @@ -513,7 +514,7 @@ private: void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); void InitNewlyAddedController(std::size_t controller_idx); - bool IsControllerSupported(Core::HID::NpadType controller) const; + bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const; void RequestPadStateUpdate(u32 npad_id); void WriteEmptyEntry(NpadInternalState& npad); diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ac48f96d3..648e69de9 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1131,18 +1131,18 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { Core::HID::VibrationDeviceInfo vibration_device_info; switch (vibration_device_handle.npad_type) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::Handheld: - case Core::HID::NpadType::JoyconDual: - case Core::HID::NpadType::JoyconLeft: - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconRight: default: vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm; break; - case Core::HID::NpadType::Pokeball: + case Core::HID::NpadStyleIndex::Pokeball: vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown; break; } -- cgit v1.2.3 From d14e74132ceaa8b5efef8a7d543cb50429cb4fb3 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 4 Nov 2021 13:08:30 -0600 Subject: settings: Fix controller preview not displaying the correct controller --- src/core/hid/emulated_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index a200992f2..a9038e06f 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -880,7 +880,7 @@ void EmulatedController::Disconnect() { } bool EmulatedController::IsConnected(bool get_temporary_value) const { - if (get_temporary_value) { + if (get_temporary_value && is_configuring) { return tmp_is_connected; } return is_connected; @@ -897,7 +897,7 @@ NpadIdType EmulatedController::GetNpadIdType() const { } NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { - if (get_temporary_value) { + if (get_temporary_value && is_configuring) { return tmp_npad_type; } return npad_type; -- cgit v1.2.3 From b21fcd952721af357d50d487ffba9580e5a6bf00 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 4 Nov 2021 14:43:08 -0600 Subject: service/hid: Add support for new controllers --- src/core/hid/hid_types.h | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 31 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 7e4f6a804..22177b5ed 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -89,13 +89,13 @@ enum class NpadStyleIndex : u8 { None = 0, ProController = 3, Handheld = 4, + HandheldNES = 4, JoyconDual = 5, JoyconLeft = 6, JoyconRight = 7, GameCube = 8, Pokeball = 9, NES = 10, - HandheldNES = 11, SNES = 12, N64 = 13, SegaGenesis = 14, diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e4a3d9163..fcc36bbc1 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -221,7 +221,6 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { break; case Core::HID::NpadStyleIndex::GameCube: shared_memory.style_set.gamecube.Assign(1); - // The GC Controller behaves like a wired Pro Controller shared_memory.device_type.fullkey.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); @@ -231,6 +230,24 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.device_type.palma.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; break; + case Core::HID::NpadStyleIndex::NES: + shared_memory.style_set.lark.Assign(1); + shared_memory.device_type.fullkey.Assign(1); + break; + case Core::HID::NpadStyleIndex::SNES: + shared_memory.style_set.lucia.Assign(1); + shared_memory.device_type.fullkey.Assign(1); + shared_memory.applet_footer.type = AppletFooterUiType::Lucia; + break; + case Core::HID::NpadStyleIndex::N64: + shared_memory.style_set.lagoon.Assign(1); + shared_memory.device_type.fullkey.Assign(1); + shared_memory.applet_footer.type = AppletFooterUiType::Lagon; + break; + case Core::HID::NpadStyleIndex::SegaGenesis: + shared_memory.style_set.lager.Assign(1); + shared_memory.device_type.fullkey.Assign(1); + break; default: break; } @@ -431,6 +448,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* UNREACHABLE(); break; case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::NES: + case Core::HID::NpadStyleIndex::SNES: + case Core::HID::NpadStyleIndex::N64: + case Core::HID::NpadStyleIndex::SegaGenesis: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); pad_state.connection_status.is_wired.Assign(1); @@ -1108,6 +1129,14 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller return style.gamecube; case Core::HID::NpadStyleIndex::Pokeball: return style.palma; + case Core::HID::NpadStyleIndex::NES: + return style.lark; + case Core::HID::NpadStyleIndex::SNES: + return style.lucia; + case Core::HID::NpadStyleIndex::N64: + return style.lagoon; + case Core::HID::NpadStyleIndex::SegaGenesis: + return style.lager; default: return false; } -- cgit v1.2.3 From e7eee36d52259321b938c350cb37a3b115953229 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 4 Nov 2021 19:05:58 -0600 Subject: service/hid: Remove includes of core.h and settings.h --- src/core/hid/emulated_console.cpp | 1 + src/core/hid/emulated_console.h | 1 - src/core/hid/emulated_devices.h | 3 +-- src/core/hle/service/hid/controllers/console_sixaxis.cpp | 8 ++++---- src/core/hle/service/hid/controllers/console_sixaxis.h | 8 ++++++-- src/core/hle/service/hid/controllers/controller_base.cpp | 2 +- src/core/hle/service/hid/controllers/controller_base.h | 8 ++++---- src/core/hle/service/hid/controllers/debug_pad.cpp | 6 +++--- src/core/hle/service/hid/controllers/debug_pad.h | 3 +-- src/core/hle/service/hid/controllers/gesture.cpp | 5 ++--- src/core/hle/service/hid/controllers/gesture.h | 2 +- src/core/hle/service/hid/controllers/keyboard.cpp | 6 +++--- src/core/hle/service/hid/controllers/keyboard.h | 3 +-- src/core/hle/service/hid/controllers/mouse.cpp | 5 ++--- src/core/hle/service/hid/controllers/mouse.h | 3 +-- src/core/hle/service/hid/controllers/npad.cpp | 15 +++++++-------- src/core/hle/service/hid/controllers/npad.h | 3 +-- src/core/hle/service/hid/controllers/stubbed.cpp | 3 ++- src/core/hle/service/hid/controllers/stubbed.h | 2 +- src/core/hle/service/hid/controllers/touchscreen.cpp | 7 +++++-- src/core/hle/service/hid/controllers/touchscreen.h | 8 +++++--- src/core/hle/service/hid/controllers/xpad.cpp | 3 ++- src/core/hle/service/hid/controllers/xpad.h | 2 +- src/core/hle/service/hid/hid.cpp | 1 + src/core/hle/service/hid/hid.h | 4 ++-- 25 files changed, 58 insertions(+), 54 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index b51c72eae..864481f52 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included +#include "common/settings.h" #include "core/hid/emulated_console.h" #include "core/hid/input_converter.h" diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 9aec482a6..25c183eee 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -15,7 +15,6 @@ #include "common/param_package.h" #include "common/point.h" #include "common/quaternion.h" -#include "common/settings.h" #include "common/vector_math.h" #include "core/hid/hid_types.h" #include "core/hid/motion_input.h" diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 418b2f9b5..d49d6d78a 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -15,7 +15,6 @@ #include "common/param_package.h" #include "common/settings.h" #include "core/hid/hid_types.h" -#include "core/hid/motion_input.h" namespace Core::HID { @@ -103,7 +102,7 @@ public: /// Reverts any mapped changes made that weren't saved void RestoreConfig(); - /// Returns the current mapped motion device + /// Returns the current mapped mouse button device Common::ParamPackage GetMouseButtonParam(std::size_t index) const; /** diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index 2bebcf0d0..ea7e8f18f 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -3,17 +3,17 @@ // Refer to the license.txt file included. #include "common/settings.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/hid/emulated_console.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/console_sixaxis.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; -Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_) - : ControllerBase{system_} { - console = system.HIDCore().GetEmulatedConsole(); +Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_) + : ControllerBase{hid_core_} { + console = hid_core.GetEmulatedConsole(); } Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index 95729e6b2..7c92413e8 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -5,16 +5,20 @@ #pragma once #include + #include "common/common_types.h" #include "common/quaternion.h" -#include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" +namespace Core::HID { +class EmulatedConsole; +} // namespace Core::HID + namespace Service::HID { class Controller_ConsoleSixAxis final : public ControllerBase { public: - explicit Controller_ConsoleSixAxis(Core::System& system_); + explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_); ~Controller_ConsoleSixAxis() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index 74a394784..788ae9ae7 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp @@ -6,7 +6,7 @@ namespace Service::HID { -ControllerBase::ControllerBase(Core::System& system_) : system(system_) {} +ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} ControllerBase::~ControllerBase() = default; void ControllerBase::ActivateController() { diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 4ba2eda1a..8125bbc84 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -11,14 +11,14 @@ namespace Core::Timing { class CoreTiming; } -namespace Core { -class System; +namespace Core::HID { +class HIDCore; } namespace Service::HID { class ControllerBase { public: - explicit ControllerBase(Core::System& system_); + explicit ControllerBase(Core::HID::HIDCore& hid_core_); virtual ~ControllerBase(); // Called when the controller is initialized @@ -44,6 +44,6 @@ public: protected: bool is_activated{false}; - Core::System& system; + Core::HID::HIDCore& hid_core; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 86b95f2c8..6a6fb9cab 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -5,7 +5,6 @@ #include #include "common/common_types.h" #include "common/settings.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" @@ -15,8 +14,9 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; -Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} { - controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other); +Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_) + : ControllerBase{hid_core_} { + controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); } Controller_DebugPad::~Controller_DebugPad() = default; diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index bd0f15eaa..15b3afb7a 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -8,7 +8,6 @@ #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" -#include "common/settings.h" #include "common/swap.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" @@ -22,7 +21,7 @@ struct AnalogStickState; namespace Service::HID { class Controller_DebugPad final : public ControllerBase { public: - explicit Controller_DebugPad(Core::System& system_); + explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_); ~Controller_DebugPad() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 00df50f32..fe895c4f6 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -5,7 +5,6 @@ #include "common/logging/log.h" #include "common/math_util.h" #include "common/settings.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" #include "core/hid/hid_core.h" @@ -25,8 +24,8 @@ constexpr f32 Square(s32 num) { return static_cast(num * num); } -Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) { - console = system.HIDCore().GetEmulatedConsole(); +Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { + console = hid_core.GetEmulatedConsole(); } Controller_Gesture::~Controller_Gesture() = default; diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 9bffde438..f924464e0 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -15,7 +15,7 @@ namespace Service::HID { class Controller_Gesture final : public ControllerBase { public: - explicit Controller_Gesture(Core::System& system_); + explicit Controller_Gesture(Core::HID::HIDCore& hid_core_); ~Controller_Gesture() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index acea68e24..1dc219bf5 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -5,7 +5,6 @@ #include #include "common/common_types.h" #include "common/settings.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" @@ -14,8 +13,9 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; -Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} { - emulated_devices = system.HIDCore().GetEmulatedDevices(); +Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_) + : ControllerBase{hid_core_} { + emulated_devices = hid_core.GetEmulatedDevices(); } Controller_Keyboard::~Controller_Keyboard() = default; diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index aba4f123e..ec5dd607c 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -8,7 +8,6 @@ #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" -#include "common/settings.h" #include "common/swap.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" @@ -22,7 +21,7 @@ struct KeyboardKey; namespace Service::HID { class Controller_Keyboard final : public ControllerBase { public: - explicit Controller_Keyboard(Core::System& system_); + explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_); ~Controller_Keyboard() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 21f7e48bb..83e69ca94 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -4,7 +4,6 @@ #include #include "common/common_types.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" #include "core/hid/emulated_devices.h" @@ -14,8 +13,8 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; -Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} { - emulated_devices = system.HIDCore().GetEmulatedDevices(); +Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { + emulated_devices = hid_core.GetEmulatedDevices(); } Controller_Mouse::~Controller_Mouse() = default; diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index ce868a247..25017f117 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -7,7 +7,6 @@ #include #include "common/bit_field.h" #include "common/common_types.h" -#include "common/settings.h" #include "common/swap.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" @@ -20,7 +19,7 @@ struct MouseState; namespace Service::HID { class Controller_Mouse final : public ControllerBase { public: - explicit Controller_Mouse(Core::System& system_); + explicit Controller_Mouse(Core::HID::HIDCore& hid_core_); ~Controller_Mouse() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index fcc36bbc1..b97e575f3 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -10,7 +10,6 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/settings.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" @@ -97,12 +96,12 @@ bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { device_handle.device_index < DeviceIndex::MaxDeviceIndex; } -Controller_NPad::Controller_NPad(Core::System& system_, +Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) - : ControllerBase{system_}, service_context{service_context_} { + : ControllerBase{hid_core_}, service_context{service_context_} { for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; - controller.device = system.HIDCore().GetEmulatedControllerByIndex(i); + controller.device = hid_core.GetEmulatedControllerByIndex(i); controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE; controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value = @@ -284,7 +283,7 @@ void Controller_NPad::OnInit() { service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); } - if (system.HIDCore().GetSupportedStyleTag().raw == 0) { + if (hid_core.GetSupportedStyleTag().raw == 0) { // We want to support all controllers Core::HID::NpadStyleTag style{}; style.handheld.Assign(1); @@ -294,7 +293,7 @@ void Controller_NPad::OnInit() { style.fullkey.Assign(1); style.gamecube.Assign(1); style.palma.Assign(1); - system.HIDCore().SetSupportedStyleTag(style); + hid_core.SetSupportedStyleTag(style); } supported_npad_id_types.resize(npad_id_list.size()); @@ -678,11 +677,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing } void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) { - system.HIDCore().SetSupportedStyleTag(style_set); + hid_core.SetSupportedStyleTag(style_set); } Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { - return system.HIDCore().GetSupportedStyleTag(); + return hid_core.GetSupportedStyleTag(); } void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 512fb5afc..a996755ed 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -11,7 +11,6 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "common/quaternion.h" -#include "common/settings.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" @@ -37,7 +36,7 @@ constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this? class Controller_NPad final : public ControllerBase { public: - explicit Controller_NPad(Core::System& system_, + explicit Controller_NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); ~Controller_NPad() override; diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index a8c93909d..b7d7a5756 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -5,11 +5,12 @@ #include #include "common/common_types.h" #include "core/core_timing.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/stubbed.h" namespace Service::HID { -Controller_Stubbed::Controller_Stubbed(Core::System& system_) : ControllerBase{system_} {} +Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} Controller_Stubbed::~Controller_Stubbed() = default; void Controller_Stubbed::OnInit() {} diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index 10aecad4c..0044a4efa 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -10,7 +10,7 @@ namespace Service::HID { class Controller_Stubbed final : public ControllerBase { public: - explicit Controller_Stubbed(Core::System& system_); + explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_); ~Controller_Stubbed() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 9ae2bf2b1..48978e5c6 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -10,13 +10,16 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/hid/emulated_console.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/touchscreen.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; -Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} { - console = system.HIDCore().GetEmulatedConsole(); +Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_) + : ControllerBase{hid_core_} { + console = hid_core.GetEmulatedConsole(); } Controller_Touchscreen::~Controller_Touchscreen() = default; diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 50dadd25f..135c2bf13 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -9,12 +9,14 @@ #include "common/common_types.h" #include "common/point.h" #include "common/swap.h" -#include "core/hid/emulated_console.h" -#include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/ring_lifo.h" +namespace Core::HID { +class EmulatedConsole; +} // namespace Core::HID + namespace Service::HID { class Controller_Touchscreen final : public ControllerBase { public: @@ -34,7 +36,7 @@ public: static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17, "TouchScreenConfigurationForNx is an invalid size"); - explicit Controller_Touchscreen(Core::System& system_); + explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_); ~Controller_Touchscreen() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index a2ed1e7c2..e4da16466 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -5,12 +5,13 @@ #include #include "common/common_types.h" #include "core/core_timing.h" +#include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/xpad.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; -Controller_XPad::Controller_XPad(Core::System& system_) : ControllerBase{system_} {} +Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} Controller_XPad::~Controller_XPad() = default; void Controller_XPad::OnInit() {} diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index 75e0d2911..54dae0be1 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -15,7 +15,7 @@ namespace Service::HID { class Controller_XPad final : public ControllerBase { public: - explicit Controller_XPad(Core::System& system_); + explicit Controller_XPad(Core::HID::HIDCore& hid_core_); ~Controller_XPad() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 648e69de9..96e8fb7e1 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -8,6 +8,7 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hid/hid_core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 2e0c33c1c..973e6a8ac 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -60,12 +60,12 @@ public: private: template void MakeController(HidController controller) { - controllers[static_cast(controller)] = std::make_unique(system); + controllers[static_cast(controller)] = std::make_unique(system.HIDCore()); } template void MakeControllerWithServiceContext(HidController controller) { controllers[static_cast(controller)] = - std::make_unique(system, service_context); + std::make_unique(system.HIDCore(), service_context); } void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); -- cgit v1.2.3 From 71f9b90dd90c442425900ee16af8b4e39ac54aed Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 8 Nov 2021 20:28:09 -0600 Subject: core/hid: Remove usage of native types, fix a couple of errors with motion --- src/core/hid/emulated_console.cpp | 2 +- src/core/hid/emulated_controller.cpp | 4 +- src/core/hid/emulated_controller.h | 4 +- src/core/hid/hid_types.h | 67 ++- .../hle/service/am/applets/applet_controller.cpp | 1 + .../hle/service/am/applets/applet_controller.h | 6 +- src/core/hle/service/hid/controllers/npad.cpp | 498 ++++++++++++--------- src/core/hle/service/hid/controllers/npad.h | 161 +++---- src/core/hle/service/hid/hid.cpp | 289 ++++++------ 9 files changed, 613 insertions(+), 419 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 864481f52..374dd5d41 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -152,7 +152,7 @@ void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) { motion.rotation = emulated.GetGyroscope(); motion.orientation = emulated.GetOrientation(); motion.quaternion = emulated.GetQuaternion(); - motion.is_at_rest = emulated.IsMoving(motion_sensitivity); + motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); TriggerOnChange(ConsoleTriggerType::Motion); } diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index a9038e06f..54c1a2324 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -347,7 +347,7 @@ void EmulatedController::RestoreConfig() { } std::vector EmulatedController::GetMappedDevices( - DeviceIndex device_index) const { + EmulatedDeviceIndex device_index) const { std::vector devices; for (const auto& param : button_params) { if (!param.Has("engine")) { @@ -704,7 +704,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: motion.gyro = emulated.GetGyroscope(); motion.rotation = emulated.GetRotations(); motion.orientation = emulated.GetOrientation(); - motion.is_at_rest = emulated.IsMoving(motion_sensitivity); + motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); TriggerOnChange(ControllerTriggerType::Motion, true); } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index fa2e89c0b..2c5d51bc8 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -81,7 +81,7 @@ struct ControllerMotion { bool is_at_rest{}; }; -enum DeviceIndex : u8 { +enum EmulatedDeviceIndex : u8 { LeftIndex, RightIndex, DualIndex, @@ -202,7 +202,7 @@ public: void RestoreConfig(); /// Returns a vector of mapped devices from the mapped button and stick parameters - std::vector GetMappedDevices(DeviceIndex device_index) const; + std::vector GetMappedDevices(EmulatedDeviceIndex device_index) const; // Returns the current mapped button device Common::ParamPackage GetButtonParam(std::size_t index) const; diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 22177b5ed..f224cb744 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -13,7 +13,7 @@ namespace Core::HID { // This is nn::hid::NpadIdType -enum class NpadIdType : u8 { +enum class NpadIdType : u32 { Player1 = 0x0, Player2 = 0x1, Player3 = 0x2, @@ -25,7 +25,7 @@ enum class NpadIdType : u8 { Other = 0x10, Handheld = 0x20, - Invalid = 0xFF, + Invalid = 0xFFFFFFFF, }; /// Converts a NpadIdType to an array index. @@ -104,10 +104,30 @@ enum class NpadStyleIndex : u8 { MaxNpadType = 34, }; +// This is nn::hid::NpadStyleSet +enum class NpadStyleSet : u32 { + None = 0, + Fullkey = 1U << 0, + Handheld = 1U << 1, + JoyDual = 1U << 2, + JoyLeft = 1U << 3, + JoyRight = 1U << 4, + Gc = 1U << 5, + Palma = 1U << 6, + Lark = 1U << 7, + HandheldLark = 1U << 8, + Lucia = 1U << 9, + Lagoon = 1U << 10, + Lager = 1U << 11, + SystemExt = 1U << 29, + System = 1U << 30, +}; +static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); + // This is nn::hid::NpadStyleTag struct NpadStyleTag { union { - u32 raw{}; + NpadStyleSet raw{}; BitField<0, 1, u32> fullkey; BitField<1, 1, u32> handheld; @@ -322,6 +342,47 @@ struct DebugPadButton { }; static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); +enum class DeviceIndex : u8 { + Left = 0, + Right = 1, + None = 2, + MaxDeviceIndex = 3, +}; + +// This is nn::hid::ConsoleSixAxisSensorHandle +struct ConsoleSixAxisSensorHandle { + u8 unknown_1; + u8 unknown_2; + INSERT_PADDING_BYTES_NOINIT(2); +}; +static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4, + "ConsoleSixAxisSensorHandle is an invalid size"); + +// This is nn::hid::SixAxisSensorHandle +struct SixAxisSensorHandle { + NpadStyleIndex npad_type; + u8 npad_id; + DeviceIndex device_index; + INSERT_PADDING_BYTES_NOINIT(1); +}; +static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size"); + +struct SixAxisSensorFusionParameters { + f32 parameter1; + f32 parameter2; +}; +static_assert(sizeof(SixAxisSensorFusionParameters) == 8, + "SixAxisSensorFusionParameters is an invalid size"); + +// This is nn::hid::VibrationDeviceHandle +struct VibrationDeviceHandle { + NpadStyleIndex npad_type; + u8 npad_id; + DeviceIndex device_index; + INSERT_PADDING_BYTES_NOINIT(1); +}; +static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); + // This is nn::hid::VibrationDeviceType enum class VibrationDeviceType : u32 { Unknown = 0, diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 374e0c7f4..d073f2210 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp @@ -12,6 +12,7 @@ #include "core/frontend/applets/controller.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" #include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_controller.h" diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h index 0a34c4fc0..1a832505e 100644 --- a/src/core/hle/service/am/applets/applet_controller.h +++ b/src/core/hle/service/am/applets/applet_controller.h @@ -16,6 +16,10 @@ namespace Core { class System; } +namespace Core::HID { +enum class NpadStyleSet : u32; +} + namespace Service::AM::Applets { using IdentificationColor = std::array; @@ -52,7 +56,7 @@ struct ControllerSupportArgPrivate { bool flag_1{}; ControllerSupportMode mode{}; ControllerSupportCaller caller{}; - u32 style_set{}; + Core::HID::NpadStyleSet style_set{}; u32 joy_hold_type{}; }; static_assert(sizeof(ControllerSupportArgPrivate) == 0x14, diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index b97e575f3..eaec79139 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -21,68 +21,25 @@ namespace Service::HID { constexpr std::size_t NPAD_OFFSET = 0x9A00; -constexpr u32 MAX_NPAD_ID = 7; -constexpr std::size_t HANDHELD_INDEX = 8; -constexpr std::array npad_id_list{ - 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, +constexpr std::array npad_id_list{ + Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3, + Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6, + Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other, + Core::HID::NpadIdType::Handheld, }; -std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { +bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) { switch (npad_id) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - return npad_id; - case HANDHELD_INDEX: - case NPAD_HANDHELD: - return HANDHELD_INDEX; - case 9: - case NPAD_UNKNOWN: - return 9; - default: - UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id); - return 0; - } -} - -u32 Controller_NPad::IndexToNPad(std::size_t index) { - switch (index) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - return static_cast(index); - case HANDHELD_INDEX: - return NPAD_HANDHELD; - case 9: - return NPAD_UNKNOWN; - default: - UNIMPLEMENTED_MSG("Unknown npad index {}", index); - return 0; - } -} - -bool Controller_NPad::IsNpadIdValid(u32 npad_id) { - switch (npad_id) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case NPAD_UNKNOWN: - case NPAD_HANDHELD: + case Core::HID::NpadIdType::Player1: + case Core::HID::NpadIdType::Player2: + case Core::HID::NpadIdType::Player3: + case Core::HID::NpadIdType::Player4: + case Core::HID::NpadIdType::Player5: + case Core::HID::NpadIdType::Player6: + case Core::HID::NpadIdType::Player7: + case Core::HID::NpadIdType::Player8: + case Core::HID::NpadIdType::Other: + case Core::HID::NpadIdType::Handheld: return true; default: LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id); @@ -90,10 +47,16 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) { } } -bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { - return IsNpadIdValid(device_handle.npad_id) && +bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) { + return IsNpadIdValid(static_cast(device_handle.npad_id)) && + device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType && + device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; +} + +bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) { + return IsNpadIdValid(static_cast(device_handle.npad_id)) && device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType && - device_handle.device_index < DeviceIndex::MaxDeviceIndex; + device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; } Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, @@ -102,9 +65,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; controller.device = hid_core.GetEmulatedControllerByIndex(i); - controller.vibration[Core::HID::DeviceIndex::LeftIndex].latest_vibration_value = + controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE; - controller.vibration[Core::HID::DeviceIndex::RightIndex].latest_vibration_value = + controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value = DEFAULT_VIBRATION_VALUE; Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this, @@ -130,17 +93,21 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); return; } + if (controller_idx >= controller_data.size()) { + return; + } auto& controller = controller_data[controller_idx]; const auto is_connected = controller.device->IsConnected(); const auto npad_type = controller.device->GetNpadStyleIndex(); + const auto npad_id = controller.device->GetNpadIdType(); switch (type) { case Core::HID::ControllerTriggerType::Connected: case Core::HID::ControllerTriggerType::Disconnected: if (is_connected == controller.is_connected) { return; } - UpdateControllerAt(npad_type, controller_idx, is_connected); + UpdateControllerAt(npad_type, npad_id, is_connected); break; case Core::HID::ControllerTriggerType::Battery: { if (!controller.is_connected) { @@ -158,15 +125,16 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, } } -void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { - auto& controller = controller_data[controller_idx]; +void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { + LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); + auto& controller = GetControllerFromNpadIdType(npad_id); const auto controller_type = controller.device->GetNpadStyleIndex(); auto& shared_memory = controller.shared_memory_entry; if (controller_type == Core::HID::NpadStyleIndex::None) { controller.styleset_changed_event->GetWritableEvent().Signal(); return; } - shared_memory.style_set.raw = 0; // Zero out + shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None; shared_memory.device_type.raw = 0; shared_memory.system_properties.raw = 0; switch (controller_type) { @@ -174,7 +142,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { UNREACHABLE(); break; case Core::HID::NpadStyleIndex::ProController: - shared_memory.style_set.fullkey.Assign(1); + shared_memory.style_tag.fullkey.Assign(1); shared_memory.device_type.fullkey.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); @@ -183,7 +151,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; break; case Core::HID::NpadStyleIndex::Handheld: - shared_memory.style_set.handheld.Assign(1); + shared_memory.style_tag.handheld.Assign(1); shared_memory.device_type.handheld_left.Assign(1); shared_memory.device_type.handheld_right.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); @@ -193,7 +161,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; break; case Core::HID::NpadStyleIndex::JoyconDual: - shared_memory.style_set.joycon_dual.Assign(1); + shared_memory.style_tag.joycon_dual.Assign(1); shared_memory.device_type.joycon_left.Assign(1); shared_memory.device_type.joycon_right.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); @@ -203,7 +171,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; break; case Core::HID::NpadStyleIndex::JoyconLeft: - shared_memory.style_set.joycon_left.Assign(1); + shared_memory.style_tag.joycon_left.Assign(1); shared_memory.device_type.joycon_left.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.use_minus.Assign(1); @@ -211,7 +179,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; break; case Core::HID::NpadStyleIndex::JoyconRight: - shared_memory.style_set.joycon_right.Assign(1); + shared_memory.style_tag.joycon_right.Assign(1); shared_memory.device_type.joycon_right.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.use_plus.Assign(1); @@ -219,32 +187,32 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; break; case Core::HID::NpadStyleIndex::GameCube: - shared_memory.style_set.gamecube.Assign(1); + shared_memory.style_tag.gamecube.Assign(1); shared_memory.device_type.fullkey.Assign(1); shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); break; case Core::HID::NpadStyleIndex::Pokeball: - shared_memory.style_set.palma.Assign(1); + shared_memory.style_tag.palma.Assign(1); shared_memory.device_type.palma.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; break; case Core::HID::NpadStyleIndex::NES: - shared_memory.style_set.lark.Assign(1); + shared_memory.style_tag.lark.Assign(1); shared_memory.device_type.fullkey.Assign(1); break; case Core::HID::NpadStyleIndex::SNES: - shared_memory.style_set.lucia.Assign(1); + shared_memory.style_tag.lucia.Assign(1); shared_memory.device_type.fullkey.Assign(1); shared_memory.applet_footer.type = AppletFooterUiType::Lucia; break; case Core::HID::NpadStyleIndex::N64: - shared_memory.style_set.lagoon.Assign(1); + shared_memory.style_tag.lagoon.Assign(1); shared_memory.device_type.fullkey.Assign(1); shared_memory.applet_footer.type = AppletFooterUiType::Lagon; break; case Core::HID::NpadStyleIndex::SegaGenesis: - shared_memory.style_set.lager.Assign(1); + shared_memory.style_tag.lager.Assign(1); shared_memory.device_type.fullkey.Assign(1); break; default: @@ -268,7 +236,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.is_connected = true; controller.device->Connect(); - SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); + SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory_entry); } @@ -283,7 +251,7 @@ void Controller_NPad::OnInit() { service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i)); } - if (hid_core.GetSupportedStyleTag().raw == 0) { + if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) { // We want to support all controllers Core::HID::NpadStyleTag style{}; style.handheld.Assign(1); @@ -298,7 +266,7 @@ void Controller_NPad::OnInit() { supported_npad_id_types.resize(npad_id_list.size()); std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), - npad_id_list.size() * sizeof(u32)); + npad_id_list.size() * sizeof(Core::HID::NpadIdType)); // Prefill controller buffers for (auto& controller : controller_data) { @@ -322,8 +290,7 @@ void Controller_NPad::OnInit() { for (auto& controller : controller_data) { const auto& device = controller.device; if (device->IsConnected()) { - const std::size_t index = Core::HID::NpadIdTypeToIndex(device->GetNpadIdType()); - AddNewControllerAt(device->GetNpadStyleIndex(), index); + AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType()); } } } @@ -354,15 +321,14 @@ void Controller_NPad::OnRelease() { auto& controller = controller_data[i]; service_context.CloseEvent(controller.styleset_changed_event); for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { - VibrateControllerAtIndex(i, device_idx, {}); + VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {}); } } } -void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { +void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { std::lock_guard lock{mutex}; - const auto controller_idx = NPadIdToIndex(npad_id); - auto& controller = controller_data[controller_idx]; + auto& controller = GetControllerFromNpadIdType(npad_id); const auto controller_type = controller.device->GetNpadStyleIndex(); if (!controller.device->IsConnected()) { return; @@ -431,9 +397,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* &controller.shared_memory_entry, sizeof(NpadInternalState)); continue; } - const u32 npad_index = static_cast(i); - RequestPadStateUpdate(npad_index); + RequestPadStateUpdate(controller.device->GetNpadIdType()); auto& pad_state = controller.npad_pad_state; auto& libnx_state = controller.npad_libnx_state; auto& trigger_state = controller.npad_trigger_state; @@ -571,10 +536,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; - if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { - sixaxis_at_rest = true; + if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) { + controller.sixaxis_at_rest = true; for (std::size_t e = 0; e < motion_state.size(); ++e) { - sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest; + controller.sixaxis_at_rest = + controller.sixaxis_at_rest && motion_state[e].is_at_rest; } } @@ -584,7 +550,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing break; case Core::HID::NpadStyleIndex::ProController: sixaxis_fullkey_state.attribute.raw = 0; - if (sixaxis_sensors_enabled) { + if (controller.sixaxis_sensor_enabled) { sixaxis_fullkey_state.attribute.is_connected.Assign(1); sixaxis_fullkey_state.accel = motion_state[0].accel; sixaxis_fullkey_state.gyro = motion_state[0].gyro; @@ -594,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing break; case Core::HID::NpadStyleIndex::Handheld: sixaxis_handheld_state.attribute.raw = 0; - if (sixaxis_sensors_enabled) { + if (controller.sixaxis_sensor_enabled) { sixaxis_handheld_state.attribute.is_connected.Assign(1); sixaxis_handheld_state.accel = motion_state[0].accel; sixaxis_handheld_state.gyro = motion_state[0].gyro; @@ -605,7 +571,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing case Core::HID::NpadStyleIndex::JoyconDual: sixaxis_dual_left_state.attribute.raw = 0; sixaxis_dual_right_state.attribute.raw = 0; - if (sixaxis_sensors_enabled) { + if (controller.sixaxis_sensor_enabled) { // Set motion for the left joycon sixaxis_dual_left_state.attribute.is_connected.Assign(1); sixaxis_dual_left_state.accel = motion_state[0].accel; @@ -613,7 +579,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing sixaxis_dual_left_state.rotation = motion_state[0].rotation; sixaxis_dual_left_state.orientation = motion_state[0].orientation; } - if (sixaxis_sensors_enabled) { + if (controller.sixaxis_sensor_enabled) { // Set motion for the right joycon sixaxis_dual_right_state.attribute.is_connected.Assign(1); sixaxis_dual_right_state.accel = motion_state[1].accel; @@ -624,7 +590,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing break; case Core::HID::NpadStyleIndex::JoyconLeft: sixaxis_left_lifo_state.attribute.raw = 0; - if (sixaxis_sensors_enabled) { + if (controller.sixaxis_sensor_enabled) { sixaxis_left_lifo_state.attribute.is_connected.Assign(1); sixaxis_left_lifo_state.accel = motion_state[0].accel; sixaxis_left_lifo_state.gyro = motion_state[0].gyro; @@ -634,7 +600,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing break; case Core::HID::NpadStyleIndex::JoyconRight: sixaxis_right_lifo_state.attribute.raw = 0; - if (sixaxis_sensors_enabled) { + if (controller.sixaxis_sensor_enabled) { sixaxis_right_lifo_state.attribute.is_connected.Assign(1); sixaxis_right_lifo_state.accel = motion_state[1].accel; sixaxis_right_lifo_state.gyro = motion_state[1].gyro; @@ -724,26 +690,30 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode return communication_mode; } -void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) { - const std::size_t npad_index = NPadIdToIndex(npad_id); - ASSERT(npad_index < controller_data.size()); - auto& controller = controller_data[npad_index]; +void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, + NpadJoyAssignmentMode assignment_mode) { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + return; + } + + auto& controller = GetControllerFromNpadIdType(npad_id); if (controller.shared_memory_entry.assignment_mode != assignment_mode) { controller.shared_memory_entry.assignment_mode = assignment_mode; } } -bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, - const VibrationValue& vibration_value) { - auto& controller = controller_data[npad_index]; - +bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, + std::size_t device_index, + const Core::HID::VibrationValue& vibration_value) { + auto& controller = GetControllerFromNpadIdType(npad_id); if (!controller.device->IsConnected()) { return false; } if (!controller.device->IsVibrationEnabled()) { - if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f || - controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) { + if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || + controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { // Send an empty vibration to stop any vibrations. Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; controller.device->SetVibration(device_index, vibration); @@ -762,7 +732,7 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size const auto now = steady_clock::now(); // Filter out non-zero vibrations that are within 10ms of each other. - if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && + if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && duration_cast( now - controller.vibration[device_index].last_vibration_timepoint) < milliseconds(10)) { @@ -772,13 +742,15 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size controller.vibration[device_index].last_vibration_timepoint = now; } - Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low, - vibration_value.amp_high, vibration_value.freq_high}; + Core::HID::VibrationValue vibration{ + vibration_value.low_amplitude, vibration_value.low_frequency, + vibration_value.high_amplitude, vibration_value.high_frequency}; return controller.device->SetVibration(device_index, vibration); } -void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, - const VibrationValue& vibration_value) { +void Controller_NPad::VibrateController( + const Core::HID::VibrationDeviceHandle& vibration_device_handle, + const Core::HID::VibrationValue& vibration_value) { if (!IsDeviceHandleValid(vibration_device_handle)) { return; } @@ -787,15 +759,14 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han return; } - const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); - auto& controller = controller_data[npad_index]; + auto& controller = GetControllerFromHandle(vibration_device_handle); const auto device_index = static_cast(vibration_device_handle.device_index); if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { return; } - if (vibration_device_handle.device_index == DeviceIndex::None) { + if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { UNREACHABLE_MSG("DeviceIndex should never be None!"); return; } @@ -803,28 +774,30 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han // Some games try to send mismatched parameters in the device handle, block these. if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || - vibration_device_handle.device_index == DeviceIndex::Right)) || + vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || - vibration_device_handle.device_index == DeviceIndex::Left))) { + vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { return; } // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_value.amp_low == - controller.vibration[device_index].latest_vibration_value.amp_low && - vibration_value.amp_high == - controller.vibration[device_index].latest_vibration_value.amp_high) { + if (vibration_value.low_amplitude == + controller.vibration[device_index].latest_vibration_value.low_amplitude && + vibration_value.high_amplitude == + controller.vibration[device_index].latest_vibration_value.high_amplitude) { return; } - if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { + if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index, + vibration_value)) { controller.vibration[device_index].latest_vibration_value = vibration_value; } } -void Controller_NPad::VibrateControllers(const std::vector& vibration_device_handles, - const std::vector& vibration_values) { +void Controller_NPad::VibrateControllers( + const std::vector& vibration_device_handles, + const std::vector& vibration_values) { if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { return; } @@ -839,31 +812,31 @@ void Controller_NPad::VibrateControllers(const std::vector& vibrat } } -Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( - const DeviceHandle& vibration_device_handle) const { +Core::HID::VibrationValue Controller_NPad::GetLastVibration( + const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { if (!IsDeviceHandleValid(vibration_device_handle)) { return {}; } - const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); - const auto& controller = controller_data[npad_index]; + const auto& controller = GetControllerFromHandle(vibration_device_handle); const auto device_index = static_cast(vibration_device_handle.device_index); return controller.vibration[device_index].latest_vibration_value; } -void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { +void Controller_NPad::InitializeVibrationDevice( + const Core::HID::VibrationDeviceHandle& vibration_device_handle) { if (!IsDeviceHandleValid(vibration_device_handle)) { return; } - const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); + const auto npad_index = static_cast(vibration_device_handle.npad_id); const auto device_index = static_cast(vibration_device_handle.device_index); InitializeVibrationDeviceAtIndex(npad_index, device_index); } -void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, +void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index) { - auto& controller = controller_data[npad_index]; + auto& controller = GetControllerFromNpadIdType(npad_id); if (!Settings::values.vibration_enabled.GetValue()) { controller.vibration[device_index].device_mounted = false; return; @@ -877,58 +850,67 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { permit_vibration_session_enabled = permit_vibration_session; } -bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { +bool Controller_NPad::IsVibrationDeviceMounted( + const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { if (!IsDeviceHandleValid(vibration_device_handle)) { return false; } - const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); - const auto& controller = controller_data[npad_index]; + const auto& controller = GetControllerFromHandle(vibration_device_handle); const auto device_index = static_cast(vibration_device_handle.device_index); return controller.vibration[device_index].device_mounted; } -Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { - const auto& controller = controller_data[NPadIdToIndex(npad_id)]; +Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + // Fallback to player 1 + const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1); + return controller.styleset_changed_event->GetReadableEvent(); + } + + const auto& controller = GetControllerFromNpadIdType(npad_id); return controller.styleset_changed_event->GetReadableEvent(); } -void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { - const auto& controller = controller_data[NPadIdToIndex(npad_id)]; +void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const { + const auto& controller = GetControllerFromNpadIdType(npad_id); controller.styleset_changed_event->GetWritableEvent().Signal(); } void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, - std::size_t npad_index) { - UpdateControllerAt(controller, npad_index, true); + Core::HID::NpadIdType npad_id) { + UpdateControllerAt(controller, npad_id, true); } -void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, std::size_t npad_index, - bool connected) { - auto& controller = controller_data[npad_index]; +void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, + Core::HID::NpadIdType npad_id, bool connected) { + auto& controller = GetControllerFromNpadIdType(npad_id); if (!connected) { - DisconnectNpadAtIndex(npad_index); + DisconnectNpad(npad_id); return; } controller.device->SetNpadStyleIndex(type); - InitNewlyAddedController(npad_index); + InitNewlyAddedController(npad_id); } -void Controller_NPad::DisconnectNpad(u32 npad_id) { - DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); -} +void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + return; + } -void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { - auto& controller = controller_data[npad_index]; + LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); + auto& controller = GetControllerFromNpadIdType(npad_id); for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { // Send an empty vibration to stop any vibrations. - VibrateControllerAtIndex(npad_index, device_idx, {}); + VibrateControllerAtIndex(npad_id, device_idx, {}); controller.vibration[device_idx].device_mounted = false; } auto& shared_memory_entry = controller.shared_memory_entry; - shared_memory_entry.style_set.raw = 0; // Zero out + shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out shared_memory_entry.device_type.raw = 0; shared_memory_entry.system_properties.raw = 0; shared_memory_entry.button_properties.raw = 0; @@ -949,48 +931,102 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { controller.is_connected = false; controller.device->Disconnect(); - SignalStyleSetChangedEvent(IndexToNPad(npad_index)); + SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory_entry); } -void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { - gyroscope_zero_drift_mode = drift_mode; +void Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, + GyroscopeZeroDriftMode drift_mode) { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + return; + } + auto& controller = GetControllerFromHandle(sixaxis_handle); + controller.gyroscope_zero_drift_mode = drift_mode; } -Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const { - return gyroscope_zero_drift_mode; +Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode( + Core::HID::SixAxisSensorHandle sixaxis_handle) const { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + // Return the default value + return GyroscopeZeroDriftMode::Standard; + } + const auto& controller = GetControllerFromHandle(sixaxis_handle); + return controller.gyroscope_zero_drift_mode; } -bool Controller_NPad::IsSixAxisSensorAtRest() const { - return sixaxis_at_rest; +bool Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + // Return the default value + return true; + } + const auto& controller = GetControllerFromHandle(sixaxis_handle); + return controller.sixaxis_at_rest; +} + +void Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, + bool sixaxis_status) { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + return; + } + auto& controller = GetControllerFromHandle(sixaxis_handle); + controller.sixaxis_sensor_enabled = sixaxis_status; } -void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) { - sixaxis_sensors_enabled = six_axis_status; +void Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, + bool sixaxis_fusion_status) { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + return; + } + auto& controller = GetControllerFromHandle(sixaxis_handle); + controller.sixaxis_fusion_enabled = sixaxis_fusion_status; } -void Controller_NPad::SetSixAxisFusionParameters(f32 parameter1, f32 parameter2) { - sixaxis_fusion_parameter1 = parameter1; - sixaxis_fusion_parameter2 = parameter2; +void Controller_NPad::SetSixAxisFusionParameters( + Core::HID::SixAxisSensorHandle sixaxis_handle, + Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + return; + } + auto& controller = GetControllerFromHandle(sixaxis_handle); + controller.sixaxis_fusion = sixaxis_fusion_parameters; } -std::pair Controller_NPad::GetSixAxisFusionParameters() { - return { - sixaxis_fusion_parameter1, - sixaxis_fusion_parameter2, - }; +Core::HID::SixAxisSensorFusionParameters Controller_NPad::GetSixAxisFusionParameters( + Core::HID::SixAxisSensorHandle sixaxis_handle) { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + // Since these parameters are unknow just return zeros + return {}; + } + auto& controller = GetControllerFromHandle(sixaxis_handle); + return controller.sixaxis_fusion; } -void Controller_NPad::ResetSixAxisFusionParameters() { - sixaxis_fusion_parameter1 = 0.0f; - sixaxis_fusion_parameter2 = 0.0f; +void Controller_NPad::ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle) { + if (!IsDeviceHandleValid(sixaxis_handle)) { + LOG_ERROR(Service_HID, "Invalid handle"); + return; + } + auto& controller = GetControllerFromHandle(sixaxis_handle); + // Since these parameters are unknow just fill with zeros + controller.sixaxis_fusion = {}; } -void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { - const auto npad_index_1 = NPadIdToIndex(npad_id_1); - const auto npad_index_2 = NPadIdToIndex(npad_id_2); - const auto& controller_1 = controller_data[npad_index_1].device; - const auto& controller_2 = controller_data[npad_index_2].device; +void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2) { + if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, + npad_id_2); + return; + } + auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; + auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; // If the controllers at both npad indices form a pair of left and right joycons, merge them. // Otherwise, do nothing. @@ -1000,7 +1036,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) { // Disconnect the joycon at the second id and connect the dual joycon at the first index. DisconnectNpad(npad_id_2); - AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_index_1); + AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); } } @@ -1014,15 +1050,20 @@ void Controller_NPad::StopLRAssignmentMode() { is_in_lr_assignment_mode = false; } -bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { - if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN || - npad_id_2 == NPAD_UNKNOWN) { +bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, + Core::HID::NpadIdType npad_id_2) { + if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, + npad_id_2); + return false; + } + if (npad_id_1 == Core::HID::NpadIdType::Handheld || + npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || + npad_id_2 == Core::HID::NpadIdType::Other) { return true; } - const auto npad_index_1 = NPadIdToIndex(npad_id_1); - const auto npad_index_2 = NPadIdToIndex(npad_id_2); - const auto& controller_1 = controller_data[npad_index_1].device; - const auto& controller_2 = controller_data[npad_index_2].device; + const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; + const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; const auto type_index_1 = controller_1->GetNpadStyleIndex(); const auto type_index_2 = controller_2->GetNpadStyleIndex(); @@ -1030,28 +1071,39 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { return false; } - AddNewControllerAt(type_index_2, npad_index_1); - AddNewControllerAt(type_index_1, npad_index_2); + AddNewControllerAt(type_index_2, npad_id_1); + AddNewControllerAt(type_index_1, npad_id_2); return true; } -Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { - if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { - // These are controllers without led patterns +Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); return Core::HID::LedPattern{0, 0, 0, 0}; } - return controller_data[npad_id].device->GetLedPattern(); + const auto& controller = GetControllerFromNpadIdType(npad_id).device; + return controller->GetLedPattern(); } -bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { - auto& controller = controller_data[NPadIdToIndex(npad_id)]; +bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled( + Core::HID::NpadIdType npad_id) const { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + // Return the default value + return false; + } + const auto& controller = GetControllerFromNpadIdType(npad_id); return controller.unintended_home_button_input_protection; } void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, - u32 npad_id) { - auto& controller = controller_data[NPadIdToIndex(npad_id)]; + Core::HID::NpadIdType npad_id) { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + return; + } + auto& controller = GetControllerFromNpadIdType(npad_id); controller.unintended_home_button_input_protection = is_protection_enabled; } @@ -1099,7 +1151,7 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller if (controller == Core::HID::NpadStyleIndex::Handheld) { const bool support_handheld = std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), - NPAD_HANDHELD) != supported_npad_id_types.end(); + Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end(); // Handheld is not even a supported type, lets stop here if (!support_handheld) { return false; @@ -1113,7 +1165,9 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller } if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), - [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { + [](Core::HID::NpadIdType npad_id) { + return npad_id <= Core::HID::NpadIdType::Player8; + })) { Core::HID::NpadStyleTag style = GetSupportedStyleSet(); switch (controller) { case Core::HID::NpadStyleIndex::ProController: @@ -1144,4 +1198,48 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller return false; } +Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( + const Core::HID::SixAxisSensorHandle& device_handle) { + const auto npad_id = static_cast(device_handle.npad_id); + return GetControllerFromNpadIdType(npad_id); +} + +const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( + const Core::HID::SixAxisSensorHandle& device_handle) const { + const auto npad_id = static_cast(device_handle.npad_id); + return GetControllerFromNpadIdType(npad_id); +} + +Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( + const Core::HID::VibrationDeviceHandle& device_handle) { + const auto npad_id = static_cast(device_handle.npad_id); + return GetControllerFromNpadIdType(npad_id); +} + +const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( + const Core::HID::VibrationDeviceHandle& device_handle) const { + const auto npad_id = static_cast(device_handle.npad_id); + return GetControllerFromNpadIdType(npad_id); +} + +Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType( + Core::HID::NpadIdType npad_id) { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + npad_id = Core::HID::NpadIdType::Player1; + } + const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id); + return controller_data[npad_index]; +} + +const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType( + Core::HID::NpadIdType npad_id) const { + if (!IsNpadIdValid(npad_id)) { + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); + npad_id = Core::HID::NpadIdType::Player1; + } + const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id); + return controller_data[npad_index]; +} + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index a996755ed..3798c037f 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -31,9 +31,6 @@ class ServiceContext; namespace Service::HID { -constexpr u32 NPAD_HANDHELD = 32; -constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this? - class Controller_NPad final : public ControllerBase { public: explicit Controller_NPad(Core::HID::HIDCore& hid_core_, @@ -53,13 +50,6 @@ public: void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; - enum class DeviceIndex : u8 { - Left = 0, - Right = 1, - None = 2, - MaxDeviceIndex = 3, - }; - // This is nn::hid::GyroscopeZeroDriftMode enum class GyroscopeZeroDriftMode : u32 { Loose = 0, @@ -79,6 +69,12 @@ public: Single = 1, }; + // This is nn::hid::NpadJoyDeviceType + enum class NpadJoyDeviceType : s64 { + Left = 0, + Right = 1, + }; + // This is nn::hid::NpadHandheldActivationMode enum class NpadHandheldActivationMode : u64 { Dual = 0, @@ -94,28 +90,11 @@ public: Default = 3, }; - struct DeviceHandle { - Core::HID::NpadStyleIndex npad_type; - u8 npad_id; - DeviceIndex device_index; - INSERT_PADDING_BYTES_NOINIT(1); - }; - static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); - - // This is nn::hid::VibrationValue - struct VibrationValue { - f32 amp_low; - f32 freq_low; - f32 amp_high; - f32 freq_high; - }; - static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size"); - - static constexpr VibrationValue DEFAULT_VIBRATION_VALUE{ - .amp_low = 0.0f, - .freq_low = 160.0f, - .amp_high = 0.0f, - .freq_high = 320.0f, + static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{ + .low_amplitude = 0.0f, + .low_frequency = 160.0f, + .high_amplitude = 0.0f, + .high_frequency = 320.0f, }; void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); @@ -134,68 +113,77 @@ public: void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); NpadCommunicationMode GetNpadCommunicationMode() const; - void SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode); + void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode); - bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, - const VibrationValue& vibration_value); + bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, + const Core::HID::VibrationValue& vibration_value); - void VibrateController(const DeviceHandle& vibration_device_handle, - const VibrationValue& vibration_value); + void VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle, + const Core::HID::VibrationValue& vibration_value); - void VibrateControllers(const std::vector& vibration_device_handles, - const std::vector& vibration_values); + void VibrateControllers( + const std::vector& vibration_device_handles, + const std::vector& vibration_values); - VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; + Core::HID::VibrationValue GetLastVibration( + const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); + void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); - void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); + void InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index); void SetPermitVibrationSession(bool permit_vibration_session); - bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; + bool IsVibrationDeviceMounted( + const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - Kernel::KReadableEvent& GetStyleSetChangedEvent(u32 npad_id); - void SignalStyleSetChangedEvent(u32 npad_id) const; + Kernel::KReadableEvent& GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id); + void SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const; // Adds a new controller at an index. - void AddNewControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index); + void AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id); // Adds a new controller at an index with connection status. - void UpdateControllerAt(Core::HID::NpadStyleIndex controller, std::size_t npad_index, + void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, bool connected); - void DisconnectNpad(u32 npad_id); - void DisconnectNpadAtIndex(std::size_t index); - - void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); - GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; - bool IsSixAxisSensorAtRest() const; - void SetSixAxisEnabled(bool six_axis_status); - void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2); - std::pair GetSixAxisFusionParameters(); - void ResetSixAxisFusionParameters(); - Core::HID::LedPattern GetLedPattern(u32 npad_id); - bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; - void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); + void DisconnectNpad(Core::HID::NpadIdType npad_id); + + void SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, + GyroscopeZeroDriftMode drift_mode); + GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode( + Core::HID::SixAxisSensorHandle sixaxis_handle) const; + bool IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const; + void SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, bool sixaxis_status); + void SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, + bool sixaxis_fusion_status); + void SetSixAxisFusionParameters( + Core::HID::SixAxisSensorHandle sixaxis_handle, + Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); + Core::HID::SixAxisSensorFusionParameters GetSixAxisFusionParameters( + Core::HID::SixAxisSensorHandle sixaxis_handle); + void ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle); + Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id); + bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const; + void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, + Core::HID::NpadIdType npad_id); void SetAnalogStickUseCenterClamp(bool use_center_clamp); void ClearAllConnectedControllers(); void DisconnectAllConnectedControllers(); void ConnectAllDisconnectedControllers(); void ClearAllControllers(); - void MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2); + void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); void StartLRAssignmentMode(); void StopLRAssignmentMode(); - bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2); + bool SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); // Logical OR for all buttons presses on all controllers // Specifically for cheat engine and other features. u32 GetAndResetPressState(); - static std::size_t NPadIdToIndex(u32 npad_id); - static u32 IndexToNPad(std::size_t index); - static bool IsNpadIdValid(u32 npad_id); - static bool IsDeviceHandleValid(const DeviceHandle& device_handle); + static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); + static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle); + static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle); private: // This is nn::hid::detail::ColorAttribute @@ -441,7 +429,7 @@ private: // This is nn::hid::detail::NpadInternalState struct NpadInternalState { - Core::HID::NpadStyleTag style_set; + Core::HID::NpadStyleTag style_tag; NpadJoyAssignmentMode assignment_mode; NpadFullKeyColorState fullkey_color; NpadJoyColorState joycon_color; @@ -476,19 +464,19 @@ private: NpadLuciaType lucia_type; NpadLagonType lagon_type; NpadLagerType lager_type; - INSERT_PADDING_BYTES( - 0x4); // FW 13.x Investigate there is some sort of bitflag related to joycons + // FW 13.x Investigate there is some sort of bitflag related to joycons + INSERT_PADDING_BYTES(0x4); INSERT_PADDING_BYTES(0xc08); // Unknown }; static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); struct VibrationData { bool device_mounted{}; - VibrationValue latest_vibration_value{}; + Core::HID::VibrationValue latest_vibration_value{}; std::chrono::steady_clock::time_point last_vibration_timepoint{}; }; - struct ControllerData { + struct NpadControllerData { Core::HID::EmulatedController* device; Kernel::KEvent* styleset_changed_event{}; NpadInternalState shared_memory_entry{}; @@ -498,6 +486,13 @@ private: bool is_connected{}; Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; + // Motion parameters + bool sixaxis_at_rest{true}; + bool sixaxis_sensor_enabled{true}; + bool sixaxis_fusion_enabled{false}; + Core::HID::SixAxisSensorFusionParameters sixaxis_fusion{}; + GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; + // Current pad state NPadGenericState npad_pad_state{}; NPadGenericState npad_libnx_state{}; @@ -512,27 +507,33 @@ private: }; void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); - void InitNewlyAddedController(std::size_t controller_idx); + void InitNewlyAddedController(Core::HID::NpadIdType npad_id); bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const; - void RequestPadStateUpdate(u32 npad_id); + void RequestPadStateUpdate(Core::HID::NpadIdType npad_id); void WriteEmptyEntry(NpadInternalState& npad); + NpadControllerData& GetControllerFromHandle( + const Core::HID::SixAxisSensorHandle& device_handle); + const NpadControllerData& GetControllerFromHandle( + const Core::HID::SixAxisSensorHandle& device_handle) const; + NpadControllerData& GetControllerFromHandle( + const Core::HID::VibrationDeviceHandle& device_handle); + const NpadControllerData& GetControllerFromHandle( + const Core::HID::VibrationDeviceHandle& device_handle) const; + NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); + const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; + std::atomic press_state{}; - std::array controller_data{}; + std::array controller_data{}; KernelHelpers::ServiceContext& service_context; std::mutex mutex; - std::vector supported_npad_id_types{}; + std::vector supported_npad_id_types{}; NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; bool permit_vibration_session_enabled{false}; bool analog_stick_use_center_clamp{}; - GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; - bool sixaxis_sensors_enabled{true}; - f32 sixaxis_fusion_parameter1{}; - f32 sixaxis_fusion_parameter2{}; - bool sixaxis_at_rest{true}; bool is_in_lr_assignment_mode{false}; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 96e8fb7e1..496b55d0e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -161,7 +161,7 @@ public: private: void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto vibration_device_handle{rp.PopRaw()}; + const auto vibration_device_handle{rp.PopRaw()}; if (applet_resource != nullptr) { applet_resource->GetController(HidController::NPad) @@ -417,6 +417,7 @@ void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -443,19 +444,18 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + u32 basic_xpad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(true); + // This function does nothing on 10.0.0+ - LOG_DEBUG(Service_HID, - "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}", + parameters.basic_xpad_id, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -464,19 +464,18 @@ void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + u32 basic_xpad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(false); + // This function does nothing on 10.0.0+ - LOG_DEBUG(Service_HID, - "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}", + parameters.basic_xpad_id, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -485,14 +484,16 @@ void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(true); + applet_resource->GetController(HidController::NPad) + .SetSixAxisEnabled(parameters.sixaxis_handle, true); LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", @@ -506,14 +507,16 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - applet_resource->GetController(HidController::NPad).SetSixAxisEnabled(false); + applet_resource->GetController(HidController::NPad) + .SetSixAxisEnabled(parameters.sixaxis_handle, false); LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", @@ -529,19 +532,23 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { struct Parameters { bool enable_sixaxis_sensor_fusion; INSERT_PADDING_BYTES_NOINIT(3); - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; u64 applet_resource_user_id; }; static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - LOG_WARNING(Service_HID, - "(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " - "device_index={}, applet_resource_user_id={}", - parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, - parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, - parameters.applet_resource_user_id); + applet_resource->GetController(HidController::NPad) + .SetSixAxisFusionEnabled(parameters.sixaxis_handle, + parameters.enable_sixaxis_sensor_fusion); + + LOG_DEBUG(Service_HID, + "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " + "device_index={}, applet_resource_user_id={}", + parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, + parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, + parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -550,9 +557,9 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; - f32 parameter1; - f32 parameter2; + Core::HID::SixAxisSensorHandle sixaxis_handle; + Core::HID::SixAxisSensorFusionParameters sixaxis_fusion; + INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); @@ -560,14 +567,14 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetSixAxisFusionParameters(parameters.parameter1, parameters.parameter2); + .SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion); - LOG_WARNING(Service_HID, - "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, parameter1={}, " - "parameter2={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.parameter1, - parameters.parameter2, parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, " + "parameter2={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1, + parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -576,35 +583,33 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; + INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); - f32 parameter1 = 0; - f32 parameter2 = 0; const auto parameters{rp.PopRaw()}; - std::tie(parameter1, parameter2) = + const auto sixaxis_fusion_parameters = applet_resource->GetController(HidController::NPad) - .GetSixAxisFusionParameters(); + .GetSixAxisFusionParameters(parameters.sixaxis_handle); - LOG_WARNING( - Service_HID, - "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(parameter1); - rb.Push(parameter2); + rb.PushRaw(sixaxis_fusion_parameters); } void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; + INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); @@ -612,13 +617,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .ResetSixAxisFusionParameters(); + .ResetSixAxisFusionParameters(parameters.sixaxis_handle); - LOG_WARNING( - Service_HID, - "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", + parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, + parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -626,12 +630,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto sixaxis_handle{rp.PopRaw()}; + const auto sixaxis_handle{rp.PopRaw()}; const auto drift_mode{rp.PopEnum()}; const auto applet_resource_user_id{rp.Pop()}; applet_resource->GetController(HidController::NPad) - .SetGyroscopeZeroDriftMode(drift_mode); + .SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode); LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " @@ -646,10 +650,11 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -661,21 +666,23 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.PushEnum(applet_resource->GetController(HidController::NPad) - .GetGyroscopeZeroDriftMode()); + .GetGyroscopeZeroDriftMode(parameters.sixaxis_handle)); } void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; + const auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard}; applet_resource->GetController(HidController::NPad) - .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); + .SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode); LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", @@ -689,10 +696,11 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -704,16 +712,17 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(applet_resource->GetController(HidController::NPad) - .IsSixAxisSensorAtRest()); + .IsSixAxisSensorAtRest(parameters.sixaxis_handle)); } void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::SixAxisSensorHandle sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -735,13 +744,14 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; applet_resource->ActivateController(HidController::Gesture); - LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, - parameters.applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}", + parameters.unknown, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -749,12 +759,20 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto supported_styleset{rp.Pop()}; + struct Parameters { + Core::HID::NpadStyleSet supported_styleset; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetSupportedStyleSet({supported_styleset}); + .SetSupportedStyleSet({parameters.supported_styleset}); - LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); + LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}", + parameters.supported_styleset, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -768,9 +786,9 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(applet_resource->GetController(HidController::NPad) - .GetSupportedStyleSet() - .raw); + rb.PushEnum(applet_resource->GetController(HidController::NPad) + .GetSupportedStyleSet() + .raw); } void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { @@ -813,11 +831,12 @@ void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - u32 npad_id; + Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; u64 unknown; }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -833,10 +852,11 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - u32 npad_id; + Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -852,7 +872,7 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id{rp.Pop()}; + const auto npad_id{rp.PopEnum()}; LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); @@ -867,16 +887,17 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { // Should have no effect with how our npad sets up the data IPC::RequestParser rp{ctx}; struct Parameters { - u32 unknown; + s32 revision; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; applet_resource->ActivateController(HidController::NPad); - LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, + LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -911,10 +932,11 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - u32 npad_id; + Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -932,11 +954,12 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault IPC::RequestParser rp{ctx}; struct Parameters { - u32 npad_id; + Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; u64 npad_joy_device_type; }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -955,10 +978,11 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - u32 npad_id; + Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -974,8 +998,8 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id_1{rp.Pop()}; - const auto npad_id_2{rp.Pop()}; + const auto npad_id_1{rp.PopEnum()}; + const auto npad_id_2{rp.PopEnum()}; const auto applet_resource_user_id{rp.Pop()}; applet_resource->GetController(HidController::NPad) @@ -1041,8 +1065,8 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto npad_id_1{rp.Pop()}; - const auto npad_id_2{rp.Pop()}; + const auto npad_id_1{rp.PopEnum()}; + const auto npad_id_2{rp.PopEnum()}; const auto applet_resource_user_id{rp.Pop()}; const bool res = applet_resource->GetController(HidController::NPad) @@ -1063,10 +1087,11 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - u32 npad_id; + Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -1084,9 +1109,10 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c struct Parameters { bool unintended_home_button_input_protection; INSERT_PADDING_BYTES_NOINIT(3); - u32 npad_id; + Core::HID::NpadIdType npad_id; u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -1108,6 +1134,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { bool analog_stick_use_center_clamp; + INSERT_PADDING_BYTES_NOINIT(7); u64 applet_resource_user_id; }; static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); @@ -1127,7 +1154,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto vibration_device_handle{rp.PopRaw()}; + const auto vibration_device_handle{rp.PopRaw()}; Core::HID::VibrationDeviceInfo vibration_device_info; @@ -1149,13 +1176,13 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { } switch (vibration_device_handle.device_index) { - case Controller_NPad::DeviceIndex::Left: + case Core::HID::DeviceIndex::Left: vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; break; - case Controller_NPad::DeviceIndex::Right: + case Core::HID::DeviceIndex::Right: vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; break; - case Controller_NPad::DeviceIndex::None: + case Core::HID::DeviceIndex::None: default: UNREACHABLE_MSG("DeviceIndex should never be None!"); vibration_device_info.position = Core::HID::VibrationDevicePosition::None; @@ -1173,11 +1200,12 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle vibration_device_handle; - Controller_NPad::VibrationValue vibration_value; + Core::HID::VibrationDeviceHandle vibration_device_handle; + Core::HID::VibrationValue vibration_value; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -1197,10 +1225,11 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle vibration_device_handle; + Core::HID::VibrationDeviceHandle vibration_device_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -1251,10 +1280,10 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { const auto handles = ctx.ReadBuffer(0); const auto vibrations = ctx.ReadBuffer(1); - std::vector vibration_device_handles( - handles.size() / sizeof(Controller_NPad::DeviceHandle)); - std::vector vibration_values( - vibrations.size() / sizeof(Controller_NPad::VibrationValue)); + std::vector vibration_device_handles( + handles.size() / sizeof(Core::HID::VibrationDeviceHandle)); + std::vector vibration_values(vibrations.size() / + sizeof(Core::HID::VibrationValue)); std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); @@ -1271,7 +1300,8 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle vibration_device_handle; + Core::HID::VibrationDeviceHandle vibration_device_handle; + INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; Core::HID::VibrationGcErmCommand gc_erm_command; }; @@ -1288,25 +1318,25 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { const auto vibration_value = [parameters] { switch (parameters.gc_erm_command) { case Core::HID::VibrationGcErmCommand::Stop: - return Controller_NPad::VibrationValue{ - .amp_low = 0.0f, - .freq_low = 160.0f, - .amp_high = 0.0f, - .freq_high = 320.0f, + return Core::HID::VibrationValue{ + .low_amplitude = 0.0f, + .low_frequency = 160.0f, + .high_amplitude = 0.0f, + .high_frequency = 320.0f, }; case Core::HID::VibrationGcErmCommand::Start: - return Controller_NPad::VibrationValue{ - .amp_low = 1.0f, - .freq_low = 160.0f, - .amp_high = 1.0f, - .freq_high = 320.0f, + return Core::HID::VibrationValue{ + .low_amplitude = 1.0f, + .low_frequency = 160.0f, + .high_amplitude = 1.0f, + .high_frequency = 320.0f, }; case Core::HID::VibrationGcErmCommand::StopHard: - return Controller_NPad::VibrationValue{ - .amp_low = 0.0f, - .freq_low = 0.0f, - .amp_high = 0.0f, - .freq_high = 0.0f, + return Core::HID::VibrationValue{ + .low_amplitude = 0.0f, + .low_frequency = 0.0f, + .high_amplitude = 0.0f, + .high_frequency = 0.0f, }; default: return Controller_NPad::DEFAULT_VIBRATION_VALUE; @@ -1331,7 +1361,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle vibration_device_handle; + Core::HID::VibrationDeviceHandle vibration_device_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; @@ -1342,7 +1372,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { .GetLastVibration(parameters.vibration_device_handle); const auto gc_erm_command = [last_vibration] { - if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) { + if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) { return Core::HID::VibrationGcErmCommand::Start; } @@ -1352,7 +1382,7 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. * This is done to reuse the controller vibration functions made for regular controllers. */ - if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) { + if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) { return Core::HID::VibrationGcErmCommand::StopHard; } @@ -1396,10 +1426,11 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle vibration_device_handle; + Core::HID::VibrationDeviceHandle vibration_device_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; @@ -1430,18 +1461,18 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - LOG_WARNING( - Service_HID, - "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + LOG_WARNING(Service_HID, + "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}", + parameters.console_sixaxis_handle.unknown_1, + parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -1450,18 +1481,18 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - Controller_NPad::DeviceHandle sixaxis_handle; + Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; - LOG_WARNING( - Service_HID, - "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", - parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, - parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); + LOG_WARNING(Service_HID, + "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}", + parameters.console_sixaxis_handle.unknown_1, + parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -1615,10 +1646,8 @@ void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_resource_user_id{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", - applet_resource_user_id); + LOG_WARNING(Service_HID, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); -- cgit v1.2.3 From 7fcfe24a3edff903871bee6c249d97e64648ddfa Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 13 Nov 2021 02:39:01 -0600 Subject: core/hid: Fix keyboard alignment --- src/core/hid/hid_types.h | 25 ++++++++++++----------- src/core/hle/service/hid/controllers/keyboard.cpp | 1 + 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index f224cb744..41bc65ce2 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -423,20 +423,21 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor // This is nn::hid::KeyboardModifier struct KeyboardModifier { union { - u32 raw{}; - BitField<0, 1, u32> control; - BitField<1, 1, u32> shift; - BitField<2, 1, u32> left_alt; - BitField<3, 1, u32> right_alt; - BitField<4, 1, u32> gui; - BitField<8, 1, u32> caps_lock; - BitField<9, 1, u32> scroll_lock; - BitField<10, 1, u32> num_lock; - BitField<11, 1, u32> katakana; - BitField<12, 1, u32> hiragana; + u64 raw{}; + BitField<0, 1, u64> control; + BitField<1, 1, u64> shift; + BitField<2, 1, u64> left_alt; + BitField<3, 1, u64> right_alt; + BitField<4, 1, u64> gui; + BitField<8, 1, u64> caps_lock; + BitField<9, 1, u64> scroll_lock; + BitField<10, 1, u64> num_lock; + BitField<11, 1, u64> katakana; + BitField<12, 1, u64> hiragana; + BitField<32, 1, u64> unknown; }; }; -static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size"); +static_assert(sizeof(KeyboardModifier) == 0x8, "KeyboardModifier is an invalid size"); // This is nn::hid::KeyboardKey struct KeyboardKey { diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 1dc219bf5..d6505dbc5 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -42,6 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, next_state.key = keyboard_state; next_state.modifier = keyboard_modifier_state; + next_state.modifier.unknown.Assign(1); } keyboard_lifo.WriteNextEntry(next_state); -- cgit v1.2.3 From b673857d7dfc72f38d9242b315cd590b859795ff Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 13 Nov 2021 23:25:45 -0600 Subject: core/hid: Improve accuracy of the keyboard implementation --- src/core/hid/emulated_devices.cpp | 3 +- src/core/hid/hid_types.h | 398 +++++++++++++++------- src/core/hle/service/hid/controllers/keyboard.cpp | 1 + src/core/hle/service/hid/hid.cpp | 35 +- src/core/hle/service/hid/hid.h | 2 + 5 files changed, 303 insertions(+), 136 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index e97470240..0d840a003 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -170,13 +170,14 @@ void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, return; } + // Index should be converted from NativeKeyboard to KeyboardKeyIndex UpdateKey(index, current_status.value); TriggerOnChange(DeviceTriggerType::Keyboard); } void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { - constexpr u8 KEYS_PER_BYTE = 8; + constexpr std::size_t KEYS_PER_BYTE = 8; auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE]; const u8 mask = static_cast(1 << (key_index % KEYS_PER_BYTE)); if (status) { diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 41bc65ce2..af95f3aff 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -12,6 +12,195 @@ namespace Core::HID { +enum class DeviceIndex : u8 { + Left = 0, + Right = 1, + None = 2, + MaxDeviceIndex = 3, +}; + +// This is nn::hid::NpadButton +enum class NpadButton : u64 { + None = 0, + A = 1U << 0, + B = 1U << 1, + X = 1U << 2, + Y = 1U << 3, + StickL = 1U << 4, + StickR = 1U << 5, + L = 1U << 6, + R = 1U << 7, + ZL = 1U << 8, + ZR = 1U << 9, + Plus = 1U << 10, + Minus = 1U << 11, + + Left = 1U << 12, + Up = 1U << 13, + Right = 1U << 14, + Down = 1U << 15, + + StickLLeft = 1U << 16, + StickLUp = 1U << 17, + StickLRight = 1U << 18, + StickLDown = 1U << 19, + + StickRLeft = 1U << 20, + StickRUp = 1U << 21, + StickRRight = 1U << 22, + StickRDown = 1U << 23, + + LeftSL = 1U << 24, + LeftSR = 1U << 25, + + RightSL = 1U << 26, + RightSR = 1U << 27, + + Palma = 1U << 28, + Verification = 1U << 29, + HandheldLeftB = 1U << 30, + LagonCLeft = 1U << 31, + LagonCUp = 1ULL << 32, + LagonCRight = 1ULL << 33, + LagonCDown = 1ULL << 34, +}; +DECLARE_ENUM_FLAG_OPERATORS(NpadButton); + +enum class KeyboardKeyIndex : u32 { + A = 4, + B = 5, + C = 6, + D = 7, + E = 8, + F = 9, + G = 10, + H = 11, + I = 12, + J = 13, + K = 14, + L = 15, + M = 16, + N = 17, + O = 18, + P = 19, + Q = 20, + R = 21, + S = 22, + T = 23, + U = 24, + V = 25, + W = 26, + X = 27, + Y = 28, + Z = 29, + D1 = 30, + D2 = 31, + D3 = 32, + D4 = 33, + D5 = 34, + D6 = 35, + D7 = 36, + D8 = 37, + D9 = 38, + D0 = 39, + Return = 40, + Escape = 41, + Backspace = 42, + Tab = 43, + Space = 44, + Minus = 45, + Plus = 46, + OpenBracket = 47, + CloseBracket = 48, + Pipe = 49, + Tilde = 50, + Semicolon = 51, + Quote = 52, + Backquote = 53, + Comma = 54, + Period = 55, + Slash = 56, + CapsLock = 57, + F1 = 58, + F2 = 59, + F3 = 60, + F4 = 61, + F5 = 62, + F6 = 63, + F7 = 64, + F8 = 65, + F9 = 66, + F10 = 67, + F11 = 68, + F12 = 69, + PrintScreen = 70, + ScrollLock = 71, + Pause = 72, + Insert = 73, + Home = 74, + PageUp = 75, + Delete = 76, + End = 77, + PageDown = 78, + RightArrow = 79, + LeftArrow = 80, + DownArrow = 81, + UpArrow = 82, + NumLock = 83, + NumPadDivide = 84, + NumPadMultiply = 85, + NumPadSubtract = 86, + NumPadAdd = 87, + NumPadEnter = 88, + NumPad1 = 89, + NumPad2 = 90, + NumPad3 = 91, + NumPad4 = 92, + NumPad5 = 93, + NumPad6 = 94, + NumPad7 = 95, + NumPad8 = 96, + NumPad9 = 97, + NumPad0 = 98, + NumPadDot = 99, + Backslash = 100, + Application = 101, + Power = 102, + NumPadEquals = 103, + F13 = 104, + F14 = 105, + F15 = 106, + F16 = 107, + F17 = 108, + F18 = 109, + F19 = 110, + F20 = 111, + F21 = 112, + F22 = 113, + F23 = 114, + F24 = 115, + NumPadComma = 133, + Ro = 135, + KatakanaHiragana = 136, + Yen = 137, + Henkan = 138, + Muhenkan = 139, + NumPadCommaPc98 = 140, + HangulEnglish = 144, + Hanja = 145, + Katakana = 146, + Hiragana = 147, + ZenkakuHankaku = 148, + LeftControl = 224, + LeftShift = 225, + LeftAlt = 226, + LeftGui = 227, + RightControl = 228, + RightShift = 229, + RightAlt = 230, + RightGui = 231, +}; + // This is nn::hid::NpadIdType enum class NpadIdType : u32 { Player1 = 0x0, @@ -28,62 +217,6 @@ enum class NpadIdType : u32 { Invalid = 0xFFFFFFFF, }; -/// Converts a NpadIdType to an array index. -constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { - switch (npad_id_type) { - case NpadIdType::Player1: - return 0; - case NpadIdType::Player2: - return 1; - case NpadIdType::Player3: - return 2; - case NpadIdType::Player4: - return 3; - case NpadIdType::Player5: - return 4; - case NpadIdType::Player6: - return 5; - case NpadIdType::Player7: - return 6; - case NpadIdType::Player8: - return 7; - case NpadIdType::Handheld: - return 8; - case NpadIdType::Other: - return 9; - default: - return 0; - } -} - -/// Converts an array index to a NpadIdType -constexpr NpadIdType IndexToNpadIdType(size_t index) { - switch (index) { - case 0: - return NpadIdType::Player1; - case 1: - return NpadIdType::Player2; - case 2: - return NpadIdType::Player3; - case 3: - return NpadIdType::Player4; - case 4: - return NpadIdType::Player5; - case 5: - return NpadIdType::Player6; - case 6: - return NpadIdType::Player7; - case 7: - return NpadIdType::Player8; - case 8: - return NpadIdType::Handheld; - case 9: - return NpadIdType::Other; - default: - return NpadIdType::Invalid; - } -} - // This is nn::hid::NpadStyleIndex enum class NpadStyleIndex : u8 { None = 0, @@ -124,6 +257,27 @@ enum class NpadStyleSet : u32 { }; static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); +// This is nn::hid::VibrationDevicePosition +enum class VibrationDevicePosition : u32 { + None = 0, + Left = 1, + Right = 2, +}; + +// This is nn::hid::VibrationDeviceType +enum class VibrationDeviceType : u32 { + Unknown = 0, + LinearResonantActuator = 1, + GcErm = 2, +}; + +// This is nn::hid::VibrationGcErmCommand +enum class VibrationGcErmCommand : u64 { + Stop = 0, + Start = 1, + StopHard = 2, +}; + // This is nn::hid::NpadStyleTag struct NpadStyleTag { union { @@ -220,53 +374,6 @@ struct LedPattern { }; }; -// This is nn::hid::NpadButton -enum class NpadButton : u64 { - None = 0, - A = 1U << 0, - B = 1U << 1, - X = 1U << 2, - Y = 1U << 3, - StickL = 1U << 4, - StickR = 1U << 5, - L = 1U << 6, - R = 1U << 7, - ZL = 1U << 8, - ZR = 1U << 9, - Plus = 1U << 10, - Minus = 1U << 11, - - Left = 1U << 12, - Up = 1U << 13, - Right = 1U << 14, - Down = 1U << 15, - - StickLLeft = 1U << 16, - StickLUp = 1U << 17, - StickLRight = 1U << 18, - StickLDown = 1U << 19, - - StickRLeft = 1U << 20, - StickRUp = 1U << 21, - StickRRight = 1U << 22, - StickRDown = 1U << 23, - - LeftSL = 1U << 24, - LeftSR = 1U << 25, - - RightSL = 1U << 26, - RightSR = 1U << 27, - - Palma = 1U << 28, - Verification = 1U << 29, - HandheldLeftB = 1U << 30, - LagonCLeft = 1U << 31, - LagonCUp = 1ULL << 32, - LagonCRight = 1ULL << 33, - LagonCDown = 1ULL << 34, -}; -DECLARE_ENUM_FLAG_OPERATORS(NpadButton); - struct NpadButtonState { union { NpadButton raw{}; @@ -342,13 +449,6 @@ struct DebugPadButton { }; static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); -enum class DeviceIndex : u8 { - Left = 0, - Right = 1, - None = 2, - MaxDeviceIndex = 3, -}; - // This is nn::hid::ConsoleSixAxisSensorHandle struct ConsoleSixAxisSensorHandle { u8 unknown_1; @@ -383,20 +483,6 @@ struct VibrationDeviceHandle { }; static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); -// This is nn::hid::VibrationDeviceType -enum class VibrationDeviceType : u32 { - Unknown = 0, - LinearResonantActuator = 1, - GcErm = 2, -}; - -// This is nn::hid::VibrationDevicePosition -enum class VibrationDevicePosition : u32 { - None = 0, - Left = 1, - Right = 2, -}; - // This is nn::hid::VibrationValue struct VibrationValue { f32 low_amplitude; @@ -406,13 +492,6 @@ struct VibrationValue { }; static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); -// This is nn::hid::VibrationGcErmCommand -enum class VibrationGcErmCommand : u64 { - Stop = 0, - Start = 1, - StopHard = 2, -}; - // This is nn::hid::VibrationDeviceInfo struct VibrationDeviceInfo { VibrationDeviceType type{}; @@ -482,4 +561,61 @@ struct MouseState { MouseAttribute attribute; }; static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); + +/// Converts a NpadIdType to an array index. +constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { + switch (npad_id_type) { + case NpadIdType::Player1: + return 0; + case NpadIdType::Player2: + return 1; + case NpadIdType::Player3: + return 2; + case NpadIdType::Player4: + return 3; + case NpadIdType::Player5: + return 4; + case NpadIdType::Player6: + return 5; + case NpadIdType::Player7: + return 6; + case NpadIdType::Player8: + return 7; + case NpadIdType::Handheld: + return 8; + case NpadIdType::Other: + return 9; + default: + return 0; + } +} + +/// Converts an array index to a NpadIdType +constexpr NpadIdType IndexToNpadIdType(size_t index) { + switch (index) { + case 0: + return NpadIdType::Player1; + case 1: + return NpadIdType::Player2; + case 2: + return NpadIdType::Player3; + case 3: + return NpadIdType::Player4; + case 4: + return NpadIdType::Player5; + case 5: + return NpadIdType::Player6; + case 6: + return NpadIdType::Player7; + case 7: + return NpadIdType::Player8; + case 8: + return NpadIdType::Handheld; + case 9: + return NpadIdType::Other; + default: + return NpadIdType::Invalid; + } +} + } // namespace Core::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index d6505dbc5..0ef8af0e6 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -42,6 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, next_state.key = keyboard_state; next_state.modifier = keyboard_modifier_state; + // This is always enabled on HW. Check what it actually does next_state.modifier.unknown.Assign(1); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 496b55d0e..e740b4331 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -35,8 +35,9 @@ namespace Service::HID { // Updating period for each HID device. // Period time is obtained by measuring the number of samples in a second on HW using a homebrew -constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) -constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) +constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) +constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; IAppletResource::IAppletResource(Core::System& system_, @@ -78,14 +79,21 @@ IAppletResource::IAppletResource(Core::System& system_, const auto guard = LockService(); UpdateControllers(user_data, ns_late); }); + keyboard_update_event = Core::Timing::CreateEvent( + "HID::UpdatekeyboardCallback", + [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + const auto guard = LockService(); + UpdateKeyboard(user_data, ns_late); + }); motion_update_event = Core::Timing::CreateEvent( - "HID::MotionPadCallback", + "HID::UpdateMotionCallback", [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { const auto guard = LockService(); UpdateMotion(user_data, ns_late); }); system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); + system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event); system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); system.HIDCore().ReloadInputDevices(); @@ -101,6 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) { IAppletResource::~IAppletResource() { system.CoreTiming().UnscheduleEvent(pad_update_event, 0); + system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0); } @@ -117,18 +126,36 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, auto& core_timing = system.CoreTiming(); for (const auto& controller : controllers) { + // Keyboard has it's own update event + if (controller == controllers[static_cast(HidController::Keyboard)]) { + continue; + } controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); } // If ns_late is higher than the update rate ignore the delay - if (ns_late > motion_update_ns) { + if (ns_late > pad_update_ns) { ns_late = {}; } core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); } +void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + + controllers[static_cast(HidController::Keyboard)]->OnUpdate( + core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); + + // If ns_late is higher than the update rate ignore the delay + if (ns_late > keyboard_update_ns) { + ns_late = {}; + } + + core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event); +} + void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 973e6a8ac..bbad165f8 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -70,11 +70,13 @@ private: void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); + void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); KernelHelpers::ServiceContext& service_context; std::shared_ptr pad_update_event; + std::shared_ptr keyboard_update_event; std::shared_ptr motion_update_event; std::array, static_cast(HidController::MaxControllers)> -- cgit v1.2.3 From bca299e8e0489867f7d4bbfd264e221e7e61ae1e Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 14 Nov 2021 10:45:07 -0600 Subject: input_common: Allow keyboard to be backwards compatible --- src/core/hid/emulated_devices.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 0d840a003..45e0bd80d 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -29,13 +29,29 @@ void EmulatedDevices::ReloadInput() { mouse_button_devices.begin(), Common::Input::CreateDevice); - std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(), - keyboard_devices.begin(), - Common::Input::CreateDeviceFromString); + std::size_t key_index = 0; + for (auto& keyboard_device : keyboard_devices) { + // Keyboard keys are only mapped on port 1, pad 0 + Common::ParamPackage keyboard_params; + keyboard_params.Set("engine", "keyboard"); + keyboard_params.Set("button", static_cast(key_index)); + keyboard_params.Set("port", 1); + keyboard_params.Set("pad", 0); + keyboard_device = Common::Input::CreateDevice(keyboard_params); + key_index++; + } - std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(), - keyboard_modifier_devices.begin(), - Common::Input::CreateDeviceFromString); + key_index = 0; + for (auto& keyboard_device : keyboard_modifier_devices) { + // Keyboard moddifiers are only mapped on port 1, pad 1 + Common::ParamPackage keyboard_params; + keyboard_params.Set("engine", "keyboard"); + keyboard_params.Set("button", static_cast(key_index)); + keyboard_params.Set("port", 1); + keyboard_params.Set("pad", 1); + keyboard_device = Common::Input::CreateDevice(keyboard_params); + key_index++; + } for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { if (!mouse_button_devices[index]) { -- cgit v1.2.3 From 654d76e79e84a3384fa503fac9003a5d0a32f28b Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 14 Nov 2021 14:09:29 -0600 Subject: core/hid: Fully implement native mouse --- src/core/hid/emulated_console.cpp | 11 ++- src/core/hid/emulated_devices.cpp | 124 ++++++++++++++++++------- src/core/hid/emulated_devices.h | 56 ++++++----- src/core/hid/input_converter.cpp | 21 +++++ src/core/hid/input_converter.h | 9 ++ src/core/hle/service/hid/controllers/mouse.cpp | 9 +- 6 files changed, 170 insertions(+), 60 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 374dd5d41..b224932dc 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -24,7 +24,10 @@ void EmulatedConsole::SetTouchParams() { std::size_t index = 0; // Hardcode mouse, touchscreen and cemuhook parameters - touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; + if (!Settings::values.mouse_enabled) { + // We can't use mouse as touch if native mouse is enabled + touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; + } touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"}; touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"}; touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"}; @@ -36,6 +39,9 @@ void EmulatedConsole::SetTouchParams() { // Map the rest of the fingers from touch from button configuration for (const auto& config_entry : touch_buttons) { + if (index >= touch_params.size()) { + continue; + } Common::ParamPackage params{config_entry}; Common::ParamPackage touch_button_params; const int x = params.Get("x", 0); @@ -49,9 +55,6 @@ void EmulatedConsole::SetTouchParams() { touch_button_params.Set("touch_id", static_cast(index)); touch_params[index] = touch_button_params; index++; - if (index >= touch_params.size()) { - return; - } } } diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 45e0bd80d..70a494097 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -15,21 +15,34 @@ EmulatedDevices::EmulatedDevices() = default; EmulatedDevices::~EmulatedDevices() = default; void EmulatedDevices::ReloadFromSettings() { - const auto& mouse = Settings::values.mouse_buttons; - - for (std::size_t index = 0; index < mouse.size(); ++index) { - mouse_button_params[index] = Common::ParamPackage(mouse[index]); - } ReloadInput(); } void EmulatedDevices::ReloadInput() { - std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN, - mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END, - mouse_button_devices.begin(), - Common::Input::CreateDevice); - + // If you load any device here add the equivalent to the UnloadInput() function std::size_t key_index = 0; + for (auto& mouse_device : mouse_button_devices) { + Common::ParamPackage mouse_params; + mouse_params.Set("engine", "mouse"); + mouse_params.Set("button", static_cast(key_index)); + mouse_device = Common::Input::CreateDevice(mouse_params); + key_index++; + } + + mouse_stick_device = Common::Input::CreateDeviceFromString( + "engine:mouse,axis_x:0,axis_y:1"); + + // First two axis are reserved for mouse position + key_index = 2; + for (auto& mouse_device : mouse_analog_devices) { + Common::ParamPackage mouse_params; + mouse_params.Set("engine", "mouse"); + mouse_params.Set("axis", static_cast(key_index)); + mouse_device = Common::Input::CreateDevice(mouse_params); + key_index++; + } + + key_index = 0; for (auto& keyboard_device : keyboard_devices) { // Keyboard keys are only mapped on port 1, pad 0 Common::ParamPackage keyboard_params; @@ -64,6 +77,23 @@ void EmulatedDevices::ReloadInput() { mouse_button_devices[index]->SetCallback(button_callback); } + for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) { + if (!mouse_analog_devices[index]) { + continue; + } + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { + SetMouseAnalog(callback, index); + }}; + mouse_analog_devices[index]->SetCallback(button_callback); + } + + if (mouse_stick_device) { + Common::Input::InputCallback button_callback{ + [this](Common::Input::CallbackStatus callback) { SetMouseStick(callback); }}; + mouse_stick_device->SetCallback(button_callback); + } + for (std::size_t index = 0; index < keyboard_devices.size(); ++index) { if (!keyboard_devices[index]) { continue; @@ -91,6 +121,10 @@ void EmulatedDevices::UnloadInput() { for (auto& button : mouse_button_devices) { button.reset(); } + for (auto& analog : mouse_analog_devices) { + analog.reset(); + } + mouse_stick_device.reset(); for (auto& button : keyboard_devices) { button.reset(); } @@ -116,12 +150,6 @@ void EmulatedDevices::SaveCurrentConfig() { if (!is_configuring) { return; } - - auto& mouse = Settings::values.mouse_buttons; - - for (std::size_t index = 0; index < mouse.size(); ++index) { - mouse[index] = mouse_button_params[index].Serialize(); - } } void EmulatedDevices::RestoreConfig() { @@ -131,21 +159,6 @@ void EmulatedDevices::RestoreConfig() { ReloadFromSettings(); } -Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) const { - if (index >= mouse_button_params.size()) { - return {}; - } - return mouse_button_params[index]; -} - -void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackage param) { - if (index >= mouse_button_params.size()) { - return; - } - mouse_button_params[index] = param; - ReloadInput(); -} - void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= device_status.keyboard_values.size()) { return; @@ -334,6 +347,51 @@ void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std TriggerOnChange(DeviceTriggerType::Mouse); } +void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index) { + if (index >= device_status.mouse_analog_values.size()) { + return; + } + std::lock_guard lock{mutex}; + const auto analog_value = TransformToAnalog(callback); + + device_status.mouse_analog_values[index] = analog_value; + + if (is_configuring) { + device_status.mouse_position_state = {}; + TriggerOnChange(DeviceTriggerType::Mouse); + return; + } + + switch (index) { + case Settings::NativeMouseWheel::X: + device_status.mouse_wheel_state.x = static_cast(analog_value.value); + break; + case Settings::NativeMouseWheel::Y: + device_status.mouse_wheel_state.y = static_cast(analog_value.value); + break; + } + + TriggerOnChange(DeviceTriggerType::Mouse); +} + +void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) { + std::lock_guard lock{mutex}; + const auto stick_value = TransformToStick(callback); + + device_status.mouse_stick_value = stick_value; + + if (is_configuring) { + device_status.mouse_position_state = {}; + TriggerOnChange(DeviceTriggerType::Mouse); + return; + } + + device_status.mouse_position_state.x = stick_value.x.value; + device_status.mouse_position_state.y = stick_value.y.value; + + TriggerOnChange(DeviceTriggerType::Mouse); +} + KeyboardValues EmulatedDevices::GetKeyboardValues() const { return device_status.keyboard_values; } @@ -362,6 +420,10 @@ MousePosition EmulatedDevices::GetMousePosition() const { return device_status.mouse_position_state; } +AnalogStickState EmulatedDevices::GetMouseDeltaWheel() const { + return device_status.mouse_wheel_state; +} + void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { for (const auto& poller_pair : callback_list) { const InterfaceUpdateCallback& poller = poller_pair.second; diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index d49d6d78a..49edfd255 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -17,13 +17,15 @@ #include "core/hid/hid_types.h" namespace Core::HID { - using KeyboardDevices = std::array, Settings::NativeKeyboard::NumKeyboardKeys>; using KeyboardModifierDevices = std::array, Settings::NativeKeyboard::NumKeyboardMods>; using MouseButtonDevices = std::array, Settings::NativeMouseButton::NumMouseButtons>; +using MouseAnalogDevices = std::array, + Settings::NativeMouseWheel::NumMouseWheels>; +using MouseStickDevice = std::unique_ptr; using MouseButtonParams = std::array; @@ -34,12 +36,13 @@ using KeyboardModifierValues = std::array; using MouseButtonValues = std::array; +using MouseAnalogValues = + std::array; +using MouseStickValue = Common::Input::StickStatus; struct MousePosition { - s32 x; - s32 y; - s32 delta_wheel_x; - s32 delta_wheel_y; + f32 x; + f32 y; }; struct DeviceStatus { @@ -47,12 +50,15 @@ struct DeviceStatus { KeyboardValues keyboard_values{}; KeyboardModifierValues keyboard_moddifier_values{}; MouseButtonValues mouse_button_values{}; + MouseAnalogValues mouse_analog_values{}; + MouseStickValue mouse_stick_value{}; // Data for HID serices KeyboardKey keyboard_state{}; KeyboardModifier keyboard_moddifier_state{}; MouseButton mouse_button_state{}; MousePosition mouse_position_state{}; + AnalogStickState mouse_wheel_state{}; }; enum class DeviceTriggerType { @@ -102,15 +108,6 @@ public: /// Reverts any mapped changes made that weren't saved void RestoreConfig(); - /// Returns the current mapped mouse button device - Common::ParamPackage GetMouseButtonParam(std::size_t index) const; - - /** - * Updates the current mapped mouse button device - * @param ParamPackage with controller data to be mapped - */ - void SetMouseButtonParam(std::size_t index, Common::ParamPackage param); - /// Returns the latest status of button input from the keyboard with parameters KeyboardValues GetKeyboardValues() const; @@ -132,9 +129,12 @@ public: /// Returns the latest mouse coordinates MousePosition GetMousePosition() const; + /// Returns the latest mouse wheel change + AnalogStickState GetMouseDeltaWheel() const; + /** * Adds a callback to the list of events - * @param ConsoleUpdateCallback that will be triggered + * @param InterfaceUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(InterfaceUpdateCallback update_callback); @@ -150,26 +150,40 @@ private: void UpdateKey(std::size_t key_index, bool status); /** - * Updates the touch status of the console + * Updates the touch status of the keyboard device * @param callback: A CallbackStatus containing the key status * @param index: key ID to be updated */ void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index); /** - * Updates the touch status of the console + * Updates the keyboard status of the keyboard device * @param callback: A CallbackStatus containing the modifier key status * @param index: modifier key ID to be updated */ void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index); /** - * Updates the touch status of the console + * Updates the mouse button status of the mouse device * @param callback: A CallbackStatus containing the button status - * @param index: Button ID of the to be updated + * @param index: Button ID to be updated */ void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index); + /** + * Updates the mouse wheel status of the mouse device + * @param callback: A CallbackStatus containing the wheel status + * @param index: wheel ID to be updated + */ + void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index); + + /** + * Updates the mouse position status of the mouse device + * @param callback: A CallbackStatus containing the position status + * @param index: stick ID to be updated + */ + void SetMouseStick(Common::Input::CallbackStatus callback); + /** * Triggers a callback that something has changed on the device status * @param Input type of the event to trigger @@ -178,11 +192,11 @@ private: bool is_configuring{false}; - MouseButtonParams mouse_button_params; - KeyboardDevices keyboard_devices; KeyboardModifierDevices keyboard_modifier_devices; MouseButtonDevices mouse_button_devices; + MouseAnalogDevices mouse_analog_devices; + MouseStickDevice mouse_stick_device; mutable std::mutex mutex; std::unordered_map callback_list; diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 480b862fd..c4e653956 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -242,6 +242,27 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta return status; } +Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback) { + Common::Input::AnalogStatus status{}; + + switch (callback.type) { + case Common::Input::InputType::Analog: + status.properties = callback.analog_status.properties; + status.raw_value = callback.analog_status.raw_value; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to analog not implemented", callback.type); + break; + } + + SanitizeAnalog(status, false); + + // Adjust if value is inverted + status.value = status.properties.inverted ? -status.value : status.value; + + return status; +} + void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { const auto& properties = analog.properties; float& raw_value = analog.raw_value; diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h index 2a722b39f..1492489d7 100644 --- a/src/core/hid/input_converter.h +++ b/src/core/hid/input_converter.h @@ -68,6 +68,15 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& */ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); +/** + * Converts raw input data into a valid analog status. Applies offset, deadzone, range and + * invert properties to the output. + * + * @param Supported callbacks: Analog. + * @return A valid AnalogStatus object. + */ +Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); + /** * Converts raw analog data into a valid analog value * @param An analog object containing raw data and properties, bool that determines if the value diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 83e69ca94..9c408e7f4 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -38,13 +38,14 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (Settings::values.mouse_enabled) { const auto& mouse_button_state = emulated_devices->GetMouseButtons(); const auto& mouse_position_state = emulated_devices->GetMousePosition(); + const auto& mouse_wheel_state = emulated_devices->GetMouseDeltaWheel(); next_state.attribute.is_connected.Assign(1); - next_state.x = mouse_position_state.x; - next_state.y = mouse_position_state.y; + next_state.x = static_cast(mouse_position_state.x * Layout::ScreenUndocked::Width); + next_state.y = static_cast(mouse_position_state.y * Layout::ScreenUndocked::Height); next_state.delta_x = next_state.x - last_entry.x; next_state.delta_y = next_state.y - last_entry.y; - next_state.delta_wheel_x = mouse_position_state.delta_wheel_x; - next_state.delta_wheel_y = mouse_position_state.delta_wheel_y; + next_state.delta_wheel_x = mouse_wheel_state.x; + next_state.delta_wheel_y = mouse_wheel_state.y; next_state.button = mouse_button_state; } -- cgit v1.2.3 From f4e5f89e6fb9d68cd4ba7d98c281584c50f0e149 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 14 Nov 2021 21:28:38 -0600 Subject: core/hid: Improve accuary of mouse implementation --- src/core/hid/emulated_devices.cpp | 10 +++---- src/core/hid/emulated_devices.h | 4 +-- src/core/hid/hid_types.h | 35 ++++++++++++++--------- src/core/hid/input_converter.cpp | 4 +++ src/core/hle/service/hid/controllers/keyboard.cpp | 3 +- src/core/hle/service/hid/controllers/keyboard.h | 1 + src/core/hle/service/hid/controllers/mouse.cpp | 7 +++-- src/core/hle/service/hid/controllers/mouse.h | 2 ++ src/core/hle/service/hid/hid.cpp | 29 ++++++++++++------- src/core/hle/service/hid/hid.h | 4 +-- 10 files changed, 61 insertions(+), 38 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 70a494097..874780ec2 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -376,9 +376,9 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) { std::lock_guard lock{mutex}; - const auto stick_value = TransformToStick(callback); + const auto touch_value = TransformToTouch(callback); - device_status.mouse_stick_value = stick_value; + device_status.mouse_stick_value = touch_value; if (is_configuring) { device_status.mouse_position_state = {}; @@ -386,8 +386,8 @@ void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) { return; } - device_status.mouse_position_state.x = stick_value.x.value; - device_status.mouse_position_state.y = stick_value.y.value; + device_status.mouse_position_state.x = touch_value.x.value; + device_status.mouse_position_state.y = touch_value.y.value; TriggerOnChange(DeviceTriggerType::Mouse); } @@ -420,7 +420,7 @@ MousePosition EmulatedDevices::GetMousePosition() const { return device_status.mouse_position_state; } -AnalogStickState EmulatedDevices::GetMouseDeltaWheel() const { +AnalogStickState EmulatedDevices::GetMouseWheel() const { return device_status.mouse_wheel_state; } diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 49edfd255..05a945d08 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -38,7 +38,7 @@ using MouseButtonValues = std::array; using MouseAnalogValues = std::array; -using MouseStickValue = Common::Input::StickStatus; +using MouseStickValue = Common::Input::TouchStatus; struct MousePosition { f32 x; @@ -130,7 +130,7 @@ public: MousePosition GetMousePosition() const; /// Returns the latest mouse wheel change - AnalogStickState GetMouseDeltaWheel() const; + AnalogStickState GetMouseWheel() const; /** * Adds a callback to the list of events diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index af95f3aff..8b12f63ad 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -502,21 +502,30 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor // This is nn::hid::KeyboardModifier struct KeyboardModifier { union { - u64 raw{}; - BitField<0, 1, u64> control; - BitField<1, 1, u64> shift; - BitField<2, 1, u64> left_alt; - BitField<3, 1, u64> right_alt; - BitField<4, 1, u64> gui; - BitField<8, 1, u64> caps_lock; - BitField<9, 1, u64> scroll_lock; - BitField<10, 1, u64> num_lock; - BitField<11, 1, u64> katakana; - BitField<12, 1, u64> hiragana; - BitField<32, 1, u64> unknown; + u32 raw{}; + BitField<0, 1, u32> control; + BitField<1, 1, u32> shift; + BitField<2, 1, u32> left_alt; + BitField<3, 1, u32> right_alt; + BitField<4, 1, u32> gui; + BitField<8, 1, u32> caps_lock; + BitField<9, 1, u32> scroll_lock; + BitField<10, 1, u32> num_lock; + BitField<11, 1, u32> katakana; + BitField<12, 1, u32> hiragana; + }; +}; + +static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size"); + +// This is nn::hid::KeyboardAttribute +struct KeyboardAttribute { + union { + u32 raw{}; + BitField<0, 1, u32> is_connected; }; }; -static_assert(sizeof(KeyboardModifier) == 0x8, "KeyboardModifier is an invalid size"); +static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size"); // This is nn::hid::KeyboardKey struct KeyboardKey { diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index c4e653956..f5acff6e0 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -175,6 +175,10 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& case Common::Input::InputType::Touch: status = callback.touch_status; break; + case Common::Input::InputType::Stick: + status.x = callback.stick_status.x; + status.y = callback.stick_status.y; + break; default: LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type); break; diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 0ef8af0e6..9588a6910 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -42,8 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, next_state.key = keyboard_state; next_state.modifier = keyboard_modifier_state; - // This is always enabled on HW. Check what it actually does - next_state.modifier.unknown.Assign(1); + next_state.attribute.is_connected.Assign(1); } keyboard_lifo.WriteNextEntry(next_state); diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index ec5dd607c..0d61cb470 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -38,6 +38,7 @@ private: struct KeyboardState { s64 sampling_number; Core::HID::KeyboardModifier modifier; + Core::HID::KeyboardAttribute attribute; Core::HID::KeyboardKey key; }; static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 9c408e7f4..ba79888ae 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -38,15 +38,16 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* if (Settings::values.mouse_enabled) { const auto& mouse_button_state = emulated_devices->GetMouseButtons(); const auto& mouse_position_state = emulated_devices->GetMousePosition(); - const auto& mouse_wheel_state = emulated_devices->GetMouseDeltaWheel(); + const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); next_state.attribute.is_connected.Assign(1); next_state.x = static_cast(mouse_position_state.x * Layout::ScreenUndocked::Width); next_state.y = static_cast(mouse_position_state.y * Layout::ScreenUndocked::Height); next_state.delta_x = next_state.x - last_entry.x; next_state.delta_y = next_state.y - last_entry.y; - next_state.delta_wheel_x = mouse_wheel_state.x; - next_state.delta_wheel_y = mouse_wheel_state.y; + next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; + next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; + last_mouse_wheel_state = mouse_wheel_state; next_state.button = mouse_button_state; } diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 25017f117..1ac69aa6f 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -14,6 +14,7 @@ namespace Core::HID { class EmulatedDevices; struct MouseState; +struct AnalogStickState; } // namespace Core::HID namespace Service::HID { @@ -37,6 +38,7 @@ private: static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); Core::HID::MouseState next_state{}; + Core::HID::AnalogStickState last_mouse_wheel_state; Core::HID::EmulatedDevices* emulated_devices; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index e740b4331..95fc07325 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -35,9 +35,9 @@ namespace Service::HID { // Updating period for each HID device. // Period time is obtained by measuring the number of samples in a second on HW using a homebrew -constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) -constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) -constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) +constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) +constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; IAppletResource::IAppletResource(Core::System& system_, @@ -79,11 +79,11 @@ IAppletResource::IAppletResource(Core::System& system_, const auto guard = LockService(); UpdateControllers(user_data, ns_late); }); - keyboard_update_event = Core::Timing::CreateEvent( - "HID::UpdatekeyboardCallback", + mouse_keyboard_update_event = Core::Timing::CreateEvent( + "HID::UpdateMouseKeyboardCallback", [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { const auto guard = LockService(); - UpdateKeyboard(user_data, ns_late); + UpdateMouseKeyboard(user_data, ns_late); }); motion_update_event = Core::Timing::CreateEvent( "HID::UpdateMotionCallback", @@ -93,7 +93,7 @@ IAppletResource::IAppletResource(Core::System& system_, }); system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); - system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event); + system.CoreTiming().ScheduleEvent(mouse_keyboard_update_ns, mouse_keyboard_update_event); system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); system.HIDCore().ReloadInputDevices(); @@ -109,7 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) { IAppletResource::~IAppletResource() { system.CoreTiming().UnscheduleEvent(pad_update_event, 0); - system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0); + system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0); } @@ -130,6 +130,10 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, if (controller == controllers[static_cast(HidController::Keyboard)]) { continue; } + // Mouse has it's own update event + if (controller == controllers[static_cast(HidController::Mouse)]) { + continue; + } controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); } @@ -142,18 +146,21 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); } -void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { +void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data, + std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); + controllers[static_cast(HidController::Mouse)]->OnUpdate( + core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); controllers[static_cast(HidController::Keyboard)]->OnUpdate( core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); // If ns_late is higher than the update rate ignore the delay - if (ns_late > keyboard_update_ns) { + if (ns_late > mouse_keyboard_update_ns) { ns_late = {}; } - core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event); + core_timing.ScheduleEvent(mouse_keyboard_update_ns - ns_late, mouse_keyboard_update_event); } void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index bbad165f8..ab0084118 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -70,13 +70,13 @@ private: void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); - void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); + void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); KernelHelpers::ServiceContext& service_context; std::shared_ptr pad_update_event; - std::shared_ptr keyboard_update_event; + std::shared_ptr mouse_keyboard_update_event; std::shared_ptr motion_update_event; std::array, static_cast(HidController::MaxControllers)> -- cgit v1.2.3 From 42949738f2c01a4125a9a385c9100240181153ec Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 14 Nov 2021 21:56:54 -0600 Subject: kraken: Address comments from review Fix compiler bug --- src/core/hid/hid_types.h | 3 ++- src/core/hle/service/hid/controllers/npad.cpp | 2 +- src/core/hle/service/hid/ring_lifo.h | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 8b12f63ad..3cbe16260 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -564,8 +564,9 @@ struct MouseState { s32 y; s32 delta_x; s32 delta_y; - s32 delta_wheel_x; + // Axis Order in HW is switched for the wheel s32 delta_wheel_y; + s32 delta_wheel_x; MouseButton button; MouseAttribute attribute; }; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index eaec79139..4b23230e1 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -345,7 +345,7 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | btn::StickRRight | btn::StickRDown; - pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask; + pad_entry.npad_buttons.raw = button_state.raw & right_button_mask; pad_entry.r_stick = stick_state.right; } diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h index 6209ed0d1..f0e0bab7f 100644 --- a/src/core/hle/service/hid/ring_lifo.h +++ b/src/core/hle/service/hid/ring_lifo.h @@ -7,7 +7,6 @@ #include #include "common/common_types.h" -#include "common/swap.h" namespace Service::HID { constexpr std::size_t max_buffer_size = 17; @@ -21,7 +20,7 @@ struct AtomicStorage { template struct Lifo { s64 timestamp{}; - s64 total_buffer_count = max_buffer_size; + s64 total_buffer_count = static_cast(max_buffer_size); s64 buffer_tail{}; s64 buffer_count{}; std::array, max_buffer_size> entries{}; @@ -35,11 +34,11 @@ struct Lifo { } std::size_t GetPreviousEntryIndex() const { - return (buffer_tail + total_buffer_count - 1) % total_buffer_count; + return static_cast((buffer_tail + total_buffer_count - 1) % total_buffer_count); } std::size_t GetNextEntryIndex() const { - return (buffer_tail + 1) % total_buffer_count; + return static_cast((buffer_tail + 1) % total_buffer_count); } void WriteNextEntry(const State& new_state) { -- cgit v1.2.3 From 922aa9410a78ef9d6fd5b5d4455375d512333239 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 19 Nov 2021 10:56:52 -0600 Subject: bootmanager: Use cross-platform keyboard input --- src/core/hid/hid_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 1fe2fd89b..609f40f3b 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -52,7 +52,7 @@ public: void UnloadInputDevices(); /// Number of emulated controllers - const std::size_t available_controllers{10}; + static constexpr std::size_t available_controllers{10}; private: std::unique_ptr player_1; -- cgit v1.2.3 From 23bf2e3bb6fe0881e28767e768ad9c0a9f851d57 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Mon, 22 Nov 2021 22:15:34 -0600 Subject: service/hid: Finish converting LIFO objects and address some nits --- src/core/hid/emulated_controller.cpp | 2 +- src/core/hid/hid_types.h | 6 +-- .../service/hid/controllers/console_sixaxis.cpp | 31 +++++------- .../hle/service/hid/controllers/console_sixaxis.h | 31 +++--------- .../hle/service/hid/controllers/controller_base.h | 2 + src/core/hle/service/hid/controllers/debug_pad.h | 2 +- src/core/hle/service/hid/controllers/gesture.h | 2 +- src/core/hle/service/hid/controllers/keyboard.h | 2 +- src/core/hle/service/hid/controllers/mouse.h | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 2 + src/core/hle/service/hid/controllers/npad.h | 56 +++++++--------------- src/core/hle/service/hid/controllers/touchscreen.h | 2 +- src/core/hle/service/hid/controllers/xpad.h | 2 +- src/core/hle/service/hid/ring_lifo.h | 3 +- 14 files changed, 50 insertions(+), 95 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 54c1a2324..54d4ed93d 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -723,7 +723,7 @@ void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std: bool is_charging = false; bool is_powered = false; - BatteryLevel battery_level = 0; + NpadBatteryLevel battery_level = 0; switch (controller.battery_values[index]) { case Common::Input::BatteryLevel::Charging: is_charging = true; diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 3cbe16260..acf54e233 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -346,15 +346,15 @@ struct NpadGcTriggerState { static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); // This is nn::hid::system::NpadBatteryLevel -using BatteryLevel = u32; -static_assert(sizeof(BatteryLevel) == 0x4, "BatteryLevel is an invalid size"); +using NpadBatteryLevel = u32; +static_assert(sizeof(NpadBatteryLevel) == 0x4, "NpadBatteryLevel is an invalid size"); // This is nn::hid::system::NpadPowerInfo struct NpadPowerInfo { bool is_powered; bool is_charging; INSERT_PADDING_BYTES(0x6); - BatteryLevel battery_level; + NpadBatteryLevel battery_level; }; static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index ea7e8f18f..f0f3105dc 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -24,34 +24,25 @@ void Controller_ConsoleSixAxis::OnRelease() {} void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) { - seven_six_axis.header.timestamp = core_timing.GetCPUTicks(); - seven_six_axis.header.total_entry_count = 17; - if (!IsControllerActivated() || !is_transfer_memory_set) { - seven_six_axis.header.entry_count = 0; - seven_six_axis.header.last_entry_index = 0; + seven_sixaxis_lifo.buffer_count = 0; + seven_sixaxis_lifo.buffer_tail = 0; return; } - seven_six_axis.header.entry_count = 16; - - const auto& last_entry = - seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; - seven_six_axis.header.last_entry_index = (seven_six_axis.header.last_entry_index + 1) % 17; - auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; - cur_entry.sampling_number = last_entry.sampling_number + 1; - cur_entry.sampling_number2 = cur_entry.sampling_number; + const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; + next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; // Try to read sixaxis sensor states const auto motion_status = console->GetMotion(); console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; - cur_entry.accel = motion_status.accel; + next_seven_sixaxis_state.accel = motion_status.accel; // Zero gyro values as they just mess up with the camera // Note: Probably a correct sensivity setting must be set - cur_entry.gyro = {}; - cur_entry.quaternion = { + next_seven_sixaxis_state.gyro = {}; + next_seven_sixaxis_state.quaternion = { { motion_status.quaternion.xyz.y, motion_status.quaternion.xyz.x, @@ -68,7 +59,8 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti // Update console six axis shared memory std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis)); // Update seven six axis transfer memory - std::memcpy(transfer_memory, &seven_six_axis, sizeof(seven_six_axis)); + seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); + std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); } void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) { @@ -77,8 +69,7 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) { } void Controller_ConsoleSixAxis::ResetTimestamp() { - auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; - cur_entry.sampling_number = 0; - cur_entry.sampling_number2 = 0; + seven_sixaxis_lifo.buffer_count = 0; + seven_sixaxis_lifo.buffer_tail = 0; } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index 7c92413e8..279241858 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -10,6 +10,7 @@ #include "common/quaternion.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/ring_lifo.h" namespace Core::HID { class EmulatedConsole; @@ -40,50 +41,30 @@ private: struct SevenSixAxisState { INSERT_PADDING_WORDS(4); // unused s64 sampling_number{}; - s64 sampling_number2{}; u64 unknown{}; Common::Vec3f accel{}; Common::Vec3f gyro{}; Common::Quaternion quaternion{}; }; - static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size"); - - struct CommonHeader { - s64 timestamp; - s64 total_entry_count; - s64 last_entry_index; - s64 entry_count; - }; - static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); - - // TODO(german77): SevenSixAxisMemory doesn't follow the standard lifo. Investigate - struct SevenSixAxisMemory { - CommonHeader header{}; - std::array sevensixaxis_states{}; - }; - static_assert(sizeof(SevenSixAxisMemory) == 0xA70, "SevenSixAxisMemory is an invalid size"); + static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat struct ConsoleSharedMemory { u64 sampling_number{}; bool is_seven_six_axis_sensor_at_rest{}; + INSERT_PADDING_BYTES(4); // padding f32 verticalization_error{}; Common::Vec3f gyro_bias{}; }; static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); - struct MotionDevice { - Common::Vec3f accel; - Common::Vec3f gyro; - Common::Vec3f rotation; - std::array orientation; - Common::Quaternion quaternion; - }; + Lifo seven_sixaxis_lifo{}; + static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); Core::HID::EmulatedConsole* console; u8* transfer_memory = nullptr; bool is_transfer_memory_set = false; ConsoleSharedMemory console_six_axis{}; - SevenSixAxisMemory seven_six_axis{}; + SevenSixAxisState next_seven_sixaxis_state{}; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 8125bbc84..7450eb20a 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -41,6 +41,8 @@ public: bool IsControllerActivated() const; + static const std::size_t hid_entry_count = 17; + protected: bool is_activated{false}; diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 15b3afb7a..afe374fc2 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -54,7 +54,7 @@ private: static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); // This is nn::hid::detail::DebugPadLifo - Lifo debug_pad_lifo{}; + Lifo debug_pad_lifo{}; static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); DebugPadState next_state{}; diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index f924464e0..0936a3fa3 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -136,7 +136,7 @@ private: GestureProperties GetGestureProperties(); // This is nn::hid::detail::GestureLifo - Lifo gesture_lifo{}; + Lifo gesture_lifo{}; static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); GestureState next_state{}; diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 0d61cb470..cf62d3896 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -44,7 +44,7 @@ private: static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); // This is nn::hid::detail::KeyboardLifo - Lifo keyboard_lifo{}; + Lifo keyboard_lifo{}; static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); KeyboardState next_state{}; diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 1ac69aa6f..7559fc78d 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -34,7 +34,7 @@ public: private: // This is nn::hid::detail::MouseLifo - Lifo mouse_lifo{}; + Lifo mouse_lifo{}; static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); Core::HID::MouseState next_state{}; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 4b23230e1..dd4d954aa 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -157,6 +157,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_minus.Assign(1); + shared_memory.system_properties.use_directional_buttons.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; break; @@ -167,6 +168,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_minus.Assign(1); + shared_memory.system_properties.use_directional_buttons.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; break; diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 3798c037f..9fa113bb6 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -339,26 +339,6 @@ private: static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, "NfcXcdDeviceHandleStateImpl is an invalid size"); - // nn::hid::detail::NfcXcdDeviceHandleStateImplAtomicStorage - struct NfcXcdDeviceHandleStateImplAtomicStorage { - u64 sampling_number; - NfcXcdDeviceHandleStateImpl nfc_xcd_device_handle_state; - }; - static_assert(sizeof(NfcXcdDeviceHandleStateImplAtomicStorage) == 0x20, - "NfcXcdDeviceHandleStateImplAtomicStorage is an invalid size"); - - // This is nn::hid::detail::NfcXcdDeviceHandleState - struct NfcXcdDeviceHandleState { - // TODO(german77): Make this struct a ring lifo object - INSERT_PADDING_BYTES(0x8); // Unused - s64 total_buffer_count = max_buffer_size; - s64 buffer_tail{}; - s64 buffer_count{}; - std::array nfc_xcd_device_handle_storage; - }; - static_assert(sizeof(NfcXcdDeviceHandleState) == 0x60, - "NfcXcdDeviceHandleState is an invalid size"); - // This is nn::hid::system::AppletFooterUiAttributesSet struct AppletFooterUiAttributes { INSERT_PADDING_BYTES(0x4); @@ -433,32 +413,32 @@ private: NpadJoyAssignmentMode assignment_mode; NpadFullKeyColorState fullkey_color; NpadJoyColorState joycon_color; - Lifo fullkey_lifo; - Lifo handheld_lifo; - Lifo joy_dual_lifo; - Lifo joy_left_lifo; - Lifo joy_right_lifo; - Lifo palma_lifo; - Lifo system_ext_lifo; - Lifo sixaxis_fullkey_lifo; - Lifo sixaxis_handheld_lifo; - Lifo sixaxis_dual_left_lifo; - Lifo sixaxis_dual_right_lifo; - Lifo sixaxis_left_lifo; - Lifo sixaxis_right_lifo; + Lifo fullkey_lifo; + Lifo handheld_lifo; + Lifo joy_dual_lifo; + Lifo joy_left_lifo; + Lifo joy_right_lifo; + Lifo palma_lifo; + Lifo system_ext_lifo; + Lifo sixaxis_fullkey_lifo; + Lifo sixaxis_handheld_lifo; + Lifo sixaxis_dual_left_lifo; + Lifo sixaxis_dual_right_lifo; + Lifo sixaxis_left_lifo; + Lifo sixaxis_right_lifo; DeviceType device_type; INSERT_PADDING_BYTES(0x4); // Reserved NPadSystemProperties system_properties; NpadSystemButtonProperties button_properties; - Core::HID::BatteryLevel battery_level_dual; - Core::HID::BatteryLevel battery_level_left; - Core::HID::BatteryLevel battery_level_right; + Core::HID::NpadBatteryLevel battery_level_dual; + Core::HID::NpadBatteryLevel battery_level_left; + Core::HID::NpadBatteryLevel battery_level_right; union { - NfcXcdDeviceHandleState nfc_xcd_device_handle; + Lifo nfc_xcd_device_lifo{}; AppletFooterUi applet_footer; }; INSERT_PADDING_BYTES(0x20); // Unknown - Lifo gc_trigger_lifo; + Lifo gc_trigger_lifo; NpadLarkType lark_type_l_and_main; NpadLarkType lark_type_r; NpadLuciaType lucia_type; diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 135c2bf13..708dde4f0 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -61,7 +61,7 @@ private: static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); // This is nn::hid::detail::TouchScreenLifo - Lifo touch_screen_lifo{}; + Lifo touch_screen_lifo{}; static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); TouchScreenState next_state{}; diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index 54dae0be1..ba8db8d9d 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -102,7 +102,7 @@ private: static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size"); // This is nn::hid::detail::BasicXpadLifo - Lifo basic_xpad_lifo{}; + Lifo basic_xpad_lifo{}; static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size"); BasicXpadState next_state{}; }; diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h index f0e0bab7f..44c20d967 100644 --- a/src/core/hle/service/hid/ring_lifo.h +++ b/src/core/hle/service/hid/ring_lifo.h @@ -9,7 +9,6 @@ #include "common/common_types.h" namespace Service::HID { -constexpr std::size_t max_buffer_size = 17; template struct AtomicStorage { @@ -17,7 +16,7 @@ struct AtomicStorage { State state; }; -template +template struct Lifo { s64 timestamp{}; s64 total_buffer_count = static_cast(max_buffer_size); -- cgit v1.2.3 From 639402850ac65c694967ef6519becb65abe89b39 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Fri, 26 Nov 2021 15:45:37 -0600 Subject: input_common: Fully implement UDP controllers --- src/core/hid/emulated_console.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index b224932dc..80db8e9c6 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -30,8 +30,10 @@ void EmulatedConsole::SetTouchParams() { } touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"}; touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"}; - touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"}; - touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:2,axis_y:3,button:1"}; + touch_params[index++] = + Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"}; + touch_params[index++] = + Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; const auto button_index = static_cast(Settings::values.touch_from_button_map_index.GetValue()); -- cgit v1.2.3 From 182cd9004f75df21979d0edd47910fecbd129b63 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 26 Nov 2021 19:29:08 -0600 Subject: config: Remove vibration configuration --- src/core/hid/emulated_controller.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 54d4ed93d..06ae41c3e 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -92,10 +92,11 @@ void EmulatedController::ReloadFromSettings() { ReloadInput(); } + void EmulatedController::LoadDevices() { // TODO(german77): Use more buttons to detect the correct device - const auto left_joycon = button_params[Settings::NativeButton::A]; - const auto right_joycon = button_params[Settings::NativeButton::DRight]; + const auto left_joycon = button_params[Settings::NativeButton::DRight]; + const auto right_joycon = button_params[Settings::NativeButton::A]; // Triggers for GC controllers trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; -- cgit v1.2.3 From f966c05a74e2406a6416cf6295459e25c0d675ec Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 25 Nov 2021 20:12:47 -0600 Subject: core/hid: Stub GetUniquePadsFromNpad Used in checkpoint homebrew --- src/core/hle/service/hid/hid.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 95fc07325..b36689552 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1883,7 +1883,7 @@ public: {317, nullptr, "GetNpadLeftRightInterfaceType"}, {318, nullptr, "HasBattery"}, {319, nullptr, "HasLeftRightBattery"}, - {321, nullptr, "GetUniquePadsFromNpad"}, + {321, &HidSys::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"}, {322, nullptr, "GetIrSensorState"}, {323, nullptr, "GetXcdHandleForNpadWithIrSensor"}, {324, nullptr, "GetUniquePadButtonSet"}, @@ -2054,6 +2054,18 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } + + void GetUniquePadsFromNpad(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + const s64 total_entries = 0; + LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(total_entries); + } }; class HidTmp final : public ServiceFramework { -- cgit v1.2.3 From 51df96b7c0ac7086b26fa766e87e18749e0395b1 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 27 Nov 2021 20:05:45 -0600 Subject: settings: Add debug setting to enable all controllers --- src/core/hid/emulated_controller.cpp | 20 ++++++++++++++++++++ src/core/hle/service/hid/controllers/npad.cpp | 4 ++++ 2 files changed, 24 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 06ae41c3e..466ff5542 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -27,6 +27,16 @@ NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerTyp return NpadStyleIndex::Handheld; case Settings::ControllerType::GameCube: return NpadStyleIndex::GameCube; + case Settings::ControllerType::Pokeball: + return NpadStyleIndex::Pokeball; + case Settings::ControllerType::NES: + return NpadStyleIndex::NES; + case Settings::ControllerType::SNES: + return NpadStyleIndex::SNES; + case Settings::ControllerType::N64: + return NpadStyleIndex::N64; + case Settings::ControllerType::SegaGenesis: + return NpadStyleIndex::SegaGenesis; default: return NpadStyleIndex::ProController; } @@ -46,6 +56,16 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleInde return Settings::ControllerType::Handheld; case NpadStyleIndex::GameCube: return Settings::ControllerType::GameCube; + case NpadStyleIndex::Pokeball: + return Settings::ControllerType::Pokeball; + case NpadStyleIndex::NES: + return Settings::ControllerType::NES; + case NpadStyleIndex::SNES: + return Settings::ControllerType::SNES; + case NpadStyleIndex::N64: + return Settings::ControllerType::N64; + case NpadStyleIndex::SegaGenesis: + return Settings::ControllerType::SegaGenesis; default: return Settings::ControllerType::ProController; } diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index dd4d954aa..04b3a68c3 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -263,6 +263,10 @@ void Controller_NPad::OnInit() { style.fullkey.Assign(1); style.gamecube.Assign(1); style.palma.Assign(1); + style.lark.Assign(1); + style.lucia.Assign(1); + style.lagoon.Assign(1); + style.lager.Assign(1); hid_core.SetSupportedStyleTag(style); } -- cgit v1.2.3 From 50d8e753c525f8f00a67678c56351eccf72aa1f4 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 25 Nov 2021 20:36:44 -0600 Subject: core/pdm: Stub QueryPlayStatisticsByApplicationIdAndUserAccountId Used in checkpoint homebrew --- src/core/CMakeLists.txt | 2 ++ src/core/hle/service/ns/ns.cpp | 3 ++ src/core/hle/service/ns/pdm_qry.cpp | 69 +++++++++++++++++++++++++++++++++++++ src/core/hle/service/ns/pdm_qry.h | 33 ++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 src/core/hle/service/ns/pdm_qry.cpp create mode 100644 src/core/hle/service/ns/pdm_qry.h (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 582c15f7e..eee8e2ccd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -479,6 +479,8 @@ add_library(core STATIC hle/service/ns/language.h hle/service/ns/ns.cpp hle/service/ns/ns.h + hle/service/ns/pdm_qry.cpp + hle/service/ns/pdm_qry.h hle/service/ns/pl_u.cpp hle/service/ns/pl_u.h hle/service/nvdrv/devices/nvdevice.h diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 64ffc8572..0d6fab746 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -12,6 +12,7 @@ #include "core/hle/service/ns/errors.h" #include "core/hle/service/ns/language.h" #include "core/hle/service/ns/ns.h" +#include "core/hle/service/ns/pdm_qry.h" #include "core/hle/service/ns/pl_u.h" #include "core/hle/service/set/set.h" @@ -738,6 +739,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system std::make_shared(system)->InstallAsService(service_manager); std::make_shared(system)->InstallAsService(service_manager); + std::make_shared(system)->InstallAsService(service_manager); + std::make_shared(system)->InstallAsService(service_manager); } diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp new file mode 100644 index 000000000..e2fab5c3f --- /dev/null +++ b/src/core/hle/service/ns/pdm_qry.cpp @@ -0,0 +1,69 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include + +#include "common/logging/log.h" +#include "common/uuid.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ns/pdm_qry.h" +#include "core/hle/service/service.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::NS { + +PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "QueryAppletEvent"}, + {1, nullptr, "QueryPlayStatistics"}, + {2, nullptr, "QueryPlayStatisticsByUserAccountId"}, + {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"}, + {4, nullptr, "QueryPlayStatisticsByApplicationId"}, + {5, &PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId, "QueryPlayStatisticsByApplicationIdAndUserAccountId"}, + {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"}, + {7, nullptr, "QueryLastPlayTimeV0"}, + {8, nullptr, "QueryPlayEvent"}, + {9, nullptr, "GetAvailablePlayEventRange"}, + {10, nullptr, "QueryAccountEvent"}, + {11, nullptr, "QueryAccountPlayEvent"}, + {12, nullptr, "GetAvailableAccountPlayEventRange"}, + {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"}, + {14, nullptr, "QueryRecentlyPlayedApplication"}, + {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"}, + {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"}, + {17, nullptr, "QueryLastPlayTime"}, + {18, nullptr, "QueryApplicationPlayStatisticsForSystem"}, + {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +PDM_QRY::~PDM_QRY() = default; + +void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto unknown = rp.Pop(); + rp.Pop(); // Padding + const auto application_id = rp.Pop(); + const auto user_account_uid = rp.PopRaw(); + + // TODO(German77): Read statistics of the game + PlayStatistics statistics{ + .application_id = application_id, + .total_launches = 1, + }; + + LOG_WARNING(Service_NS, + "(STUBBED) called. unknown={}. application_id=0x{:016X}, user_account_uid=0x{}", + unknown, application_id, user_account_uid.Format()); + + IPC::ResponseBuilder rb{ctx, 12}; + rb.Push(ResultSuccess); + rb.PushRaw(statistics); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/pdm_qry.h b/src/core/hle/service/ns/pdm_qry.h new file mode 100644 index 000000000..516136314 --- /dev/null +++ b/src/core/hle/service/ns/pdm_qry.h @@ -0,0 +1,33 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +struct PlayStatistics { + u64 application_id{}; + u32 first_entry_index{}; + u32 first_timestamp_user{}; + u32 first_timestamp_network{}; + u32 last_entry_index{}; + u32 last_timestamp_user{}; + u32 last_timestamp_network{}; + u32 play_time_in_minutes{}; + u32 total_launches{}; +}; +static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size"); + +class PDM_QRY final : public ServiceFramework { +public: + explicit PDM_QRY(Core::System& system_); + ~PDM_QRY() override; + +private: + void QueryPlayStatisticsByApplicationIdAndUserAccountId(Kernel::HLERequestContext& ctx); +}; + +} // namespace Service::NS -- cgit v1.2.3 From 54f007efc6ed311a8356238ea136b9744b68eb75 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 25 Nov 2021 20:39:38 -0600 Subject: core/ns: Implement GetReadOnlyApplicationControlDataInterface Used in checkpoint homebrew --- src/core/hle/service/ns/ns.cpp | 20 +++++++++++++++++++- src/core/hle/service/ns/ns.h | 7 +++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 0d6fab746..382ddcae5 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -571,11 +571,29 @@ IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) IFactoryResetInterface::~IFactoryResetInterface() = default; +IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( + Core::System& system_) + : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetApplicationControlData"}, + {1, nullptr, "GetApplicationDesiredLanguage"}, + {2, nullptr, "ConvertApplicationLanguageToLanguageCode"}, + {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, + {4, nullptr, "SelectApplicationDesiredLanguage"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; + NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {7988, nullptr, "GetDynamicRightsInterface"}, - {7989, nullptr, "GetReadOnlyApplicationControlDataInterface"}, + {7989, &NS::PushInterface, "GetReadOnlyApplicationControlDataInterface"}, {7991, nullptr, "GetReadOnlyApplicationRecordInterface"}, {7992, &NS::PushInterface, "GetECommerceInterface"}, {7993, &NS::PushInterface, "GetApplicationVersionInterface"}, diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 218eec3ec..43540b0fb 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -74,6 +74,13 @@ public: ~IFactoryResetInterface() override; }; +class IReadOnlyApplicationControlDataInterface final + : public ServiceFramework { +public: + explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); + ~IReadOnlyApplicationControlDataInterface() override; +}; + class NS final : public ServiceFramework { public: explicit NS(const char* name, Core::System& system_); -- cgit v1.2.3 From b9b28c0457e81d80fc51670b88692a062ea9e08e Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:16:05 -0500 Subject: core: hid: Cleanup and amend documentation --- src/core/hid/emulated_console.h | 26 +++++++++-------- src/core/hid/emulated_controller.h | 58 ++++++++++++++++++++------------------ src/core/hid/emulated_devices.h | 38 +++++++++++++------------ src/core/hid/input_converter.h | 23 +++++++-------- 4 files changed, 76 insertions(+), 69 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 25c183eee..67981b844 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -78,7 +78,7 @@ struct ConsoleUpdateCallback { class EmulatedConsole { public: /** - * Contains all input data related to the console like motion and touch input + * Contains all input data within the emulated switch console tablet such as touch and motion */ EmulatedConsole(); ~EmulatedConsole(); @@ -89,14 +89,16 @@ public: /// Removes all callbacks created from input devices void UnloadInput(); - /// Sets the emulated console into configuring mode. Locking all HID service events from being - /// moddified + /** + * Sets the emulated console into configuring mode + * This prevents the modification of the HID state of the emulated console by input commands + */ void EnableConfiguration(); - /// Returns the emulated console to the normal behaivour + /// Returns the emulated console into normal mode, allowing the modification of the HID state void DisableConfiguration(); - /// Returns true if the emulated console is on configuring mode + /// Returns true if the emulated console is in configuring mode bool IsConfiguring() const; /// Reload all input devices @@ -116,7 +118,7 @@ public: /** * Updates the current mapped motion device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetMotionParam(Common::ParamPackage param); @@ -134,14 +136,14 @@ public: /** * Adds a callback to the list of events - * @param ConsoleUpdateCallback that will be triggered + * @param update_callback A ConsoleUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(ConsoleUpdateCallback update_callback); /** * Removes a callback from the list stopping any future events to this object - * @param Key corresponding to the callback index in the list + * @param key Key corresponding to the callback index in the list */ void DeleteCallback(int key); @@ -151,20 +153,20 @@ private: /** * Updates the motion status of the console - * @param A CallbackStatus containing gyro and accelerometer data + * @param callback A CallbackStatus containing gyro and accelerometer data */ void SetMotion(Common::Input::CallbackStatus callback); /** * Updates the touch status of the console - * @param callback: A CallbackStatus containing the touch position - * @param index: Finger ID to be updated + * @param callback A CallbackStatus containing the touch position + * @param index Finger ID to be updated */ void SetTouch(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the console status - * @param Input type of the event to trigger + * @param type Input type of the event to trigger */ void TriggerOnChange(ConsoleTriggerType type); diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 2c5d51bc8..5887e3e38 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -132,8 +132,8 @@ struct ControllerUpdateCallback { class EmulatedController { public: /** - * Contains all input data related to this controller. Like buttons, joysticks, motion. - * @param Npad id type for this specific controller + * Contains all input data (buttons, joysticks, vibration, and motion) within this controller. + * @param npad_id_type npad id type for this specific controller */ explicit EmulatedController(NpadIdType npad_id_type_); ~EmulatedController(); @@ -155,7 +155,7 @@ public: /** * Gets the NpadStyleIndex for this controller - * @param If true tmp_npad_type will be returned + * @param get_temporary_value If true tmp_npad_type will be returned * @return NpadStyleIndex set on the controller */ NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; @@ -168,7 +168,7 @@ public: /** * Is the emulated connected - * @param If true tmp_is_connected will be returned + * @param get_temporary_value If true tmp_is_connected will be returned * @return true if the controller has the connected status */ bool IsConnected(bool get_temporary_value = false) const; @@ -179,14 +179,16 @@ public: /// Removes all callbacks created from input devices void UnloadInput(); - /// Sets the emulated console into configuring mode. Locking all HID service events from being - /// moddified + /** + * Sets the emulated controller into configuring mode + * This prevents the modification of the HID state of the emulated controller by input commands + */ void EnableConfiguration(); - /// Returns the emulated console to the normal behaivour + /// Returns the emulated controller into normal mode, allowing the modification of the HID state void DisableConfiguration(); - /// Returns true if the emulated device is on configuring mode + /// Returns true if the emulated controller is in configuring mode bool IsConfiguring() const; /// Reload all input devices @@ -215,19 +217,19 @@ public: /** * Updates the current mapped button device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetButtonParam(std::size_t index, Common::ParamPackage param); /** * Updates the current mapped stick device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetStickParam(std::size_t index, Common::ParamPackage param); /** * Updates the current mapped motion device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetMotionParam(std::size_t index, Common::ParamPackage param); @@ -270,13 +272,13 @@ public: /// Returns the latest battery status from the controller BatteryLevelState GetBattery() const; - /* + /** * Sends a specific vibration to the output device * @return returns true if vibration had no errors */ bool SetVibration(std::size_t device_index, VibrationValue vibration); - /* + /** * Sends a small vibration to the output device * @return returns true if SetVibration was successfull */ @@ -290,14 +292,14 @@ public: /** * Adds a callback to the list of events - * @param ConsoleUpdateCallback that will be triggered + * @param update_callback A ConsoleUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(ControllerUpdateCallback update_callback); /** * Removes a callback from the list stopping any future events to this object - * @param Key corresponding to the callback index in the list + * @param key Key corresponding to the callback index in the list */ void DeleteCallback(int key); @@ -310,43 +312,43 @@ private: /** * Updates the button status of the controller - * @param callback: A CallbackStatus containing the button status - * @param index: Button ID of the to be updated + * @param callback A CallbackStatus containing the button status + * @param index Button ID of the to be updated */ void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the analog stick status of the controller - * @param callback: A CallbackStatus containing the analog stick status - * @param index: stick ID of the to be updated + * @param callback A CallbackStatus containing the analog stick status + * @param index stick ID of the to be updated */ void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the trigger status of the controller - * @param callback: A CallbackStatus containing the trigger status - * @param index: trigger ID of the to be updated + * @param callback A CallbackStatus containing the trigger status + * @param index trigger ID of the to be updated */ void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the motion status of the controller - * @param callback: A CallbackStatus containing gyro and accelerometer data - * @param index: motion ID of the to be updated + * @param callback A CallbackStatus containing gyro and accelerometer data + * @param index motion ID of the to be updated */ void SetMotion(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the battery status of the controller - * @param callback: A CallbackStatus containing the battery status - * @param index: Button ID of the to be updated + * @param callback A CallbackStatus containing the battery status + * @param index Button ID of the to be updated */ void SetBattery(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the controller status - * @param type: Input type of the event to trigger - * @param is_service_update: indicates if this event should be sended to only services + * @param type Input type of the event to trigger + * @param is_service_update indicates if this event should only be sent to HID services */ void TriggerOnChange(ControllerTriggerType type, bool is_service_update); @@ -357,7 +359,7 @@ private: f32 motion_sensitivity{0.01f}; bool force_update_motion{false}; - // Temporary values to avoid doing changes while the controller is on configuration mode + // Temporary values to avoid doing changes while the controller is in configuring mode NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; bool tmp_is_connected{false}; diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 05a945d08..d4f457651 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -75,7 +75,7 @@ class EmulatedDevices { public: /** * Contains all input data related to external devices that aren't necesarily a controller - * like keyboard and mouse + * This includes devices such as the keyboard or mouse */ EmulatedDevices(); ~EmulatedDevices(); @@ -86,14 +86,16 @@ public: /// Removes all callbacks created from input devices void UnloadInput(); - /// Sets the emulated console into configuring mode. Locking all HID service events from being - /// moddified + /** + * Sets the emulated devices into configuring mode + * This prevents the modification of the HID state of the emulated devices by input commands + */ void EnableConfiguration(); - /// Returns the emulated console to the normal behaivour + /// Returns the emulated devices into normal mode, allowing the modification of the HID state void DisableConfiguration(); - /// Returns true if the emulated device is on configuring mode + /// Returns true if the emulated device is in configuring mode bool IsConfiguring() const; /// Reload all input devices @@ -134,14 +136,14 @@ public: /** * Adds a callback to the list of events - * @param InterfaceUpdateCallback that will be triggered + * @param update_callback InterfaceUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(InterfaceUpdateCallback update_callback); /** * Removes a callback from the list stopping any future events to this object - * @param Key corresponding to the callback index in the list + * @param key Key corresponding to the callback index in the list */ void DeleteCallback(int key); @@ -151,42 +153,42 @@ private: /** * Updates the touch status of the keyboard device - * @param callback: A CallbackStatus containing the key status - * @param index: key ID to be updated + * @param callback A CallbackStatus containing the key status + * @param index key ID to be updated */ void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the keyboard status of the keyboard device - * @param callback: A CallbackStatus containing the modifier key status - * @param index: modifier key ID to be updated + * @param callback A CallbackStatus containing the modifier key status + * @param index modifier key ID to be updated */ void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the mouse button status of the mouse device - * @param callback: A CallbackStatus containing the button status - * @param index: Button ID to be updated + * @param callback A CallbackStatus containing the button status + * @param index Button ID to be updated */ void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the mouse wheel status of the mouse device - * @param callback: A CallbackStatus containing the wheel status - * @param index: wheel ID to be updated + * @param callback A CallbackStatus containing the wheel status + * @param index wheel ID to be updated */ void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the mouse position status of the mouse device - * @param callback: A CallbackStatus containing the position status - * @param index: stick ID to be updated + * @param callback A CallbackStatus containing the position status + * @param index stick ID to be updated */ void SetMouseStick(Common::Input::CallbackStatus callback); /** * Triggers a callback that something has changed on the device status - * @param Input type of the event to trigger + * @param type Input type of the event to trigger */ void TriggerOnChange(DeviceTriggerType type); diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h index 1492489d7..d24582226 100644 --- a/src/core/hid/input_converter.h +++ b/src/core/hid/input_converter.h @@ -21,7 +21,7 @@ namespace Core::HID { /** * Converts raw input data into a valid battery status. * - * @param Supported callbacks: Analog, Battery, Trigger. + * @param callback Supported callbacks: Analog, Battery, Trigger. * @return A valid BatteryStatus object. */ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback); @@ -29,7 +29,7 @@ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackSta /** * Converts raw input data into a valid button status. Applies invert properties to the output. * - * @param Supported callbacks: Analog, Button, Trigger. + * @param callback Supported callbacks: Analog, Button, Trigger. * @return A valid TouchStatus object. */ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback); @@ -37,7 +37,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu /** * Converts raw input data into a valid motion status. * - * @param Supported callbacks: Motion. + * @param callback Supported callbacks: Motion. * @return A valid TouchStatus object. */ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback); @@ -46,7 +46,7 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert * properties to the output. * - * @param Supported callbacks: Stick. + * @param callback Supported callbacks: Stick. * @return A valid StickStatus object. */ Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback); @@ -54,7 +54,7 @@ Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& /** * Converts raw input data into a valid touch status. * - * @param Supported callbacks: Touch. + * @param callback Supported callbacks: Touch. * @return A valid TouchStatus object. */ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback); @@ -63,7 +63,7 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and * invert properties to the output. Button status uses the threshold property if necessary. * - * @param Supported callbacks: Analog, Button, Trigger. + * @param callback Supported callbacks: Analog, Button, Trigger. * @return A valid TriggerStatus object. */ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); @@ -72,22 +72,23 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta * Converts raw input data into a valid analog status. Applies offset, deadzone, range and * invert properties to the output. * - * @param Supported callbacks: Analog. + * @param callback Supported callbacks: Analog. * @return A valid AnalogStatus object. */ Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); /** * Converts raw analog data into a valid analog value - * @param An analog object containing raw data and properties, bool that determines if the value - * needs to be clamped between -1.0f and 1.0f. + * @param analog An analog object containing raw data and properties + * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f. */ void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value); /** * Converts raw stick data into a valid stick value - * @param Two analog objects containing raw data and properties, bool that determines if the value - * needs to be clamped into the unit circle. + * @param analog_x raw analog data and properties for the x-axis + * @param analog_y raw analog data and properties for the y-axis + * @param clamp_value bool that determines if the value needs to be clamped into the unit circle. */ void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, bool clamp_value); -- cgit v1.2.3 From 04f48f0120f7f7f3f573ef13aa0feba88aa3172c Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:17:55 -0500 Subject: core: hid: Mark constructors as explicit --- src/core/hid/emulated_console.h | 2 +- src/core/hid/emulated_devices.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 67981b844..bb3d7ab90 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -80,7 +80,7 @@ public: /** * Contains all input data within the emulated switch console tablet such as touch and motion */ - EmulatedConsole(); + explicit EmulatedConsole(); ~EmulatedConsole(); YUZU_NON_COPYABLE(EmulatedConsole); diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index d4f457651..c72327681 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -77,7 +77,7 @@ public: * Contains all input data related to external devices that aren't necesarily a controller * This includes devices such as the keyboard or mouse */ - EmulatedDevices(); + explicit EmulatedDevices(); ~EmulatedDevices(); YUZU_NON_COPYABLE(EmulatedDevices); -- cgit v1.2.3 From 410df5446eb23e75582020790bce2e8241da88ff Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:22:59 -0500 Subject: general: Fix handheld typo --- src/core/hle/service/hid/controllers/npad.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 04b3a68c3..35dbf12df 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -635,7 +635,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing // This buffer only is updated on handheld on HW npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); } else { - // Hanheld doesn't update this buffer on HW + // Handheld doesn't update this buffer on HW npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); } -- cgit v1.2.3 From 940375dfbbbb14480de042c96128aaded894e827 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:59:58 -0500 Subject: core: hid: hid_core: Add (Enable/DIsable)AllControllerConfiguration --- src/core/hid/hid_core.cpp | 26 ++++++++++++++++++++++++++ src/core/hid/hid_core.h | 6 ++++++ 2 files changed, 32 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index 741a69c3c..946adde00 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -135,6 +135,32 @@ NpadIdType HIDCore::GetFirstNpadId() const { return NpadIdType::Player1; } +void HIDCore::EnableAllControllerConfiguration() { + player_1->EnableConfiguration(); + player_2->EnableConfiguration(); + player_3->EnableConfiguration(); + player_4->EnableConfiguration(); + player_5->EnableConfiguration(); + player_6->EnableConfiguration(); + player_7->EnableConfiguration(); + player_8->EnableConfiguration(); + other->EnableConfiguration(); + handheld->EnableConfiguration(); +} + +void HIDCore::DisableAllControllerConfiguration() { + player_1->DisableConfiguration(); + player_2->DisableConfiguration(); + player_3->DisableConfiguration(); + player_4->DisableConfiguration(); + player_5->DisableConfiguration(); + player_6->DisableConfiguration(); + player_7->DisableConfiguration(); + player_8->DisableConfiguration(); + other->DisableConfiguration(); + handheld->DisableConfiguration(); +} + void HIDCore::ReloadInputDevices() { player_1->ReloadFromSettings(); player_2->ReloadFromSettings(); diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 609f40f3b..140a0e962 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -45,6 +45,12 @@ public: /// Returns the first connected npad id NpadIdType GetFirstNpadId() const; + /// Sets all emulated controllers into configuring mode. + void EnableAllControllerConfiguration(); + + /// Sets all emulated controllers into normal mode. + void DisableAllControllerConfiguration(); + /// Reloads all input devices from settings void ReloadInputDevices(); -- cgit v1.2.3 From bfac21fca10e1bc2f6888ce8592dc58bd9f2ffc3 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 18:20:34 -0500 Subject: core: hid: hid_types: Add "All" to NpadButton This represents a bitmask for all pressed buttons --- src/core/hid/hid_types.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index acf54e233..780659b86 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -63,6 +63,8 @@ enum class NpadButton : u64 { LagonCUp = 1ULL << 32, LagonCRight = 1ULL << 33, LagonCDown = 1ULL << 34, + + All = 0xFFFFFFFFFFFFFFFFULL, }; DECLARE_ENUM_FLAG_OPERATORS(NpadButton); -- cgit v1.2.3 From 322339a5fd4ed78826ecea42e71bc179afb7b5a7 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 18:23:52 -0500 Subject: npad: Return NpadButton in GetAndResetPressState We were previously truncating this to a u32 as there were no known buttons that used the full 64 bits of this type. Fix this now that we know they are used. --- src/core/hle/service/hid/controllers/npad.cpp | 6 +++--- src/core/hle/service/hid/controllers/npad.h | 4 ++-- src/core/memory/cheat_engine.cpp | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 35dbf12df..6916930f7 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -510,7 +510,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* libnx_state.r_stick = pad_state.r_stick; npad.system_ext_lifo.WriteNextEntry(pad_state); - press_state |= static_cast(pad_state.npad_buttons.raw); + press_state |= static_cast(pad_state.npad_buttons.raw); std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), &controller.shared_memory_entry, sizeof(NpadInternalState)); @@ -1149,8 +1149,8 @@ void Controller_NPad::ClearAllControllers() { } } -u32 Controller_NPad::GetAndResetPressState() { - return press_state.exchange(0); +Core::HID::NpadButton Controller_NPad::GetAndResetPressState() { + return static_cast(press_state.exchange(0)); } bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 9fa113bb6..de5fa5a64 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -179,7 +179,7 @@ public: // Logical OR for all buttons presses on all controllers // Specifically for cheat engine and other features. - u32 GetAndResetPressState(); + Core::HID::NpadButton GetAndResetPressState(); static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle); @@ -503,7 +503,7 @@ private: NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; - std::atomic press_state{}; + std::atomic press_state{}; std::array controller_data{}; KernelHelpers::ServiceContext& service_context; diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 20f0e90f5..12446c9ac 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -19,7 +19,6 @@ namespace Core::Memory { namespace { constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12}; -constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) { auto end_index = start_index; @@ -61,7 +60,7 @@ u64 StandardVmCallbacks::HidKeysDown() { applet_resource ->GetController(Service::HID::HidController::NPad) .GetAndResetPressState(); - return press_state & KEYPAD_BITMASK; + return static_cast(press_state & HID::NpadButton::All); } void StandardVmCallbacks::DebugLog(u8 id, u64 value) { -- cgit v1.2.3 From 5deecd714b78233a4cec207b67d2a32c2defbf0a Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 29 Nov 2021 18:26:52 -0500 Subject: input_interpreter: Make use of NpadButton instead of a u64 Allows us to be more explicit with the representation of button states and use the provided bit manipulation operators --- src/core/hid/input_interpreter.cpp | 16 ++++++++-------- src/core/hid/input_interpreter.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp index 870422d82..2dbda8814 100644 --- a/src/core/hid/input_interpreter.cpp +++ b/src/core/hid/input_interpreter.cpp @@ -20,7 +20,7 @@ InputInterpreter::InputInterpreter(Core::System& system) InputInterpreter::~InputInterpreter() = default; void InputInterpreter::PollInput() { - const u64 button_state = npad.GetAndResetPressState(); + const auto button_state = npad.GetAndResetPressState(); previous_index = current_index; current_index = (current_index + 1) % button_states.size(); @@ -32,30 +32,30 @@ void InputInterpreter::ResetButtonStates() { previous_index = 0; current_index = 0; - button_states[0] = 0xFFFFFFFFFFFFFFFF; + button_states[0] = Core::HID::NpadButton::All; for (std::size_t i = 1; i < button_states.size(); ++i) { - button_states[i] = 0; + button_states[i] = Core::HID::NpadButton::None; } } bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { - return (button_states[current_index] & static_cast(button)) != 0; + return True(button_states[current_index] & button); } bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { - const bool current_press = (button_states[current_index] & static_cast(button)) != 0; - const bool previous_press = (button_states[previous_index] & static_cast(button)) != 0; + const bool current_press = True(button_states[current_index] & button); + const bool previous_press = True(button_states[previous_index] & button); return current_press && !previous_press; } bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { - u64 held_buttons{button_states[0]}; + Core::HID::NpadButton held_buttons{button_states[0]}; for (std::size_t i = 1; i < button_states.size(); ++i) { held_buttons &= button_states[i]; } - return (held_buttons & static_cast(button)) != 0; + return True(held_buttons & button); } diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h index 1c2e02142..70c34d474 100644 --- a/src/core/hid/input_interpreter.h +++ b/src/core/hid/input_interpreter.h @@ -105,7 +105,7 @@ private: Service::HID::Controller_NPad& npad; /// Stores 9 consecutive button states polled from HID. - std::array button_states{}; + std::array button_states{}; std::size_t previous_index{}; std::size_t current_index{}; -- cgit v1.2.3 From 505ae5ea1bec7e17dba3d1b4382a839797eff83d Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 30 Nov 2021 12:19:21 -0500 Subject: service: friend: Implement GetCompletionEvent - Used by Super Bomberman R Online --- src/core/hle/service/friend/friend.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 68c9240ae..3c36f4085 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -17,10 +17,11 @@ namespace Service::Friend { class IFriendService final : public ServiceFramework { public: - explicit IFriendService(Core::System& system_) : ServiceFramework{system_, "IFriendService"} { + explicit IFriendService(Core::System& system_) + : ServiceFramework{system_, "IFriendService"}, service_context{system, "IFriendService"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetCompletionEvent"}, + {0, &IFriendService::GetCompletionEvent, "GetCompletionEvent"}, {1, nullptr, "Cancel"}, {10100, nullptr, "GetFriendListIds"}, {10101, &IFriendService::GetFriendList, "GetFriendList"}, @@ -109,6 +110,12 @@ public: // clang-format on RegisterHandlers(functions); + + completion_event = service_context.CreateEvent("IFriendService:CompletionEvent"); + } + + ~IFriendService() override { + service_context.CloseEvent(completion_event); } private: @@ -129,6 +136,14 @@ private: }; static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size"); + void GetCompletionEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Friend, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(completion_event->GetReadableEvent()); + } + void GetBlockedUserListIds(Kernel::HLERequestContext& ctx) { // This is safe to stub, as there should be no adverse consequences from reporting no // blocked users. @@ -179,6 +194,10 @@ private: rb.Push(0); // Friend count // TODO(ogniK): Return a buffer of u64s which are the "NetworkServiceAccountId" } + + KernelHelpers::ServiceContext service_context; + + Kernel::KEvent* completion_event; }; class INotificationService final : public ServiceFramework { -- cgit v1.2.3 From 2c47f8aa1886522898b5b3a73185b5662be3e9f3 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Thu, 2 Dec 2021 12:19:43 +0800 Subject: Support multiple videos playing --- src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | 11 ++++++++--- src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | 5 +++-- src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | 3 ++- src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 11 ++++++++--- 4 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 0d7d4ad03..8e2a16d86 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -21,7 +21,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& case 0x0: switch (command.cmd) { case 0x1: - return Submit(input, output); + return Submit(fd, input, output); case 0x2: return GetSyncpoint(input, output); case 0x3: @@ -62,11 +62,16 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& return NvResult::NotImplemented; } -void nvhost_nvdec::OnOpen(DeviceFD fd) {} +void nvhost_nvdec::OnOpen(DeviceFD fd) { + static u32 next_id{}; + fd_to_id[fd] = next_id++; +} void nvhost_nvdec::OnClose(DeviceFD fd) { LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); - system.GPU().ClearCdmaInstance(); + if (fd_to_id.find(fd) != fd_to_id.end()) { + system.GPU().ClearCdmaInstance(fd_to_id[fd]); + } } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index e61261f98..8a05f0668 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -59,7 +59,8 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector& input) { return NvResult::Success; } -NvResult nvhost_nvdec_common::Submit(const std::vector& input, std::vector& output) { +NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector& input, + std::vector& output) { IoctlSubmit params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); @@ -93,7 +94,7 @@ NvResult nvhost_nvdec_common::Submit(const std::vector& input, std::vectoraddr + cmd_buffer.offset, cmdlist.data(), cmdlist.size() * sizeof(u32)); - gpu.PushCommandBuffer(cmdlist); + gpu.PushCommandBuffer(fd_to_id[fd], cmdlist); } std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); // Some games expect command_buffers to be written back diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 351625c17..e28c54df6 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -104,13 +104,14 @@ protected: /// Ioctl command implementations NvResult SetNVMAPfd(const std::vector& input); - NvResult Submit(const std::vector& input, std::vector& output); + NvResult Submit(DeviceFD fd, const std::vector& input, std::vector& output); NvResult GetSyncpoint(const std::vector& input, std::vector& output); NvResult GetWaitbase(const std::vector& input, std::vector& output); NvResult MapBuffer(const std::vector& input, std::vector& output); NvResult UnmapBuffer(const std::vector& input, std::vector& output); NvResult SetSubmitTimeout(const std::vector& input, std::vector& output); + std::unordered_map fd_to_id{}; s32_le nvmap_fd{}; u32_le submit_timeout{}; std::shared_ptr nvmap_dev; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index eac4dd530..420fe21c8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -21,7 +21,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& i case 0x0: switch (command.cmd) { case 0x1: - return Submit(input, output); + return Submit(fd, input, output); case 0x2: return GetSyncpoint(input, output); case 0x3: @@ -62,10 +62,15 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& i return NvResult::NotImplemented; } -void nvhost_vic::OnOpen(DeviceFD fd) {} +void nvhost_vic::OnOpen(DeviceFD fd) { + static u32 next_id{}; + fd_to_id[fd] = next_id++; +} void nvhost_vic::OnClose(DeviceFD fd) { - system.GPU().ClearCdmaInstance(); + if (fd_to_id.find(fd) != fd_to_id.end()) { + system.GPU().ClearCdmaInstance(fd_to_id[fd]); + } } } // namespace Service::Nvidia::Devices -- cgit v1.2.3 From 762b8ad448369cc770beae4d8368a6258b13709e Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 2 Dec 2021 14:20:43 -0500 Subject: general: Replace high_resolution_clock with steady_clock On some OSes, high_resolution_clock is an alias to system_clock and is not monotonic in nature. Replace this with steady_clock. --- src/core/hle/service/audio/hwopus.cpp | 4 ++-- src/core/perf_stats.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 7da1f2969..981b6c996 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -96,7 +96,7 @@ private: bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector& input, std::vector& output, u64* out_performance_time) const { - const auto start_time = std::chrono::high_resolution_clock::now(); + const auto start_time = std::chrono::steady_clock::now(); const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); if (sizeof(OpusPacketHeader) > input.size()) { LOG_ERROR(Audio, "Input is smaller than the header size, header_sz={}, input_sz={}", @@ -135,7 +135,7 @@ private: return false; } - const auto end_time = std::chrono::high_resolution_clock::now() - start_time; + const auto end_time = std::chrono::steady_clock::now() - start_time; sample_count = out_sample_count; consumed = static_cast(sizeof(OpusPacketHeader) + hdr.size); if (out_performance_time != nullptr) { diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index a2541906f..816202588 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h @@ -33,7 +33,7 @@ public: explicit PerfStats(u64 title_id_); ~PerfStats(); - using Clock = std::chrono::high_resolution_clock; + using Clock = std::chrono::steady_clock; void BeginSystemFrame(); void EndSystemFrame(); @@ -87,7 +87,7 @@ private: class SpeedLimiter { public: - using Clock = std::chrono::high_resolution_clock; + using Clock = std::chrono::steady_clock; void DoSpeedLimiting(std::chrono::microseconds current_system_time_us); -- cgit v1.2.3 From f138731e2fc46d44ae2dc3a15e0dd435d65ddb8d Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 2 Dec 2021 20:12:24 -0500 Subject: service: am: ISelfController: Stub SaveCurrentScreenshot - Used by Disney Magical World 2: Enchanted Edition --- src/core/hle/service/am/am.cpp | 14 +++++++++++++- src/core/hle/service/am/am.h | 1 + src/core/hle/service/caps/caps.h | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index aee8d4f93..e60661fe1 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -30,6 +30,7 @@ #include "core/hle/service/apm/apm_controller.h" #include "core/hle/service/apm/apm_interface.h" #include "core/hle/service/bcat/backend/backend.h" +#include "core/hle/service/caps/caps.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/nvflinger/nvflinger.h" @@ -298,7 +299,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, {110, nullptr, "SetApplicationAlbumUserData"}, - {120, nullptr, "SaveCurrentScreenshot"}, + {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, {130, nullptr, "SetRecordVolumeMuted"}, {1000, nullptr, "GetDebugStorageChannel"}, }; @@ -579,6 +580,17 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestCo rb.Push(ResultSuccess); } +void ISelfController::SaveCurrentScreenshot(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto album_report_option = rp.PopEnum(); + + LOG_WARNING(Service_AM, "(STUBBED) called. album_report_option={}", album_report_option); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + AppletMessageQueue::AppletMessageQueue(Core::System& system) : service_context{system, "AppletMessageQueue"} { on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 202d20757..2a578aea5 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -151,6 +151,7 @@ private: void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx); + void SaveCurrentScreenshot(Kernel::HLERequestContext& ctx); enum class ScreenshotPermission : u32 { Inherit = 0, diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h index b18adcb9d..7254055e6 100644 --- a/src/core/hle/service/caps/caps.h +++ b/src/core/hle/service/caps/caps.h @@ -24,7 +24,7 @@ enum class AlbumImageOrientation { Orientation3 = 3, }; -enum class AlbumReportOption { +enum class AlbumReportOption : s32 { Disable = 0, Enable = 1, }; -- cgit v1.2.3 From 5462485cc3835941713b835bce3b671b15d210b7 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Fri, 3 Dec 2021 12:31:07 +0800 Subject: Address feedback --- src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | 16 +++++++++------- src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | 3 +++ src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 13 +++++++------ src/core/hle/service/nvdrv/devices/nvhost_vic.h | 3 +++ 4 files changed, 22 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 8e2a16d86..8314d1ec2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -20,8 +20,12 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& switch (command.group) { case 0x0: switch (command.cmd) { - case 0x1: + case 0x1: { + if (!fd_to_id.contains(fd)) { + fd_to_id[fd] = next_id++; + } return Submit(fd, input, output); + } case 0x2: return GetSyncpoint(input, output); case 0x3: @@ -62,15 +66,13 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& return NvResult::NotImplemented; } -void nvhost_nvdec::OnOpen(DeviceFD fd) { - static u32 next_id{}; - fd_to_id[fd] = next_id++; -} +void nvhost_nvdec::OnOpen(DeviceFD fd) {} void nvhost_nvdec::OnClose(DeviceFD fd) { LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); - if (fd_to_id.find(fd) != fd_to_id.end()) { - system.GPU().ClearCdmaInstance(fd_to_id[fd]); + const auto iter = fd_to_id.find(fd); + if (iter != fd_to_id.end()) { + system.GPU().ClearCdmaInstance(iter->second); } } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 523d96e3a..a507c4d0a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -24,6 +24,9 @@ public: void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; + +private: + u32 next_id{}; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 420fe21c8..76b39806f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -21,6 +21,9 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& i case 0x0: switch (command.cmd) { case 0x1: + if (!fd_to_id.contains(fd)) { + fd_to_id[fd] = next_id++; + } return Submit(fd, input, output); case 0x2: return GetSyncpoint(input, output); @@ -62,14 +65,12 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& i return NvResult::NotImplemented; } -void nvhost_vic::OnOpen(DeviceFD fd) { - static u32 next_id{}; - fd_to_id[fd] = next_id++; -} +void nvhost_vic::OnOpen(DeviceFD fd) {} void nvhost_vic::OnClose(DeviceFD fd) { - if (fd_to_id.find(fd) != fd_to_id.end()) { - system.GPU().ClearCdmaInstance(fd_to_id[fd]); + const auto iter = fd_to_id.find(fd); + if (iter != fd_to_id.end()) { + system.GPU().ClearCdmaInstance(iter->second); } } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index 6d7fda9d1..c9732c037 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -23,5 +23,8 @@ public: void OnOpen(DeviceFD fd) override; void OnClose(DeviceFD fd) override; + +private: + u32 next_id{}; }; } // namespace Service::Nvidia::Devices -- cgit v1.2.3 From 7fe455e42ea1a8d5e702258212d54f21f1f31610 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 4 Dec 2021 19:37:03 -0600 Subject: core/hid: Ensure only valid npad are connected --- src/core/hid/emulated_controller.cpp | 43 +++++++++++++++++++++++++++ src/core/hid/emulated_controller.h | 14 +++++++++ src/core/hid/hid_core.cpp | 10 +++++++ src/core/hid/hid_core.h | 2 +- src/core/hid/hid_types.h | 2 ++ src/core/hle/service/hid/controllers/npad.cpp | 30 ++++++++----------- 6 files changed, 83 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 466ff5542..720706794 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -866,7 +866,50 @@ void EmulatedController::SetLedPattern() { } } +void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) { + supported_style_tag = supported_styles; + if (!is_connected) { + return; + } + if (!IsControllerSupported()) { + LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller", + npad_type); + Disconnect(); + } +} + +bool EmulatedController::IsControllerSupported() const { + switch (npad_type) { + case NpadStyleIndex::ProController: + return supported_style_tag.fullkey; + case NpadStyleIndex::JoyconDual: + return supported_style_tag.joycon_dual; + case NpadStyleIndex::JoyconLeft: + return supported_style_tag.joycon_left; + case NpadStyleIndex::JoyconRight: + return supported_style_tag.joycon_right; + case NpadStyleIndex::GameCube: + return supported_style_tag.gamecube; + case NpadStyleIndex::Pokeball: + return supported_style_tag.palma; + case NpadStyleIndex::NES: + return supported_style_tag.lark; + case NpadStyleIndex::SNES: + return supported_style_tag.lucia; + case NpadStyleIndex::N64: + return supported_style_tag.lagoon; + case NpadStyleIndex::SegaGenesis: + return supported_style_tag.lager; + default: + return false; + } +} + void EmulatedController::Connect() { + if (!IsControllerSupported()) { + LOG_ERROR(Service_HID, "Controller type {} is not supported", npad_type); + return; + } { std::lock_guard lock{mutex}; if (is_configuring) { diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 5887e3e38..425b3e7c4 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -160,6 +160,13 @@ public: */ NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; + /** + * Sets the supported controller types. Disconnects the controller if current type is not + * supported + * @param supported_styles bitflag with supported types + */ + void SetSupportedNpadStyleTag(NpadStyleTag supported_styles); + /// Sets the connected status to true void Connect(); @@ -310,6 +317,12 @@ private: /// Set the params for TAS devices void LoadTASParams(); + /** + * Checks the current controller type against the supported_style_tag + * @return true if the controller is supported + */ + bool IsControllerSupported() const; + /** * Updates the button status of the controller * @param callback A CallbackStatus containing the button status @@ -354,6 +367,7 @@ private: NpadIdType npad_id_type; NpadStyleIndex npad_type{NpadStyleIndex::None}; + NpadStyleTag supported_style_tag{NpadStyleSet::All}; bool is_connected{false}; bool is_configuring{false}; f32 motion_sensitivity{0.01f}; diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index 946adde00..0c3eb5a62 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -108,6 +108,16 @@ const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t inde void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) { supported_style_tag.raw = style_tag.raw; + player_1->SetSupportedNpadStyleTag(supported_style_tag); + player_2->SetSupportedNpadStyleTag(supported_style_tag); + player_3->SetSupportedNpadStyleTag(supported_style_tag); + player_4->SetSupportedNpadStyleTag(supported_style_tag); + player_5->SetSupportedNpadStyleTag(supported_style_tag); + player_6->SetSupportedNpadStyleTag(supported_style_tag); + player_7->SetSupportedNpadStyleTag(supported_style_tag); + player_8->SetSupportedNpadStyleTag(supported_style_tag); + other->SetSupportedNpadStyleTag(supported_style_tag); + handheld->SetSupportedNpadStyleTag(supported_style_tag); } NpadStyleTag HIDCore::GetSupportedStyleTag() const { diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 140a0e962..2fb0f7e19 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -73,7 +73,7 @@ private: std::unique_ptr handheld; std::unique_ptr console; std::unique_ptr devices; - NpadStyleTag supported_style_tag; + NpadStyleTag supported_style_tag{NpadStyleSet::All}; }; } // namespace Core::HID diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 780659b86..7c12f01fc 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -256,6 +256,8 @@ enum class NpadStyleSet : u32 { Lager = 1U << 11, SystemExt = 1U << 29, System = 1U << 30, + + All = 0xFFFFFFFFU, }; static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 6916930f7..ae56f10cf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -126,8 +126,11 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, } void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { - LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); auto& controller = GetControllerFromNpadIdType(npad_id); + if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) { + return; + } + LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); const auto controller_type = controller.device->GetNpadStyleIndex(); auto& shared_memory = controller.shared_memory_entry; if (controller_type == Core::HID::NpadStyleIndex::None) { @@ -255,19 +258,7 @@ void Controller_NPad::OnInit() { if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) { // We want to support all controllers - Core::HID::NpadStyleTag style{}; - style.handheld.Assign(1); - style.joycon_left.Assign(1); - style.joycon_right.Assign(1); - style.joycon_dual.Assign(1); - style.fullkey.Assign(1); - style.gamecube.Assign(1); - style.palma.Assign(1); - style.lark.Assign(1); - style.lucia.Assign(1); - style.lagoon.Assign(1); - style.lager.Assign(1); - hid_core.SetSupportedStyleTag(style); + hid_core.SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); } supported_npad_id_types.resize(npad_id_list.size()); @@ -1072,13 +1063,18 @@ bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; const auto type_index_1 = controller_1->GetNpadStyleIndex(); const auto type_index_2 = controller_2->GetNpadStyleIndex(); + const auto is_connected_1 = controller_1->IsConnected(); + const auto is_connected_2 = controller_2->IsConnected(); - if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) { + if (!IsControllerSupported(type_index_1) && is_connected_1) { + return false; + } + if (!IsControllerSupported(type_index_2) && is_connected_2) { return false; } - AddNewControllerAt(type_index_2, npad_id_1); - AddNewControllerAt(type_index_1, npad_id_2); + UpdateControllerAt(type_index_2, npad_id_1, is_connected_2); + UpdateControllerAt(type_index_1, npad_id_2, is_connected_1); return true; } -- cgit v1.2.3 From 7347cdb65150e6a8250a619020483ab6ffcf2dbb Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 5 Dec 2021 13:57:48 -0600 Subject: core/hid: Add missing controller type --- src/core/hid/emulated_controller.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 720706794..fbb19f230 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -882,6 +882,8 @@ bool EmulatedController::IsControllerSupported() const { switch (npad_type) { case NpadStyleIndex::ProController: return supported_style_tag.fullkey; + case NpadStyleIndex::Handheld: + return supported_style_tag.handheld; case NpadStyleIndex::JoyconDual: return supported_style_tag.joycon_dual; case NpadStyleIndex::JoyconLeft: -- cgit v1.2.3 From 8aef8f39d86affd8fcc9a812d3d597f8eaee90b8 Mon Sep 17 00:00:00 2001 From: itsmeft24 Date: Sun, 5 Dec 2021 15:04:08 -0500 Subject: kernel: svc: Implement Map/UnmapProcessMemory and Create/ControlCodeMemory Used by Skyline modding framework --- src/core/hle/kernel/init/init_slab_setup.cpp | 2 + src/core/hle/kernel/k_class_token.cpp | 5 +- src/core/hle/kernel/k_code_memory.cpp | 159 ++++++++++++++++++++ src/core/hle/kernel/k_code_memory.h | 76 ++++++++++ src/core/hle/kernel/k_memory_block.h | 20 +++ src/core/hle/kernel/k_page_linked_list.h | 4 + src/core/hle/kernel/k_page_table.cpp | 124 +++++++++++++++- src/core/hle/kernel/k_page_table.h | 8 + src/core/hle/kernel/kernel.h | 4 + src/core/hle/kernel/svc.cpp | 214 ++++++++++++++++++++++++++- src/core/hle/kernel/svc_wrap.h | 27 ++++ 11 files changed, 636 insertions(+), 7 deletions(-) create mode 100644 src/core/hle/kernel/k_code_memory.cpp create mode 100644 src/core/hle/kernel/k_code_memory.h (limited to 'src/core') diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index 8ff0f695d..36fc0944a 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -9,6 +9,7 @@ #include "core/core.h" #include "core/hardware_properties.h" #include "core/hle/kernel/init/init_slab_setup.h" +#include "core/hle/kernel/k_code_memory.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_manager.h" @@ -32,6 +33,7 @@ namespace Kernel::Init { HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ + HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \ HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp index 0be0027be..21e2fe494 100644 --- a/src/core/hle/kernel/k_class_token.cpp +++ b/src/core/hle/kernel/k_class_token.cpp @@ -6,6 +6,7 @@ #include "core/hle/kernel/k_class_token.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_code_memory.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_process.h" @@ -48,7 +49,7 @@ static_assert(ClassToken == 0b10001001'00000000); static_assert(ClassToken == 0b10010001'00000000); // static_assert(ClassToken == 0b01100001'00000000); // static_assert(ClassToken == 0b10100001'00000000); -// static_assert(ClassToken == 0b11000001'00000000); +static_assert(ClassToken == 0b11000001'00000000); // Ensure that the token hierarchy is correct. @@ -79,7 +80,7 @@ static_assert(ClassToken == ((0b10001001 << 8) | ClassToken == ((0b10010001 << 8) | ClassToken)); // static_assert(ClassToken == ((0b01100001 << 8) | ClassToken)); // static_assert(ClassToken == ((0b10100001 << 8) | ClassToken)); -// static_assert(ClassToken == ((0b11000001 << 8) | ClassToken)); +static_assert(ClassToken == ((0b11000001 << 8) | ClassToken)); // Ensure that the token hierarchy reflects the class hierarchy. diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp new file mode 100644 index 000000000..926d1c076 --- /dev/null +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -0,0 +1,159 @@ +#include "core/core.h" +#include "core/core_timing.h" +#include "core/hle/kernel/k_client_port.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_code_memory.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_memory_block.h" +#include "core/hle/kernel/k_memory_layout.h" +#include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/kernel/k_resource_limit.h" +#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_scoped_resource_reservation.h" +#include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/kernel/k_writable_event.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" +#include "core/hle/kernel/svc.h" +#include "core/hle/kernel/svc_results.h" +#include "core/hle/kernel/svc_types.h" +#include "core/hle/kernel/svc_wrap.h" +#include "core/hle/lock.h" +#include "core/hle/result.h" +#include "core/memory.h" +#include "core/reporter.h" +namespace Kernel { + +KCodeMemory::KCodeMemory(KernelCore& kernel_) + : KAutoObjectWithSlabHeapAndContainer{kernel_}, m_lock(kernel_) {} + +ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) { + // Set members. + m_owner = kernel.CurrentProcess(); + + // Get the owner page table. + auto& page_table = m_owner->PageTable(); + + // Construct the page group. + KMemoryInfo kBlockInfo = page_table.QueryInfo(addr); + m_page_group = KPageLinkedList(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages()); + + // Lock the memory. + R_TRY(page_table.LockForCodeMemory(addr, size)) + + // Clear the memory. + for (const auto& block : m_page_group.Nodes()) { + std::memset(device_memory.GetPointer(block.GetAddress()), 0xFF, block.GetSize()); + } + + // Set remaining tracking members. + m_address = addr; + m_is_initialized = true; + m_is_owner_mapped = false; + m_is_mapped = false; + + // We succeeded. + return ResultSuccess; +} + +void KCodeMemory::Finalize() { + // Unlock. + if (!m_is_mapped && !m_is_owner_mapped) { + const size_t size = m_page_group.GetNumPages() * PageSize; + m_owner->PageTable().UnlockForCodeMemory(m_address, size); + } +} + +ResultCode KCodeMemory::Map(VAddr address, size_t size) { + // Validate the size. + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + + // Lock ourselves. + KScopedLightLock lk(m_lock); + + // Ensure we're not already mapped. + R_UNLESS(!m_is_mapped, ResultInvalidState); + + // Map the memory. + R_TRY(kernel.CurrentProcess()->PageTable().MapPages( + address, m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); + + // Mark ourselves as mapped. + m_is_mapped = true; + + return ResultSuccess; +} + +ResultCode KCodeMemory::Unmap(VAddr address, size_t size) { + // Validate the size. + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + + // Lock ourselves. + KScopedLightLock lk(m_lock); + + // Unmap the memory. + R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, m_page_group, + KMemoryState::CodeOut)); + + // Mark ourselves as unmapped. + m_is_mapped = false; + + return ResultSuccess; +} + +ResultCode KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) { + // Validate the size. + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + + // Lock ourselves. + KScopedLightLock lk(m_lock); + + // Ensure we're not already mapped. + R_UNLESS(!m_is_owner_mapped, ResultInvalidState); + + // Convert the memory permission. + KMemoryPermission k_perm{}; + switch (perm) { + case Svc::MemoryPermission::Read: + k_perm = KMemoryPermission::UserRead; + break; + case Svc::MemoryPermission::ReadExecute: + k_perm = KMemoryPermission::UserReadExecute; + break; + default: + break; + } + + // Map the memory. + R_TRY( + m_owner->PageTable().MapPages(address, m_page_group, KMemoryState::GeneratedCode, k_perm)); + + // Mark ourselves as mapped. + m_is_owner_mapped = true; + + return ResultSuccess; +} + +ResultCode KCodeMemory::UnmapFromOwner(VAddr address, size_t size) { + // Validate the size. + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + + // Lock ourselves. + KScopedLightLock lk(m_lock); + + // Unmap the memory. + R_TRY(m_owner->PageTable().UnmapPages(address, m_page_group, KMemoryState::GeneratedCode)); + + // Mark ourselves as unmapped. + m_is_owner_mapped = false; + + return ResultSuccess; +} + +} // namespace Kernel \ No newline at end of file diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h new file mode 100644 index 000000000..a7f7d749b --- /dev/null +++ b/src/core/hle/kernel/k_code_memory.h @@ -0,0 +1,76 @@ +#pragma once + +#include "core/core.h" +#include "core/core_timing.h" +#include "core/hle/kernel/k_client_port.h" +#include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_memory_block.h" +#include "core/hle/kernel/k_memory_layout.h" +#include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_readable_event.h" +#include "core/hle/kernel/k_resource_limit.h" +#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_scoped_resource_reservation.h" +#include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/kernel/k_writable_event.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" +#include "core/hle/kernel/svc.h" +#include "core/hle/kernel/svc_results.h" +#include "core/hle/kernel/svc_types.h" +#include "core/hle/kernel/svc_wrap.h" +#include "core/hle/lock.h" +#include "core/hle/result.h" +#include "core/memory.h" +#include "core/reporter.h" + +namespace Kernel { + +enum class CodeMemoryOperation : u32 { Map = 0, MapToOwner = 1, Unmap = 2, UnmapFromOwner = 3 }; + +class KCodeMemory final + : public KAutoObjectWithSlabHeapAndContainer { + KERNEL_AUTOOBJECT_TRAITS(KCodeMemory, KAutoObject); + +private: + KPageLinkedList m_page_group; + KProcess* m_owner; + VAddr m_address; + KLightLock m_lock; + bool m_is_initialized; + bool m_is_owner_mapped; + bool m_is_mapped; + +public: + explicit KCodeMemory(KernelCore& kernel_); + + ResultCode Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size); + void Finalize(); + + ResultCode Map(VAddr address, size_t size); + ResultCode Unmap(VAddr address, size_t size); + ResultCode MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm); + ResultCode UnmapFromOwner(VAddr address, size_t size); + + bool IsInitialized() const { + return m_is_initialized; + } + static void PostDestroy([[maybe_unused]] uintptr_t arg) {} + + KProcess* GetOwner() const { + return m_owner; + } + VAddr GetSourceAddress() { + return m_address; + } + size_t GetSize() const { + return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0; + } +}; +} // namespace Kernel \ No newline at end of file diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index a7fdb5fb8..fd491146f 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h @@ -131,6 +131,26 @@ enum class KMemoryPermission : u8 { UserMask = static_cast(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write | Svc::MemoryPermission::Execute), + + KernelShift = 3, + + KernelRead = Read << KernelShift, + KernelWrite = Write << KernelShift, + KernelExecute = Execute << KernelShift, + + NotMapped = (1 << (2 * KernelShift)), + + KernelReadWrite = KernelRead | KernelWrite, + KernelReadExecute = KernelRead | KernelExecute, + + UserRead = Read | KernelRead, + UserWrite = Write | KernelWrite, + UserExecute = Execute, + + UserReadWrite = UserRead | UserWrite, + UserReadExecute = UserRead | UserExecute, + + IpcLockChangeMask = NotMapped | UserReadWrite }; DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission); diff --git a/src/core/hle/kernel/k_page_linked_list.h b/src/core/hle/kernel/k_page_linked_list.h index 3362fb236..0e2ae582a 100644 --- a/src/core/hle/kernel/k_page_linked_list.h +++ b/src/core/hle/kernel/k_page_linked_list.h @@ -27,6 +27,10 @@ public: return num_pages; } + constexpr std::size_t GetSize() const { + return GetNumPages() * PageSize; + } + private: u64 addr{}; std::size_t num_pages{}; diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 9bda5c5b2..47f529fcd 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp @@ -368,6 +368,33 @@ ResultCode KPageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, st return ResultSuccess; } +ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, + KPageTable& src_page_table, VAddr src_addr) { + std::lock_guard lock{page_table_lock}; + + const std::size_t num_pages{size / PageSize}; + + // Check that the memory is mapped in the destination process. + size_t num_allocator_blocks; + R_TRY(CheckMemoryState(&num_allocator_blocks, dst_addr, size, KMemoryState::All, + KMemoryState::SharedCode, KMemoryPermission::UserReadWrite, + KMemoryPermission::UserReadWrite, KMemoryAttribute::All, + KMemoryAttribute::None)); + + // Check that the memory is mapped in the source process. + R_TRY(src_page_table.CheckMemoryState(src_addr, size, KMemoryState::FlagCanMapProcess, + KMemoryState::FlagCanMapProcess, KMemoryPermission::None, + KMemoryPermission::None, KMemoryAttribute::All, + KMemoryAttribute::None)); + + CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); + + // Apply the memory block update. + block_manager->Update(dst_addr, num_pages, KMemoryState::Free, KMemoryPermission::None, + KMemoryAttribute::None); + + return ResultSuccess; +} void KPageTable::MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end) { auto node{page_linked_list.Nodes().begin()}; PAddr map_addr{node->GetAddress()}; @@ -942,6 +969,62 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) return ResultSuccess; } +ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { + + std::lock_guard lock{page_table_lock}; + + KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite; + + KMemoryPermission old_perm{}; + + if (const ResultCode result{CheckMemoryState( + nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, + KMemoryState::FlagCanCodeMemory, KMemoryPermission::Mask, + KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)}; + result.IsError()) { + return result; + } + + new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm; + + block_manager->UpdateLock( + addr, size / PageSize, + [](KMemoryBlockManager::iterator block, KMemoryPermission permission) { + block->ShareToDevice(permission); + }, + new_perm); + + return ResultSuccess; +} + +ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) { + + std::lock_guard lock{page_table_lock}; + + KMemoryPermission new_perm = KMemoryPermission::UserReadWrite; + + KMemoryPermission old_perm{}; + + if (const ResultCode result{CheckMemoryState( + nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, + KMemoryState::FlagCanCodeMemory, KMemoryPermission::None, KMemoryPermission::None, + KMemoryAttribute::All, KMemoryAttribute::Locked)}; + result.IsError()) { + return result; + } + + new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm; + + block_manager->UpdateLock( + addr, size / PageSize, + [](KMemoryBlockManager::iterator block, KMemoryPermission permission) { + block->UnshareToDevice(permission); + }, + new_perm); + + return ResultSuccess; +} + ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) { block_manager = std::make_unique(start, end); @@ -1231,4 +1314,43 @@ ResultCode KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermissi return ResultSuccess; } -} // namespace Kernel +ResultCode KPageTable::CheckMemoryState(size_t* out_blocks_needed, VAddr addr, size_t size, + KMemoryState state_mask, KMemoryState state, + KMemoryPermission perm_mask, KMemoryPermission perm, + KMemoryAttribute attr_mask, KMemoryAttribute attr) const { + + // Get information about the first block. + const VAddr last_addr = addr + size - 1; + KMemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)}; + KMemoryInfo info = it->GetMemoryInfo(); + + // If the start address isn't aligned, we need a block. + const size_t blocks_for_start_align = + (Common::AlignDown(addr, PageSize) != info.GetAddress()) ? 1 : 0; + + while (true) { + // Validate against the provided masks. + R_TRY(CheckMemoryState(info, state_mask, state, perm_mask, perm, attr_mask, attr)); + + // Break once we're done. + if (last_addr <= info.GetLastAddress()) { + break; + } + + // Advance our iterator. + it++; + info = it->GetMemoryInfo(); + } + + // If the end address isn't aligned, we need a block. + const size_t blocks_for_end_align = + (Common::AlignUp(addr + size, PageSize) != info.GetEndAddress()) ? 1 : 0; + + if (out_blocks_needed != nullptr) { + *out_blocks_needed = blocks_for_start_align + blocks_for_end_align; + } + + return ResultSuccess; +} + +} // namespace Kernel \ No newline at end of file diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index b7ec38f06..d784aa67e 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h @@ -33,6 +33,8 @@ public: KMemoryPermission perm); ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); + ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table, + VAddr src_addr); ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size); ResultCode UnmapMemory(VAddr addr, std::size_t size); @@ -55,6 +57,8 @@ public: KMemoryPermission perm, PAddr map_addr = 0); ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size); ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size); + ResultCode LockForCodeMemory(VAddr addr, std::size_t size); + ResultCode UnlockForCodeMemory(VAddr addr, std::size_t size); Common::PageTable& PageTableImpl() { return page_table_impl; @@ -115,6 +119,10 @@ private: return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr); } + ResultCode CheckMemoryState(size_t* out_blocks_needed, VAddr addr, size_t size, + KMemoryState state_mask, KMemoryState state, + KMemoryPermission perm_mask, KMemoryPermission perm, + KMemoryAttribute attr_mask, KMemoryAttribute attr) const; std::recursive_mutex page_table_lock; std::unique_ptr block_manager; diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d2ceae950..d847fd0c5 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -53,6 +53,7 @@ class KSharedMemoryInfo; class KThread; class KTransferMemory; class KWritableEvent; +class KCodeMemory; class PhysicalCore; class ServiceThread; class Synchronization; @@ -326,6 +327,8 @@ public: return slab_heap_container->transfer_memory; } else if constexpr (std::is_same_v) { return slab_heap_container->writeable_event; + } else if constexpr (std::is_same_v) { + return slab_heap_container->code_memory; } } @@ -377,6 +380,7 @@ private: KSlabHeap thread; KSlabHeap transfer_memory; KSlabHeap writeable_event; + KSlabHeap code_memory; }; std::unique_ptr slab_heap_container; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f0cd8471e..b37db918e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -18,6 +18,7 @@ #include "core/core_timing.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_code_memory.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_memory_block.h" @@ -1197,6 +1198,22 @@ constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { } } +constexpr bool IsValidMapCodeMemoryPermission(Svc::MemoryPermission perm) { + return perm == Svc::MemoryPermission::ReadWrite; +} + +constexpr bool IsValidMapToOwnerCodeMemoryPermission(Svc::MemoryPermission perm) { + return perm == Svc::MemoryPermission::Read || perm == Svc::MemoryPermission::ReadExecute; +} + +constexpr bool IsValidUnmapCodeMemoryPermission(Svc::MemoryPermission perm) { + return perm == Svc::MemoryPermission::None; +} + +constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(Svc::MemoryPermission perm) { + return perm == Svc::MemoryPermission::None; +} + } // Anonymous namespace static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, @@ -1306,6 +1323,195 @@ static ResultCode SetProcessMemoryPermission(Core::System& system, Handle proces return page_table.SetProcessMemoryPermission(address, size, ConvertToKMemoryPermission(perm)); } +static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, + VAddr src_address, u64 size) { + LOG_TRACE(Kernel_SVC, + "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", + dst_address, process_handle, src_address, size); + + // Validate the address/size. + R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory); + R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory); + + // Get the processes. + KProcess* dst_process = system.CurrentProcess(); + KScopedAutoObject src_process = + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(process_handle); + R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); + + // Get the page tables. + auto& dst_pt = dst_process->PageTable(); + auto& src_pt = src_process->PageTable(); + + // Validate that the mapping is in range. + R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); + R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode), + ResultInvalidMemoryRegion); + + // Create a new page group. + KMemoryInfo kBlockInfo = dst_pt.QueryInfo(dst_address); + KPageLinkedList pg(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages()); + + // Map the group. + R_TRY(dst_pt.MapPages(dst_address, pg, KMemoryState::SharedCode, + KMemoryPermission::UserReadWrite)); + + return ResultSuccess; +} + +static ResultCode UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, + VAddr src_address, u64 size) { + LOG_TRACE(Kernel_SVC, + "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", + dst_address, process_handle, src_address, size); + + // Validate the address/size. + R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory); + R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory); + + // Get the processes. + KProcess* dst_process = system.CurrentProcess(); + KScopedAutoObject src_process = + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(process_handle); + R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); + + // Get the page tables. + auto& dst_pt = dst_process->PageTable(); + auto& src_pt = src_process->PageTable(); + + // Validate that the mapping is in range. + R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); + R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode), + ResultInvalidMemoryRegion); + + // Unmap the memory. + R_TRY(dst_pt.UnmapProcessMemory(dst_address, size, src_pt, src_address)); + + return ResultSuccess; +} + +static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) { + LOG_TRACE(Kernel_SVC, "called, handle_out=0x{:X}, address=0x{:X}, size=0x{:X}", + static_cast(out), address, size); + // Get kernel instance. + auto& kernel = system.Kernel(); + + // Validate address / size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); + + // Create the code memory. + + KCodeMemory* code_mem = KCodeMemory::Create(kernel); + R_UNLESS(code_mem != nullptr, ResultOutOfResource); + + // Verify that the region is in range. + R_UNLESS(system.CurrentProcess()->PageTable().Contains(address, size), + ResultInvalidCurrentMemory); + + // Initialize the code memory. + R_TRY(code_mem->Initialize(system.DeviceMemory(), address, size)); + + // Register the code memory. + KCodeMemory::Register(kernel, code_mem); + + // Add the code memory to the handle table. + R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, code_mem)); + + code_mem->Close(); + + return ResultSuccess; +} + +static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation, + VAddr address, size_t size, Svc::MemoryPermission perm) { + + LOG_TRACE(Kernel_SVC, + "called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, " + "permission=0x{:X}", + code_memory_handle, operation, address, size, perm); + + // Validate the address / size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); + + // Get the code memory from its handle. + KScopedAutoObject code_mem = + system.CurrentProcess()->GetHandleTable().GetObject(code_memory_handle); + R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle); + + // NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process. + // This enables homebrew usage of these SVCs for JIT. + + // Perform the operation. + switch (static_cast(operation)) { + case CodeMemoryOperation::Map: { + // Check that the region is in range. + R_UNLESS( + system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut), + ResultInvalidMemoryRegion); + + // Check the memory permission. + R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); + + // Map the memory. + R_TRY(code_mem->Map(address, size)); + } break; + case CodeMemoryOperation::Unmap: { + // Check that the region is in range. + R_UNLESS( + system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut), + ResultInvalidMemoryRegion); + + // Check the memory permission. + R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); + + // Unmap the memory. + R_TRY(code_mem->Unmap(address, size)); + } break; + case CodeMemoryOperation::MapToOwner: { + // Check that the region is in range. + R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, + KMemoryState::GeneratedCode), + ResultInvalidMemoryRegion); + + // Check the memory permission. + R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); + + // Map the memory to its owner. + R_TRY(code_mem->MapToOwner(address, size, perm)); + } break; + case CodeMemoryOperation::UnmapFromOwner: { + // Check that the region is in range. + R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, + KMemoryState::GeneratedCode), + ResultInvalidMemoryRegion); + + // Check the memory permission. + R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); + + // Unmap the memory from its owner. + R_TRY(code_mem->UnmapFromOwner(address, size)); + } break; + default: + return ResultInvalidEnumValue; + } + + return ResultSuccess; +} + static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address, Handle process_handle, VAddr address) { @@ -2600,8 +2806,8 @@ static const FunctionDef SVC_Table_64[] = { {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, {0x49, nullptr, "UnmapPhysicalMemoryUnsafe"}, {0x4A, nullptr, "SetUnsafeLimit"}, - {0x4B, nullptr, "CreateCodeMemory"}, - {0x4C, nullptr, "ControlCodeMemory"}, + {0x4B, SvcWrap64, "CreateCodeMemory"}, + {0x4C, SvcWrap64, "ControlCodeMemory"}, {0x4D, nullptr, "SleepSystem"}, {0x4E, nullptr, "ReadWriteRegister"}, {0x4F, nullptr, "SetProcessActivity"}, @@ -2641,8 +2847,8 @@ static const FunctionDef SVC_Table_64[] = { {0x71, nullptr, "ManageNamedPort"}, {0x72, nullptr, "ConnectToPort"}, {0x73, SvcWrap64, "SetProcessMemoryPermission"}, - {0x74, nullptr, "MapProcessMemory"}, - {0x75, nullptr, "UnmapProcessMemory"}, + {0x74, SvcWrap64, "MapProcessMemory"}, + {0x75, SvcWrap64, "UnmapProcessMemory"}, {0x76, SvcWrap64, "QueryProcessMemory"}, {0x77, SvcWrap64, "MapProcessCodeMemory"}, {0x78, SvcWrap64, "UnmapProcessCodeMemory"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 6e62e656f..86255fe6d 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -73,6 +73,23 @@ void SvcWrap64(Core::System& system) { .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; @@ -301,6 +318,16 @@ void SvcWrap64(Core::System& system) { 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; -- cgit v1.2.3 From 36350d3f78b331ef232cc8d935561670f2cdf949 Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Sun, 5 Dec 2021 15:56:44 -0500 Subject: Add KCodeMemory to CMakeLists.txt --- src/core/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index eee8e2ccd..4a9aadd6d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -179,6 +179,8 @@ add_library(core STATIC hle/kernel/k_client_port.h hle/kernel/k_client_session.cpp hle/kernel/k_client_session.h + hle/kernel/k_code_memory.cpp + hle/kernel/k_code_memory.h hle/kernel/k_condition_variable.cpp hle/kernel/k_condition_variable.h hle/kernel/k_event.cpp -- cgit v1.2.3 From 41aec2773f382ac4ff27daee5401b78f7669190d Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 5 Dec 2021 16:18:53 -0500 Subject: general: Add missing copyright notices --- src/core/hle/service/nvdrv/nvdata.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 3294bc0e7..5ab221fc1 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -1,3 +1,7 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #pragma once #include -- cgit v1.2.3 From b7d80c127f3b4c919887aaed391f88c033f3e7a2 Mon Sep 17 00:00:00 2001 From: itsmeft24 Date: Sun, 5 Dec 2021 16:49:52 -0500 Subject: Add copyright notice --- src/core/hle/kernel/k_code_memory.cpp | 4 ++++ src/core/hle/kernel/k_code_memory.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index 926d1c076..2e436fb4a 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -1,3 +1,7 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/k_client_port.h" diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index a7f7d749b..3961105a6 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -1,3 +1,7 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #pragma once #include "core/core.h" -- cgit v1.2.3 From d6ae9c68f80792cf11f13ca2c81ac34ddf01dafa Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 5 Dec 2021 16:17:52 -0600 Subject: service/hid: Implement SetNpadJoyAssignmentMode --- src/core/hid/hid_core.cpp | 10 ++ src/core/hid/hid_core.h | 3 + src/core/hle/service/hid/controllers/npad.cpp | 165 ++++++++++++++++++++++---- src/core/hle/service/hid/controllers/npad.h | 8 +- src/core/hle/service/hid/hid.cpp | 26 ++-- 5 files changed, 174 insertions(+), 38 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index 0c3eb5a62..a1c3bbb57 100644 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -145,6 +145,16 @@ NpadIdType HIDCore::GetFirstNpadId() const { return NpadIdType::Player1; } +NpadIdType HIDCore::GetFirstDisconnectedNpadId() const { + for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) { + const auto* const controller = GetEmulatedControllerByIndex(player_index); + if (!controller->IsConnected()) { + return controller->GetNpadIdType(); + } + } + return NpadIdType::Player1; +} + void HIDCore::EnableAllControllerConfiguration() { player_1->EnableConfiguration(); player_2->EnableConfiguration(); diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 2fb0f7e19..837f7de49 100644 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -45,6 +45,9 @@ public: /// Returns the first connected npad id NpadIdType GetFirstNpadId() const; + /// Returns the first disconnected npad id + NpadIdType GetFirstDisconnectedNpadId() const; + /// Sets all emulated controllers into configuring mode. void EnableAllControllerConfiguration(); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index ae56f10cf..2705e9dcb 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -110,7 +110,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, UpdateControllerAt(npad_type, npad_id, is_connected); break; case Core::HID::ControllerTriggerType::Battery: { - if (!controller.is_connected) { + if (!controller.device->IsConnected()) { return; } auto& shared_memory = controller.shared_memory_entry; @@ -150,7 +150,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory.system_properties.is_vertical.Assign(1); shared_memory.system_properties.use_plus.Assign(1); shared_memory.system_properties.use_minus.Assign(1); - shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; break; case Core::HID::NpadStyleIndex::Handheld: @@ -166,21 +165,30 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { break; case Core::HID::NpadStyleIndex::JoyconDual: shared_memory.style_tag.joycon_dual.Assign(1); - shared_memory.device_type.joycon_left.Assign(1); - shared_memory.device_type.joycon_right.Assign(1); - shared_memory.system_properties.is_vertical.Assign(1); - shared_memory.system_properties.use_plus.Assign(1); - shared_memory.system_properties.use_minus.Assign(1); + if (controller.is_dual_left_connected) { + shared_memory.device_type.joycon_left.Assign(1); + shared_memory.system_properties.use_minus.Assign(1); + } + if (controller.is_dual_right_connected) { + shared_memory.device_type.joycon_right.Assign(1); + shared_memory.system_properties.use_plus.Assign(1); + } shared_memory.system_properties.use_directional_buttons.Assign(1); + shared_memory.system_properties.is_vertical.Assign(1); shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; + if (controller.is_dual_left_connected && controller.is_dual_right_connected) { + shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; + } else if (controller.is_dual_left_connected) { + shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly; + } else { + shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly; + } break; case Core::HID::NpadStyleIndex::JoyconLeft: shared_memory.style_tag.joycon_left.Assign(1); shared_memory.device_type.joycon_left.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.use_minus.Assign(1); - shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; break; case Core::HID::NpadStyleIndex::JoyconRight: @@ -188,7 +196,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory.device_type.joycon_right.Assign(1); shared_memory.system_properties.is_horizontal.Assign(1); shared_memory.system_properties.use_plus.Assign(1); - shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; break; case Core::HID::NpadStyleIndex::GameCube: @@ -200,7 +207,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { case Core::HID::NpadStyleIndex::Pokeball: shared_memory.style_tag.palma.Assign(1); shared_memory.device_type.palma.Assign(1); - shared_memory.assignment_mode = NpadJoyAssignmentMode::Single; break; case Core::HID::NpadStyleIndex::NES: shared_memory.style_tag.lark.Assign(1); @@ -443,11 +449,15 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* case Core::HID::NpadStyleIndex::JoyconDual: pad_state.connection_status.raw = 0; pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_left_connected.Assign(1); - pad_state.connection_status.is_right_connected.Assign(1); + if (controller.is_dual_left_connected) { + pad_state.connection_status.is_left_connected.Assign(1); + libnx_state.connection_status.is_left_connected.Assign(1); + } + if (controller.is_dual_right_connected) { + pad_state.connection_status.is_right_connected.Assign(1); + libnx_state.connection_status.is_right_connected.Assign(1); + } - libnx_state.connection_status.is_left_connected.Assign(1); - libnx_state.connection_status.is_right_connected.Assign(1); pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; npad.joy_dual_lifo.WriteNextEntry(pad_state); @@ -687,7 +697,7 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode return communication_mode; } -void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, +void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); @@ -698,6 +708,62 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, if (controller.shared_memory_entry.assignment_mode != assignment_mode) { controller.shared_memory_entry.assignment_mode = assignment_mode; } + + if (!controller.device->IsConnected()) { + return; + } + + if (assignment_mode == NpadJoyAssignmentMode::Dual) { + if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { + DisconnectNpad(npad_id); + controller.is_dual_left_connected = true; + controller.is_dual_right_connected = false; + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); + return; + } + if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { + DisconnectNpad(npad_id); + controller.is_dual_left_connected = false; + controller.is_dual_right_connected = true; + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); + return; + } + return; + } + + // This is for NpadJoyAssignmentMode::Single + + // Only JoyconDual get affected by this function + if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { + return; + } + + if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { + DisconnectNpad(npad_id); + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); + return; + } + if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { + DisconnectNpad(npad_id); + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); + return; + } + + // We have two controllers connected to the same npad_id we need to split them + const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId(); + auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); + DisconnectNpad(npad_id); + if (npad_device_type == NpadJoyDeviceType::Left) { + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); + controller_2.is_dual_left_connected = false; + controller_2.is_dual_right_connected = true; + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); + } else { + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); + controller_2.is_dual_left_connected = true; + controller_2.is_dual_right_connected = false; + UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); + } } bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, @@ -907,6 +973,7 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { } auto& shared_memory_entry = controller.shared_memory_entry; + // Don't reset shared_memory_entry.assignment_mode this value is persistent shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out shared_memory_entry.device_type.raw = 0; shared_memory_entry.system_properties.raw = 0; @@ -923,9 +990,10 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { .left = {}, .right = {}, }; - shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual; shared_memory_entry.applet_footer.type = AppletFooterUiType::None; + controller.is_dual_left_connected = true; + controller.is_dual_right_connected = true; controller.is_connected = false; controller.device->Disconnect(); SignalStyleSetChangedEvent(npad_id); @@ -1022,19 +1090,70 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, npad_id_2); return; } - auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; - auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; + auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); + auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); + const auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); + const auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); + bool merge_controllers = false; // If the controllers at both npad indices form a pair of left and right joycons, merge them. // Otherwise, do nothing. - if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && - controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) || - (controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && - controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) { + if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && + controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { + merge_controllers = true; + } + if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && + controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) { + merge_controllers = true; + } + if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && + controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight && + controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { + merge_controllers = true; + } + if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && + controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft && + !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { + merge_controllers = true; + } + if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && + controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && + controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { + merge_controllers = true; + } + if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && + controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && + !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { + merge_controllers = true; + } + if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && + controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && + controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected && + !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { + merge_controllers = true; + } + if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && + controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual && + !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected && + controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { + merge_controllers = true; + } + + if (merge_controllers) { // Disconnect the joycon at the second id and connect the dual joycon at the first index. DisconnectNpad(npad_id_2); + controller_1.is_dual_left_connected = true; + controller_1.is_dual_right_connected = true; AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); + return; } + LOG_WARNING(Service_HID, + "Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, " + "dual_1(left/right):{}/{}, dual_2(left/right):{}/{}", + npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(), + controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected, + controller_1.is_dual_right_connected, controller_2.is_dual_left_connected, + controller_2.is_dual_right_connected); } void Controller_NPad::StartLRAssignmentMode() { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index de5fa5a64..63281cb35 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -113,7 +113,8 @@ public: void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); NpadCommunicationMode GetNpadCommunicationMode() const; - void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode); + void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, + NpadJoyAssignmentMode assignment_mode); bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, const Core::HID::VibrationValue& vibration_value); @@ -464,7 +465,10 @@ private: std::array vibration{}; bool unintended_home_button_input_protection{}; bool is_connected{}; - Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; + + // Dual joycons can have only one side connected + bool is_dual_left_connected{true}; + bool is_dual_right_connected{true}; // Motion parameters bool sixaxis_at_rest{true}; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index b36689552..ea5b2680d 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -975,35 +975,35 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); + .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, + Controller_NPad::NpadJoyAssignmentMode::Single); - LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", - parameters.npad_id, parameters.applet_resource_user_id); + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, + parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { - // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault IPC::RequestParser rp{ctx}; struct Parameters { Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; - u64 npad_joy_device_type; + Controller_NPad::NpadJoyDeviceType npad_joy_device_type; }; static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); + .SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, + Controller_NPad::NpadJoyAssignmentMode::Single); - LOG_WARNING(Service_HID, - "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", - parameters.npad_id, parameters.applet_resource_user_id, - parameters.npad_joy_device_type); + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", + parameters.npad_id, parameters.applet_resource_user_id, + parameters.npad_joy_device_type); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -1021,10 +1021,10 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; applet_resource->GetController(HidController::NPad) - .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual); + .SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); - LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", - parameters.npad_id, parameters.applet_resource_user_id); + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, + parameters.applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); -- cgit v1.2.3 From 8254f238b9e71c0292bc6456afb92086113b12ac Mon Sep 17 00:00:00 2001 From: itsmeft24 Date: Sun, 5 Dec 2021 18:49:40 -0500 Subject: Remove unnecessary includes --- src/core/hle/kernel/k_code_memory.cpp | 31 +++++++------------------------ src/core/hle/kernel/k_code_memory.h | 32 ++++++-------------------------- 2 files changed, 13 insertions(+), 50 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index 2e436fb4a..9264faf4e 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -2,36 +2,19 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_client_port.h" -#include "core/hle/kernel/k_client_session.h" +#include "common/common_types.h" +#include "core/device_memory.h" +#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_code_memory.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_memory_block.h" -#include "core/hle/kernel/k_memory_layout.h" +#include "core/hle/kernel/k_page_linked_list.h" #include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_resource_limit.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_scoped_resource_reservation.h" -#include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/kernel/k_synchronization_object.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/kernel/k_writable_event.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/physical_core.h" -#include "core/hle/kernel/svc.h" -#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_types.h" -#include "core/hle/kernel/svc_wrap.h" -#include "core/hle/lock.h" +#include "core/hle/kernel/slab_helpers.h" #include "core/hle/result.h" -#include "core/memory.h" -#include "core/reporter.h" + namespace Kernel { KCodeMemory::KCodeMemory(KernelCore& kernel_) diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 3961105a6..da60ece67 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -4,35 +4,15 @@ #pragma once -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_client_port.h" -#include "core/hle/kernel/k_client_session.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_handle_table.h" -#include "core/hle/kernel/k_memory_block.h" -#include "core/hle/kernel/k_memory_layout.h" -#include "core/hle/kernel/k_page_table.h" +#include "common/common_types.h" +#include "core/device_memory.h" +#include "core/hle/kernel/k_auto_object.h" +#include "core/hle/kernel/k_light_lock.h" +#include "core/hle/kernel/k_page_linked_list.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_resource_limit.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_scoped_resource_reservation.h" -#include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/kernel/k_synchronization_object.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/kernel/k_writable_event.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/physical_core.h" -#include "core/hle/kernel/svc.h" -#include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/svc_types.h" -#include "core/hle/kernel/svc_wrap.h" -#include "core/hle/lock.h" +#include "core/hle/kernel/slab_helpers.h" #include "core/hle/result.h" -#include "core/memory.h" -#include "core/reporter.h" namespace Kernel { -- cgit v1.2.3 From 14c03b97483bb394e210972ed30f105b9994cd04 Mon Sep 17 00:00:00 2001 From: itsmeft24 Date: Sun, 5 Dec 2021 19:00:29 -0500 Subject: fix formatting --- src/core/hle/kernel/k_code_memory.cpp | 2 +- src/core/hle/kernel/k_code_memory.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index 9264faf4e..d69f7ffb7 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -11,8 +11,8 @@ #include "core/hle/kernel/k_page_linked_list.h" #include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/svc_types.h" #include "core/hle/kernel/slab_helpers.h" +#include "core/hle/kernel/svc_types.h" #include "core/hle/result.h" namespace Kernel { diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index da60ece67..9166d98b5 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -10,8 +10,8 @@ #include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_page_linked_list.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/svc_types.h" #include "core/hle/kernel/slab_helpers.h" +#include "core/hle/kernel/svc_types.h" #include "core/hle/result.h" namespace Kernel { -- cgit v1.2.3 From 29559930e95cfc8ed5ee523fd7f61c5309280ebf Mon Sep 17 00:00:00 2001 From: jam1garner <8260240+jam1garner@users.noreply.github.com> Date: Sun, 5 Dec 2021 23:07:50 -0500 Subject: loader: Support loading subsdk{8,9} --- src/core/loader/deconstructed_rom_directory.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 1b5aca65d..b47e3bf69 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -125,8 +125,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect } metadata.Print(); - const auto static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", - "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}; + const auto static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", + "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", + "subsdk8", "subsdk9", "sdk"}; // Use the NSO module loader to figure out the code layout std::size_t code_size{}; -- cgit v1.2.3 From 189741b521e569a7087deee9f92ac66ab4f6f154 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 5 Dec 2021 22:41:21 -0600 Subject: service/hid: Stub SetNpadCaptureButtonAssignment and ClearNpadCaptureButtonAssignment Used by ring fit adventure 1.2.0 --- src/core/hle/service/hid/hid.cpp | 35 +++++++++++++++++++++++++++++++++-- src/core/hle/service/hid/hid.h | 2 ++ 2 files changed, 35 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index b36689552..14f737d39 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -293,8 +293,8 @@ Hid::Hid(Core::System& system_) {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"}, - {135, nullptr, "SetNpadCaptureButtonAssignment"}, - {136, nullptr, "ClearNpadCaptureButtonAssignment"}, + {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"}, + {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"}, {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, {201, &Hid::SendVibrationValue, "SendVibrationValue"}, {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"}, @@ -1186,6 +1186,37 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void Hid::SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Core::HID::NpadStyleSet npad_styleset; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + Core::HID::NpadButton button; + }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw()}; + + LOG_WARNING(Service_HID, + "(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}", + parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void Hid::ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw()}; diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index ab0084118..d290df161 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -136,6 +136,8 @@ private: void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx); + void SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx); + void ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx); void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); void SendVibrationValue(Kernel::HLERequestContext& ctx); void GetActualVibrationValue(Kernel::HLERequestContext& ctx); -- cgit v1.2.3 From 32854a299223c7fff759bb779adda0022c632bd3 Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Mon, 6 Dec 2021 07:58:28 -0500 Subject: fix formatting Co-authored-by: Mai M. --- src/core/hle/kernel/k_code_memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 9166d98b5..91ffafa89 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -16,7 +16,7 @@ namespace Kernel { -enum class CodeMemoryOperation : u32 { Map = 0, MapToOwner = 1, Unmap = 2, UnmapFromOwner = 3 }; +enum class CodeMemoryOperation : u32 { Map = 0, MapToOwner = 1, Unmap = 2, UnmapFromOwner = 3, }; class KCodeMemory final : public KAutoObjectWithSlabHeapAndContainer { -- cgit v1.2.3 From 4bdacdedc1d4ccb633d7427999b552382f99863c Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Mon, 6 Dec 2021 10:37:09 -0500 Subject: fix formatting --- src/core/hle/kernel/k_page_table.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 47f529fcd..99982e5a3 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp @@ -970,7 +970,6 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) } ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { - std::lock_guard lock{page_table_lock}; KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite; @@ -998,7 +997,6 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { } ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) { - std::lock_guard lock{page_table_lock}; KMemoryPermission new_perm = KMemoryPermission::UserReadWrite; @@ -1318,7 +1316,6 @@ ResultCode KPageTable::CheckMemoryState(size_t* out_blocks_needed, VAddr addr, s KMemoryState state_mask, KMemoryState state, KMemoryPermission perm_mask, KMemoryPermission perm, KMemoryAttribute attr_mask, KMemoryAttribute attr) const { - // Get information about the first block. const VAddr last_addr = addr + size - 1; KMemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)}; @@ -1353,4 +1350,4 @@ ResultCode KPageTable::CheckMemoryState(size_t* out_blocks_needed, VAddr addr, s return ResultSuccess; } -} // namespace Kernel \ No newline at end of file +} // namespace Kernel -- cgit v1.2.3 From e10903cab928e3cbc9d554a6c388434fbaa2f1db Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Mon, 6 Dec 2021 10:37:13 -0500 Subject: move private members below public members --- src/core/hle/kernel/k_code_memory.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 91ffafa89..7408b775d 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -22,15 +22,6 @@ class KCodeMemory final : public KAutoObjectWithSlabHeapAndContainer { KERNEL_AUTOOBJECT_TRAITS(KCodeMemory, KAutoObject); -private: - KPageLinkedList m_page_group; - KProcess* m_owner; - VAddr m_address; - KLightLock m_lock; - bool m_is_initialized; - bool m_is_owner_mapped; - bool m_is_mapped; - public: explicit KCodeMemory(KernelCore& kernel_); @@ -56,5 +47,15 @@ public: size_t GetSize() const { return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0; } + +private: + KPageLinkedList m_page_group; + KProcess* m_owner; + VAddr m_address; + KLightLock m_lock; + bool m_is_initialized; + bool m_is_owner_mapped; + bool m_is_mapped; }; -} // namespace Kernel \ No newline at end of file + +} // namespace Kernel -- cgit v1.2.3 From 8ed2748820d6b991ae2da4e97c98a2f8637fc331 Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Mon, 6 Dec 2021 11:02:33 -0500 Subject: fix formatting --- src/core/hle/kernel/k_code_memory.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 7408b775d..e8e83a0e5 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -16,7 +16,12 @@ namespace Kernel { -enum class CodeMemoryOperation : u32 { Map = 0, MapToOwner = 1, Unmap = 2, UnmapFromOwner = 3, }; +enum class CodeMemoryOperation : u32 { + Map = 0, + MapToOwner = 1, + Unmap = 2, + UnmapFromOwner = 3, +}; class KCodeMemory final : public KAutoObjectWithSlabHeapAndContainer { -- cgit v1.2.3 From ac1bfe228f688bb8eef38bdaf26011008891afdf Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 5 Dec 2021 22:55:23 -0600 Subject: service/notif: Add notif:a and stub ListAlarmSettings,Initialize Used by ring fit adventure 1.2.0 --- src/core/CMakeLists.txt | 2 ++ src/core/hle/service/glue/glue.cpp | 4 ++++ src/core/hle/service/glue/notif.cpp | 44 +++++++++++++++++++++++++++++++++++++ src/core/hle/service/glue/notif.h | 25 +++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 src/core/hle/service/glue/notif.cpp create mode 100644 src/core/hle/service/glue/notif.h (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index eee8e2ccd..721685bb7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -408,6 +408,8 @@ add_library(core STATIC hle/service/glue/glue.h hle/service/glue/glue_manager.cpp hle/service/glue/glue_manager.h + hle/service/glue/notif.cpp + hle/service/glue/notif.h hle/service/grc/grc.cpp hle/service/grc/grc.h hle/service/hid/hid.cpp diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp index a08dc9758..b24d469cf 100644 --- a/src/core/hle/service/glue/glue.cpp +++ b/src/core/hle/service/glue/glue.cpp @@ -8,6 +8,7 @@ #include "core/hle/service/glue/bgtc.h" #include "core/hle/service/glue/ectx.h" #include "core/hle/service/glue/glue.h" +#include "core/hle/service/glue/notif.h" namespace Service::Glue { @@ -24,6 +25,9 @@ void InstallInterfaces(Core::System& system) { // Error Context std::make_shared(system)->InstallAsService(system.ServiceManager()); + + // Notification Services for application + std::make_shared(system)->InstallAsService(system.ServiceManager()); } } // namespace Service::Glue diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp new file mode 100644 index 000000000..c559ec9df --- /dev/null +++ b/src/core/hle/service/glue/notif.cpp @@ -0,0 +1,44 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/glue/notif.h" + +namespace Service::Glue { + +NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} { + // clang-format off + static const FunctionInfo functions[] = { + {500, nullptr, "RegisterAlarmSetting"}, + {510, nullptr, "UpdateAlarmSetting"}, + {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"}, + {530, nullptr, "LoadApplicationParameter"}, + {540, nullptr, "DeleteAlarmSetting"}, + {1000, &NOTIF_A::Initialize, "Initialize"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +NOTIF_A::~NOTIF_A() = default; + +void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) { + // Returns an array of AlarmSetting + constexpr s32 alarm_count = 0; + + LOG_WARNING(Service_NOTIF, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(alarm_count); +} + +void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NOTIF, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/notif.h b/src/core/hle/service/glue/notif.h new file mode 100644 index 000000000..6ecf2015c --- /dev/null +++ b/src/core/hle/service/glue/notif.h @@ -0,0 +1,25 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Glue { + +class NOTIF_A final : public ServiceFramework { +public: + explicit NOTIF_A(Core::System& system_); + ~NOTIF_A() override; + +private: + void ListAlarmSettings(Kernel::HLERequestContext& ctx); + void Initialize(Kernel::HLERequestContext& ctx); +}; + +} // namespace Service::Glue -- cgit v1.2.3 From 669a2d2c67bd9a3267286bc0c2e6e3c1dc98c154 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 22:45:18 -0700 Subject: core: hle: kernel: Reflect non-emulated threads as core 3. --- src/core/core.cpp | 6 ------ src/core/core.h | 3 --- src/core/hle/kernel/k_address_arbiter.cpp | 4 ++-- src/core/hle/kernel/k_condition_variable.cpp | 2 +- src/core/hle/kernel/kernel.cpp | 8 ++++++++ src/core/hle/kernel/kernel.h | 3 +++ src/core/hle/kernel/svc.cpp | 5 +++-- 7 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/core') diff --git a/src/core/core.cpp b/src/core/core.cpp index 473ab9f81..aa96f709b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -521,12 +521,6 @@ const ARM_Interface& System::CurrentArmInterface() const { return impl->kernel.CurrentPhysicalCore().ArmInterface(); } -std::size_t System::CurrentCoreIndex() const { - std::size_t core = impl->kernel.GetCurrentHostThreadID(); - ASSERT(core < Core::Hardware::NUM_CPU_CORES); - return core; -} - Kernel::PhysicalCore& System::CurrentPhysicalCore() { return impl->kernel.CurrentPhysicalCore(); } diff --git a/src/core/core.h b/src/core/core.h index 645e5c241..52ff90359 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -208,9 +208,6 @@ public: /// Gets an ARM interface to the CPU core that is currently running [[nodiscard]] const ARM_Interface& CurrentArmInterface() const; - /// Gets the index of the currently running CPU core - [[nodiscard]] std::size_t CurrentCoreIndex() const; - /// Gets the physical core for the CPU core that is currently running [[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore(); diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 1b429bc1e..6771ef621 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -28,7 +28,7 @@ bool ReadFromUser(Core::System& system, s32* out, VAddr address) { bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 value) { auto& monitor = system.Monitor(); - const auto current_core = system.CurrentCoreIndex(); + const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // TODO(bunnei): We should disable interrupts here via KScopedInterruptDisable. // TODO(bunnei): We should call CanAccessAtomic(..) here. @@ -58,7 +58,7 @@ bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 valu bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32 new_value) { auto& monitor = system.Monitor(); - const auto current_core = system.CurrentCoreIndex(); + const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // TODO(bunnei): We should disable interrupts here via KScopedInterruptDisable. // TODO(bunnei): We should call CanAccessAtomic(..) here. diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 7fa9b8cc3..ed6f328fc 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -33,7 +33,7 @@ bool WriteToUser(Core::System& system, VAddr address, const u32* p) { bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero, u32 new_orr_mask) { auto& monitor = system.Monitor(); - const auto current_core = system.CurrentCoreIndex(); + const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // Load the value from the address. const auto expected = monitor.ExclusiveRead32(current_core, address); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 45e86a677..04926a291 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -845,6 +845,14 @@ const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { return impl->cores[id]; } +size_t KernelCore::CurrentPhysicalCoreIndex() const { + const u32 core_id = impl->GetCurrentHostThreadID(); + if (core_id >= Core::Hardware::NUM_CPU_CORES) { + return Core::Hardware::NUM_CPU_CORES - 1; + } + return core_id; +} + Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { u32 core_id = impl->GetCurrentHostThreadID(); ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d2ceae950..3499f8b90 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -148,6 +148,9 @@ public: /// Gets the an instance of the respective physical CPU core. const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const; + /// Gets the current physical core index for the running host thread. + std::size_t CurrentPhysicalCoreIndex() const; + /// Gets the sole instance of the Scheduler at the current running core. Kernel::KScheduler* CurrentScheduler(); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f0cd8471e..e5e879eb5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -873,7 +873,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle const u64 thread_ticks = current_thread->GetCpuTime(); out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); - } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { + } else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) { out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks; } @@ -887,7 +887,8 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle return ResultInvalidHandle; } - if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id != system.CurrentCoreIndex()) { + if (info_sub_id != 0xFFFFFFFFFFFFFFFF && + info_sub_id != system.Kernel().CurrentPhysicalCoreIndex()) { LOG_ERROR(Kernel_SVC, "Core is not the current core, got {}", info_sub_id); return ResultInvalidCombination; } -- cgit v1.2.3 From 3bd5d4b6f8887ffe302a73e3ad595f58409b5c9e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 22:58:46 -0700 Subject: core: hle: kernel: Ensure idle threads are closed before destroying scheduler. --- src/core/hle/kernel/k_scheduler.cpp | 6 +++++- src/core/hle/kernel/k_scheduler.h | 2 ++ src/core/hle/kernel/kernel.cpp | 38 +++++++++++++++---------------------- 3 files changed, 22 insertions(+), 24 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 6a7d80d03..4bae69f71 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -617,13 +617,17 @@ KScheduler::KScheduler(Core::System& system_, s32 core_id_) : system{system_}, c state.highest_priority_thread = nullptr; } -KScheduler::~KScheduler() { +void KScheduler::Finalize() { if (idle_thread) { idle_thread->Close(); idle_thread = nullptr; } } +KScheduler::~KScheduler() { + ASSERT(!idle_thread); +} + KThread* KScheduler::GetCurrentThread() const { if (auto result = current_thread.load(); result) { return result; diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index 7df288438..82fcd99e7 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h @@ -33,6 +33,8 @@ public: explicit KScheduler(Core::System& system_, s32 core_id_); ~KScheduler(); + void Finalize(); + /// Reschedules to the next available thread (call after current thread is suspended) void RescheduleCurrentCore(); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 04926a291..275fee0d8 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -83,8 +83,9 @@ struct KernelCore::Impl { } void InitializeCores() { - for (auto& core : cores) { - core.Initialize(current_process->Is64BitProcess()); + for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { + cores[core_id].Initialize(current_process->Is64BitProcess()); + system.Memory().SetCurrentPageTable(*current_process, core_id); } } @@ -123,15 +124,6 @@ struct KernelCore::Impl { next_user_process_id = KProcess::ProcessIDMin; next_thread_id = 1; - for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { - if (suspend_threads[core_id]) { - suspend_threads[core_id]->Close(); - suspend_threads[core_id] = nullptr; - } - - schedulers[core_id].reset(); - } - cores.clear(); global_handle_table->Finalize(); @@ -159,6 +151,16 @@ struct KernelCore::Impl { CleanupObject(time_shared_mem); CleanupObject(system_resource_limit); + for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { + if (suspend_threads[core_id]) { + suspend_threads[core_id]->Close(); + suspend_threads[core_id] = nullptr; + } + + schedulers[core_id]->Finalize(); + schedulers[core_id].reset(); + } + // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others next_host_thread_id = Core::Hardware::NUM_CPU_CORES; @@ -267,14 +269,6 @@ struct KernelCore::Impl { void MakeCurrentProcess(KProcess* process) { current_process = process; - if (process == nullptr) { - return; - } - - const u32 core_id = GetCurrentHostThreadID(); - if (core_id < Core::Hardware::NUM_CPU_CORES) { - system.Memory().SetCurrentPageTable(*process, core_id); - } } static inline thread_local u32 host_thread_id = UINT32_MAX; @@ -1079,13 +1073,11 @@ void KernelCore::ExceptionalExit() { } void KernelCore::EnterSVCProfile() { - std::size_t core = impl->GetCurrentHostThreadID(); - impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC)); + impl->svc_ticks[CurrentPhysicalCoreIndex()] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC)); } void KernelCore::ExitSVCProfile() { - std::size_t core = impl->GetCurrentHostThreadID(); - MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]); + MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]); } std::weak_ptr KernelCore::CreateServiceThread(const std::string& name) { -- cgit v1.2.3 From 04daefa4887fac9f90d873b5ae4b87548eafb2f0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:04:32 -0700 Subject: core: hle: kernel: k_thread: Add KScopedDisableDispatch. --- src/core/hle/kernel/k_thread.cpp | 17 ++++++++++++++++- src/core/hle/kernel/k_thread.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index db65ce79a..de94c737d 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -184,7 +184,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s // Setup the stack parameters. StackParameters& sp = GetStackParameters(); sp.cur_thread = this; - sp.disable_count = 1; + sp.disable_count = 0; SetInExceptionHandler(); // Set thread ID. @@ -966,6 +966,9 @@ ResultCode KThread::Run() { // Set our state and finish. SetState(ThreadState::Runnable); + + DisableDispatch(); + return ResultSuccess; } } @@ -1050,4 +1053,16 @@ s32 GetCurrentCoreId(KernelCore& kernel) { return GetCurrentThread(kernel).GetCurrentCore(); } +KScopedDisableDispatch::~KScopedDisableDispatch() { + if (GetCurrentThread(kernel).GetDisableDispatchCount() <= 1) { + auto scheduler = kernel.CurrentScheduler(); + + if (scheduler) { + scheduler->RescheduleCurrentCore(); + } + } else { + GetCurrentThread(kernel).EnableDispatch(); + } +} + } // namespace Kernel diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index c77f44ad4..a149744c8 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -450,16 +450,35 @@ public: sleeping_queue = q; } + [[nodiscard]] bool IsKernelThread() const { + return GetActiveCore() == 3; + } + [[nodiscard]] s32 GetDisableDispatchCount() const { + if (IsKernelThread()) { + // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch. + return 1; + } + return this->GetStackParameters().disable_count; } void DisableDispatch() { + if (IsKernelThread()) { + // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch. + return; + } + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); this->GetStackParameters().disable_count++; } void EnableDispatch() { + if (IsKernelThread()) { + // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch. + return; + } + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() > 0); this->GetStackParameters().disable_count--; } @@ -752,4 +771,16 @@ public: } }; +class KScopedDisableDispatch { +public: + explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} { + GetCurrentThread(kernel).DisableDispatch(); + } + + ~KScopedDisableDispatch(); + +private: + KernelCore& kernel; +}; + } // namespace Kernel -- cgit v1.2.3 From 4c18a207a4898f391afab5d7e44c1c2921bc9d6f Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:05:01 -0700 Subject: core: hle: kernel: k_handle_table: Use KScopedDisableDispatch as necessary. --- src/core/hle/kernel/k_handle_table.cpp | 6 ++++++ src/core/hle/kernel/k_handle_table.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index e90fc0628..cf95f0852 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -13,6 +13,7 @@ ResultCode KHandleTable::Finalize() { // Get the table and clear our record of it. u16 saved_table_size = 0; { + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); std::swap(m_table_size, saved_table_size); @@ -43,6 +44,7 @@ bool KHandleTable::Remove(Handle handle) { // Find the object and free the entry. KAutoObject* obj = nullptr; { + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); if (this->IsValidHandle(handle)) { @@ -62,6 +64,7 @@ bool KHandleTable::Remove(Handle handle) { } ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) { + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -84,6 +87,7 @@ ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) { } ResultCode KHandleTable::Reserve(Handle* out_handle) { + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -94,6 +98,7 @@ ResultCode KHandleTable::Reserve(Handle* out_handle) { } void KHandleTable::Unreserve(Handle handle) { + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -112,6 +117,7 @@ void KHandleTable::Unreserve(Handle handle) { } void KHandleTable::Register(Handle handle, KAutoObject* obj, u16 type) { + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); // Unpack the handle. diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 95ec905ae..4b114ec2f 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -68,6 +68,7 @@ public: template KScopedAutoObject GetObjectWithoutPseudoHandle(Handle handle) const { // Lock and look up in table. + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); if constexpr (std::is_same_v) { @@ -122,6 +123,7 @@ public: size_t num_opened; { // Lock the table. + KScopedDisableDispatch dd(kernel); KScopedSpinLock lk(m_lock); for (num_opened = 0; num_opened < num_handles; num_opened++) { // Get the current handle. -- cgit v1.2.3 From f13fce3953b376d2321645b4de4d023da0d6713d Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:08:26 -0700 Subject: core: hle: kernel: k_process: DisableDispatch on main thread. --- src/core/hle/kernel/k_process.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 1aad061e1..7cc2061ea 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -60,6 +60,7 @@ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority thread->GetContext64().cpu_registers[0] = 0; thread->GetContext32().cpu_registers[1] = thread_handle; thread->GetContext64().cpu_registers[1] = thread_handle; + thread->DisableDispatch(); auto& kernel = system.Kernel(); // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires -- cgit v1.2.3 From f412d2027a6e5798fe6fc3b43250bc2f5f1d17fc Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:12:47 -0700 Subject: core: hle: kernel: k_scheduler: Improve Unload. --- src/core/hle/kernel/k_scheduler.cpp | 46 +++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 17 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 4bae69f71..5ee4b8adc 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -650,6 +650,7 @@ void KScheduler::RescheduleCurrentCore() { if (state.needs_scheduling.load()) { Schedule(); } else { + GetCurrentThread()->EnableDispatch(); guard.Unlock(); } } @@ -659,26 +660,37 @@ void KScheduler::OnThreadStart() { } void KScheduler::Unload(KThread* thread) { + ASSERT(thread); + + if (!thread) { + return; + } + LOG_TRACE(Kernel, "core {}, unload thread {}", core_id, thread ? thread->GetName() : "nullptr"); - if (thread) { - if (thread->IsCallingSvc()) { - thread->ClearIsCallingSvc(); - } - if (!thread->IsTerminationRequested()) { - prev_thread = thread; - - Core::ARM_Interface& cpu_core = system.ArmInterface(core_id); - cpu_core.SaveContext(thread->GetContext32()); - cpu_core.SaveContext(thread->GetContext64()); - // Save the TPIDR_EL0 system register in case it was modified. - thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); - cpu_core.ClearExclusiveState(); - } else { - prev_thread = nullptr; - } - thread->context_guard.Unlock(); + if (thread->IsCallingSvc()) { + thread->ClearIsCallingSvc(); } + + auto& physical_core = system.Kernel().PhysicalCore(core_id); + if (!physical_core.IsInitialized()) { + return; + } + + Core::ARM_Interface& cpu_core = physical_core.ArmInterface(); + cpu_core.SaveContext(thread->GetContext32()); + cpu_core.SaveContext(thread->GetContext64()); + // Save the TPIDR_EL0 system register in case it was modified. + thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); + cpu_core.ClearExclusiveState(); + + if (!thread->IsTerminationRequested() && thread->GetActiveCore() == core_id) { + prev_thread = thread; + } else { + prev_thread = nullptr; + } + + thread->context_guard.Unlock(); } void KScheduler::Reload(KThread* thread) { -- cgit v1.2.3 From 13c82d042f10dbaec7fb66764bf4b636e7a2949b Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:16:12 -0700 Subject: core: hle: kernel: k_scheduler: Improve ScheduleImpl. --- src/core/hle/kernel/k_scheduler.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 5ee4b8adc..e523c4923 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -721,7 +721,7 @@ void KScheduler::SwitchContextStep2() { } void KScheduler::ScheduleImpl() { - KThread* previous_thread = current_thread.load(); + KThread* previous_thread = GetCurrentThread(); KThread* next_thread = state.highest_priority_thread; state.needs_scheduling = false; @@ -733,10 +733,15 @@ void KScheduler::ScheduleImpl() { // If we're not actually switching thread, there's nothing to do. if (next_thread == current_thread.load()) { + previous_thread->EnableDispatch(); guard.Unlock(); return; } + if (next_thread->GetCurrentCore() != core_id) { + next_thread->SetCurrentCore(core_id); + } + current_thread.store(next_thread); KProcess* const previous_process = system.Kernel().CurrentProcess(); @@ -747,11 +752,7 @@ void KScheduler::ScheduleImpl() { Unload(previous_thread); std::shared_ptr* old_context; - if (previous_thread != nullptr) { - old_context = &previous_thread->GetHostContext(); - } else { - old_context = &idle_thread->GetHostContext(); - } + old_context = &previous_thread->GetHostContext(); guard.Unlock(); Common::Fiber::YieldTo(*old_context, *switch_fiber); -- cgit v1.2.3 From 629f9274ac88722d828e3484f73084376c2811ba Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:16:36 -0700 Subject: core: hle: kernel: k_scheduler: Remove unnecessary MakeCurrentProcess. --- src/core/hle/kernel/k_scheduler.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index e523c4923..f5236dfea 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -699,11 +699,6 @@ void KScheduler::Reload(KThread* thread) { if (thread) { ASSERT_MSG(thread->GetState() == ThreadState::Runnable, "Thread must be runnable."); - auto* const thread_owner_process = thread->GetOwnerProcess(); - if (thread_owner_process != nullptr) { - system.Kernel().MakeCurrentProcess(thread_owner_process); - } - Core::ARM_Interface& cpu_core = system.ArmInterface(core_id); cpu_core.LoadContext(thread->GetContext32()); cpu_core.LoadContext(thread->GetContext64()); -- cgit v1.2.3 From 178584e56f742274ca6392ce3d87ff2ca08de731 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:20:07 -0700 Subject: core: hle: kernel: Use CurrentPhysicalCoreIndex as appropriate. --- src/core/hle/kernel/kernel.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 275fee0d8..288488644 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -848,15 +848,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const { } Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { - u32 core_id = impl->GetCurrentHostThreadID(); - ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); - return impl->cores[core_id]; + return impl->cores[CurrentPhysicalCoreIndex()]; } const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const { - u32 core_id = impl->GetCurrentHostThreadID(); - ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); - return impl->cores[core_id]; + return impl->cores[CurrentPhysicalCoreIndex()]; } Kernel::KScheduler* KernelCore::CurrentScheduler() { -- cgit v1.2.3 From d604edfedffa1245ad33dd668e9e42394a213e24 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:22:52 -0700 Subject: core: cpu_manager: Use KScopedDisableDispatch. --- src/core/cpu_manager.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 5d43c6e5d..45cc176dc 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -117,17 +117,18 @@ void CpuManager::MultiCoreRunGuestLoop() { physical_core = &kernel.CurrentPhysicalCore(); } system.ExitDynarmicProfile(); - physical_core->ArmInterface().ClearExclusiveState(); - kernel.CurrentScheduler()->RescheduleCurrentCore(); + { + Kernel::KScopedDisableDispatch dd(kernel); + physical_core->ArmInterface().ClearExclusiveState(); + } } } void CpuManager::MultiCoreRunIdleThread() { auto& kernel = system.Kernel(); while (true) { - auto& physical_core = kernel.CurrentPhysicalCore(); - physical_core.Idle(); - kernel.CurrentScheduler()->RescheduleCurrentCore(); + Kernel::KScopedDisableDispatch dd(kernel); + kernel.CurrentPhysicalCore().Idle(); } } @@ -135,12 +136,12 @@ void CpuManager::MultiCoreRunSuspendThread() { auto& kernel = system.Kernel(); kernel.CurrentScheduler()->OnThreadStart(); while (true) { - auto core = kernel.GetCurrentHostThreadID(); + auto core = kernel.CurrentPhysicalCoreIndex(); auto& scheduler = *kernel.CurrentScheduler(); Kernel::KThread* current_thread = scheduler.GetCurrentThread(); Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context); ASSERT(scheduler.ContextSwitchPending()); - ASSERT(core == kernel.GetCurrentHostThreadID()); + ASSERT(core == kernel.CurrentPhysicalCoreIndex()); scheduler.RescheduleCurrentCore(); } } -- cgit v1.2.3 From 284015dfd7d0b963b9ad0d196ee283ef2287b812 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:27:33 -0700 Subject: core: hle: kernel: k_scheduler: Improve DisableScheduling and EnableScheduling. --- src/core/hle/kernel/k_scheduler.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index f5236dfea..6ddbae52c 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -376,20 +376,18 @@ void KScheduler::ClearSchedulerUpdateNeeded(KernelCore& kernel) { } void KScheduler::DisableScheduling(KernelCore& kernel) { - if (auto* scheduler = kernel.CurrentScheduler(); scheduler) { - ASSERT(scheduler->GetCurrentThread()->GetDisableDispatchCount() >= 0); - scheduler->GetCurrentThread()->DisableDispatch(); - } + ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 0); + GetCurrentThreadPointer(kernel)->DisableDispatch(); } void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) { - if (auto* scheduler = kernel.CurrentScheduler(); scheduler) { - ASSERT(scheduler->GetCurrentThread()->GetDisableDispatchCount() >= 1); - if (scheduler->GetCurrentThread()->GetDisableDispatchCount() >= 1) { - scheduler->GetCurrentThread()->EnableDispatch(); - } + ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 1); + + if (GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() > 1) { + GetCurrentThreadPointer(kernel)->EnableDispatch(); + } else { + RescheduleCores(kernel, cores_needing_scheduling); } - RescheduleCores(kernel, cores_needing_scheduling); } u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { @@ -646,6 +644,7 @@ void KScheduler::RescheduleCurrentCore() { if (phys_core.IsInterrupted()) { phys_core.ClearInterrupt(); } + guard.Lock(); if (state.needs_scheduling.load()) { Schedule(); @@ -662,10 +661,6 @@ void KScheduler::OnThreadStart() { void KScheduler::Unload(KThread* thread) { ASSERT(thread); - if (!thread) { - return; - } - LOG_TRACE(Kernel, "core {}, unload thread {}", core_id, thread ? thread->GetName() : "nullptr"); if (thread->IsCallingSvc()) { -- cgit v1.2.3 From 3239442de6204f41054b8c0121420e64f66c832e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Aug 2021 23:43:26 -0700 Subject: core: hle: kernel: DisableDispatch on suspend threads. --- src/core/hle/kernel/kernel.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 288488644..cf155ff66 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -1055,6 +1055,9 @@ void KernelCore::Suspend(bool in_suspention) { impl->suspend_threads[core_id]->SetState(state); impl->suspend_threads[core_id]->SetWaitReasonForDebugging( ThreadWaitReasonForDebugging::Suspended); + if (!should_suspend) { + impl->suspend_threads[core_id]->DisableDispatch(); + } } } } -- cgit v1.2.3 From 07690572f777c66f649110db780f556186f5fea8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 7 Aug 2021 01:16:29 -0700 Subject: core: hle: kernel: k_auto_object: Add GetName method. - Useful purely for debugging. --- src/core/hle/kernel/k_auto_object.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index e4fcdbc67..165b76747 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -170,6 +170,10 @@ public: } } + const std::string& GetName() const { + return name; + } + private: void RegisterWithKernel(); void UnregisterWithKernel(); -- cgit v1.2.3 From 08c63d5c75522ce6b484153302de4c6cfac674f2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 7 Aug 2021 12:33:07 -0700 Subject: core: cpu_manager: Use invalid core_id on init and simplify shutdown. --- src/core/cpu_manager.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 45cc176dc..d9bd5b665 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -32,7 +32,7 @@ void CpuManager::Initialize() { core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); } } else { - core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0); + core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), -1); } } @@ -347,13 +347,9 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { sc_sync_first_use = false; } - // Abort if emulation was killed before the session really starts - if (!system.IsPoweredOn()) { - return; - } - + // Emulation was stopped if (stop_token.stop_requested()) { - break; + return; } auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); -- cgit v1.2.3 From d14b8fc7471061b84e7de0bd982a64660ee7f349 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 7 Aug 2021 12:33:31 -0700 Subject: core: hle: kernel: k_thread: Mark KScopedDisableDispatch as nodiscard. --- src/core/hle/kernel/k_thread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index a149744c8..8bbf66c52 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -773,7 +773,7 @@ public: class KScopedDisableDispatch { public: - explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} { + [[nodiscard]] explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} { GetCurrentThread(kernel).DisableDispatch(); } -- cgit v1.2.3 From 3dc803a430107fb22ffc91608c613e09ec5c8b51 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 14 Aug 2021 02:14:19 -0700 Subject: core: hle: kernel: Disable dispatch count tracking on single core. - This would have limited value, and would be a mess to handle properly. --- src/core/cpu_manager.cpp | 2 +- src/core/hle/kernel/k_thread.cpp | 6 +++++- src/core/hle/kernel/k_thread.h | 11 ++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index d9bd5b665..cbcc54891 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -32,7 +32,7 @@ void CpuManager::Initialize() { core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); } } else { - core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), -1); + core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0); } } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index de94c737d..41bf9a6bb 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -13,6 +13,9 @@ #include "common/common_types.h" #include "common/fiber.h" #include "common/logging/log.h" +#include "common/scope_exit.h" +#include "common/settings.h" +#include "common/thread_queue_list.h" #include "core/core.h" #include "core/cpu_manager.h" #include "core/hardware_properties.h" @@ -211,9 +214,10 @@ ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uint // Initialize the thread. R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); - // Initialize host context. + // Initialize emulation parameters. thread->host_context = std::make_shared(std::move(init_func), init_func_parameter); + thread->is_single_core = !Settings::values.use_multi_core.GetValue(); return ResultSuccess; } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 8bbf66c52..e4c4c877d 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -454,8 +454,12 @@ public: return GetActiveCore() == 3; } + [[nodiscard]] bool IsDispatchTrackingDisabled() const { + return is_single_core || IsKernelThread(); + } + [[nodiscard]] s32 GetDisableDispatchCount() const { - if (IsKernelThread()) { + if (IsDispatchTrackingDisabled()) { // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch. return 1; } @@ -464,7 +468,7 @@ public: } void DisableDispatch() { - if (IsKernelThread()) { + if (IsDispatchTrackingDisabled()) { // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch. return; } @@ -474,7 +478,7 @@ public: } void EnableDispatch() { - if (IsKernelThread()) { + if (IsDispatchTrackingDisabled()) { // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch. return; } @@ -727,6 +731,7 @@ private: // For emulation std::shared_ptr host_context{}; + bool is_single_core{}; // For debugging std::vector wait_objects_for_debugging; -- cgit v1.2.3 From bc1399204b914608715306a8a8dbe2f201dd4365 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 19:02:11 -0800 Subject: hle: kernel: Update KThreadQueue and migrate KSynchronizationObject. --- src/core/CMakeLists.txt | 1 + .../hle/kernel/k_scoped_scheduler_lock_and_sleep.h | 1 + src/core/hle/kernel/k_synchronization_object.cpp | 155 +++++++++++---------- src/core/hle/kernel/k_synchronization_object.h | 32 +++++ src/core/hle/kernel/k_thread.cpp | 42 +++++- src/core/hle/kernel/k_thread.h | 27 ++++ src/core/hle/kernel/k_thread_queue.cpp | 51 +++++++ src/core/hle/kernel/k_thread_queue.h | 17 +++ 8 files changed, 251 insertions(+), 75 deletions(-) create mode 100644 src/core/hle/kernel/k_thread_queue.cpp (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index eee8e2ccd..c42a29cc7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -237,6 +237,7 @@ add_library(core STATIC hle/kernel/k_system_control.h hle/kernel/k_thread.cpp hle/kernel/k_thread.h + hle/kernel/k_thread_queue.cpp hle/kernel/k_thread_queue.h hle/kernel/k_trace.h hle/kernel/k_transfer_memory.cpp diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index 61dc2858f..2995c492d 100644 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h @@ -8,6 +8,7 @@ #pragma once #include "common/common_types.h" +#include "core/hle/kernel/global_scheduler_context.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/time_manager.h" diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index f168b4f21..ba8fc4010 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -8,11 +8,70 @@ #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" namespace Kernel { +namespace { + +class ThreadQueueImplForKSynchronizationObjectWait final : public KThreadQueueWithoutEndWait { +private: + using ThreadListNode = KSynchronizationObject::ThreadListNode; + +private: + KSynchronizationObject** m_objects; + ThreadListNode* m_nodes; + s32 m_count; + +public: + ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel_, KSynchronizationObject** o, + ThreadListNode* n, s32 c) + : KThreadQueueWithoutEndWait(kernel_), m_objects(o), m_nodes(n), m_count(c) { // ... + } + + virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, + ResultCode wait_result) override { + // Determine the sync index, and unlink all nodes. + s32 sync_index = -1; + for (auto i = 0; i < m_count; ++i) { + // Check if this is the signaled object. + if (m_objects[i] == signaled_object && sync_index == -1) { + sync_index = i; + } + + // Unlink the current node from the current object. + m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); + } + + // Set the waiting thread's sync index. + waiting_thread->SetSyncedIndex(sync_index); + + // Set the waiting thread as not cancellable. + waiting_thread->ClearCancellable(); + + // Invoke the base end wait handler. + KThreadQueue::EndWait(waiting_thread, wait_result); + } + + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // Remove all nodes from our list. + for (auto i = 0; i < m_count; ++i) { + m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); + } + + // Set the waiting thread as not cancellable. + waiting_thread->ClearCancellable(); + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + } +}; + +} // namespace + void KSynchronizationObject::Finalize() { this->OnFinalizeSynchronizationObject(); KAutoObject::Finalize(); @@ -25,11 +84,19 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, std::vector thread_nodes(num_objects); // Prepare for wait. - KThread* thread = kernel_ctx.CurrentScheduler()->GetCurrentThread(); + KThread* thread = GetCurrentThreadPointer(kernel_ctx); + ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects, + thread_nodes.data(), num_objects); { // Setup the scheduling lock and sleep. - KScopedSchedulerLockAndSleep slp{kernel_ctx, thread, timeout}; + KScopedSchedulerLockAndSleep slp(kernel_ctx, thread, timeout); + + // Check if the thread should terminate. + if (thread->IsTerminationRequested()) { + slp.CancelSleep(); + return ResultTerminationRequested; + } // Check if any of the objects are already signaled. for (auto i = 0; i < num_objects; ++i) { @@ -48,12 +115,6 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, return ResultTimedOut; } - // Check if the thread should terminate. - if (thread->IsTerminationRequested()) { - slp.CancelSleep(); - return ResultTerminationRequested; - } - // Check if waiting was canceled. if (thread->IsWaitCancelled()) { slp.CancelSleep(); @@ -66,73 +127,25 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, thread_nodes[i].thread = thread; thread_nodes[i].next = nullptr; - if (objects[i]->thread_list_tail == nullptr) { - objects[i]->thread_list_head = std::addressof(thread_nodes[i]); - } else { - objects[i]->thread_list_tail->next = std::addressof(thread_nodes[i]); - } - - objects[i]->thread_list_tail = std::addressof(thread_nodes[i]); + objects[i]->LinkNode(std::addressof(thread_nodes[i])); } - // For debugging only - thread->SetWaitObjectsForDebugging({objects, static_cast(num_objects)}); - - // Mark the thread as waiting. + // Mark the thread as cancellable. thread->SetCancellable(); - thread->SetSyncedObject(nullptr, ResultTimedOut); - thread->SetState(ThreadState::Waiting); - thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); - } - - // The lock/sleep is done, so we should be able to get our result. - // Thread is no longer cancellable. - thread->ClearCancellable(); + // Clear the thread's synced index. + thread->SetSyncedIndex(-1); - // For debugging only - thread->SetWaitObjectsForDebugging({}); + // Wait for an object to be signaled. + thread->BeginWait(std::addressof(wait_queue)); + thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); + } - // Cancel the timer as needed. - kernel_ctx.TimeManager().UnscheduleTimeEvent(thread); + // Set the output index. + *out_index = thread->GetSyncedIndex(); // Get the wait result. - ResultCode wait_result{ResultSuccess}; - s32 sync_index = -1; - { - KScopedSchedulerLock lock(kernel_ctx); - KSynchronizationObject* synced_obj; - wait_result = thread->GetWaitResult(std::addressof(synced_obj)); - - for (auto i = 0; i < num_objects; ++i) { - // Unlink the object from the list. - ThreadListNode* prev_ptr = - reinterpret_cast(std::addressof(objects[i]->thread_list_head)); - ThreadListNode* prev_val = nullptr; - ThreadListNode *prev, *tail_prev; - - do { - prev = prev_ptr; - prev_ptr = prev_ptr->next; - tail_prev = prev_val; - prev_val = prev_ptr; - } while (prev_ptr != std::addressof(thread_nodes[i])); - - if (objects[i]->thread_list_tail == std::addressof(thread_nodes[i])) { - objects[i]->thread_list_tail = tail_prev; - } - - prev->next = thread_nodes[i].next; - - if (objects[i] == synced_obj) { - sync_index = i; - } - } - } - - // Set output. - *out_index = sync_index; - return wait_result; + return thread->GetWaitResult(); } KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_) @@ -141,7 +154,7 @@ KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_) KSynchronizationObject::~KSynchronizationObject() = default; void KSynchronizationObject::NotifyAvailable(ResultCode result) { - KScopedSchedulerLock lock(kernel); + KScopedSchedulerLock sl(kernel); // If we're not signaled, we've nothing to notify. if (!this->IsSignaled()) { @@ -150,11 +163,7 @@ void KSynchronizationObject::NotifyAvailable(ResultCode result) { // Iterate over each thread. for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { - KThread* thread = cur_node->thread; - if (thread->GetState() == ThreadState::Waiting) { - thread->SetSyncedObject(this, result); - thread->SetState(ThreadState::Runnable); - } + cur_node->thread->NotifyAvailable(this, result); } } diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index 898e58e16..789ff4780 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -35,6 +35,38 @@ public: [[nodiscard]] std::vector GetWaitingThreadsForDebugging() const; + void LinkNode(ThreadListNode* node) { + // Link the node to the list. + if (thread_list_tail == nullptr) { + thread_list_head = node; + } else { + thread_list_tail->next = node; + } + + thread_list_tail = node; + } + + void UnlinkNode(ThreadListNode* node) { + // Unlink the node from the list. + ThreadListNode* prev_ptr = + reinterpret_cast(std::addressof(thread_list_head)); + ThreadListNode* prev_val = nullptr; + ThreadListNode *prev, *tail_prev; + + do { + prev = prev_ptr; + prev_ptr = prev_ptr->next; + tail_prev = prev_val; + prev_val = prev_ptr; + } while (prev_ptr != node); + + if (thread_list_tail == node) { + thread_list_tail = tail_prev; + } + + prev->next = node->next; + } + protected: explicit KSynchronizationObject(KernelCore& kernel); ~KSynchronizationObject() override; diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 41bf9a6bb..3331b4845 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -303,7 +303,7 @@ void KThread::Wakeup() { if (GetState() == ThreadState::Waiting) { if (sleeping_queue != nullptr) { - sleeping_queue->WakeupThread(this); + sleeping_queue->EndWait(this, ResultSuccess); } else { SetState(ThreadState::Runnable); } @@ -331,7 +331,7 @@ void KThread::StartTermination() { // Signal. signaled = true; - NotifyAvailable(); + KSynchronizationObject::NotifyAvailable(); // Clear previous thread in KScheduler. KScheduler::ClearPreviousThread(kernel, this); @@ -1026,6 +1026,44 @@ ResultCode KThread::Sleep(s64 timeout) { return ResultSuccess; } +void KThread::BeginWait(KThreadQueue* queue) { + // Set our state as waiting. + SetState(ThreadState::Waiting); + + // Set our wait queue. + sleeping_queue = queue; +} + +void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { + // Lock the scheduler. + KScopedSchedulerLock sl(kernel); + + // If we're waiting, notify our queue that we're available. + if (GetState() == ThreadState::Waiting) { + sleeping_queue->NotifyAvailable(this, signaled_object, wait_result_); + } +} + +void KThread::EndWait(ResultCode wait_result_) { + // Lock the scheduler. + KScopedSchedulerLock sl(kernel); + + // If we're waiting, notify our queue that we're available. + if (GetState() == ThreadState::Waiting) { + sleeping_queue->EndWait(this, wait_result_); + } +} + +void KThread::CancelWait(ResultCode wait_result_, bool cancel_timer_task) { + // Lock the scheduler. + KScopedSchedulerLock sl(kernel); + + // If we're waiting, notify our queue that we're available. + if (GetState() == ThreadState::Waiting) { + sleeping_queue->CancelWait(this, wait_result_, cancel_timer_task); + } +} + void KThread::SetState(ThreadState state) { KScopedSchedulerLock sl{kernel}; diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e4c4c877d..bea5fd84d 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -202,6 +202,23 @@ public: wait_result = wait_res; } + constexpr void SetSyncedIndex(s32 index) { + synced_index = index; + } + + constexpr s32 GetSyncedIndex() const { + return synced_index; + } + + constexpr void SetWaitResult(ResultCode wait_res) { + wait_result = wait_res; + synced_object = nullptr; + } + + constexpr ResultCode GetWaitResult() const { + return wait_result; + } + [[nodiscard]] ResultCode GetWaitResult(KSynchronizationObject** out) const { *out = synced_object; return wait_result; @@ -596,6 +613,15 @@ public: address_key_value = val; } + void ClearWaitQueue() { + sleeping_queue = nullptr; + } + + void BeginWait(KThreadQueue* queue); + void NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_); + void EndWait(ResultCode wait_result_); + void CancelWait(ResultCode wait_result_, bool cancel_timer_task); + [[nodiscard]] bool HasWaiters() const { return !waiter_list.empty(); } @@ -707,6 +733,7 @@ private: u32 address_key_value{}; u32 suspend_request_flags{}; u32 suspend_allowed_flags{}; + s32 synced_index{}; ResultCode wait_result{ResultSuccess}; s32 base_priority{}; s32 physical_ideal_core_id{}; diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp new file mode 100644 index 000000000..46f27172b --- /dev/null +++ b/src/core/hle/kernel/k_thread_queue.cpp @@ -0,0 +1,51 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/k_thread_queue.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/time_manager.h" + +namespace Kernel { + +void KThreadQueue::NotifyAvailable([[maybe_unused]] KThread* waiting_thread, + [[maybe_unused]] KSynchronizationObject* signaled_object, + [[maybe_unused]] ResultCode wait_result) {} + +void KThreadQueue::EndWait(KThread* waiting_thread, ResultCode wait_result) { + // Set the thread's wait result. + waiting_thread->SetWaitResult(wait_result); + + // Set the thread as runnable. + waiting_thread->SetState(ThreadState::Runnable); + + // Clear the thread's wait queue. + waiting_thread->ClearWaitQueue(); + + // Cancel the thread task. + kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); +} + +void KThreadQueue::CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) { + // Set the thread's wait result. + waiting_thread->SetWaitResult(wait_result); + + // Set the thread as runnable. + waiting_thread->SetState(ThreadState::Runnable); + + // Clear the thread's wait queue. + waiting_thread->ClearWaitQueue(); + + // Cancel the thread task. + if (cancel_timer_task) { + kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); + } +} + +void KThreadQueueWithoutEndWait::EndWait([[maybe_unused]] KThread* waiting_thread, + [[maybe_unused]] ResultCode wait_result) {} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 35d471dc5..74e76e7cb 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -4,6 +4,7 @@ #pragma once +#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" namespace Kernel { @@ -11,7 +12,16 @@ namespace Kernel { class KThreadQueue { public: explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {} + virtual ~KThreadQueue(){}; + virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, + ResultCode wait_result); + virtual void EndWait(KThread* waiting_thread, ResultCode wait_result); + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task); + + // Deprecated, will be removed in subsequent commits. +public: bool IsEmpty() const { return wait_list.empty(); } @@ -78,4 +88,11 @@ private: KThread::WaiterList wait_list{}; }; +class KThreadQueueWithoutEndWait : public KThreadQueue { +public: + explicit KThreadQueueWithoutEndWait(KernelCore& kernel_) : KThreadQueue(kernel_) {} + + virtual void EndWait(KThread* waiting_thread, ResultCode wait_result) override final; +}; + } // namespace Kernel -- cgit v1.2.3 From 2f894560413db9bf8efc1febc26904937a28380f Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 19:21:20 -0800 Subject: hle: kernel: KThread: Remove tracking of sync object from threads. --- src/core/hle/kernel/k_address_arbiter.cpp | 16 +++++++--------- src/core/hle/kernel/k_condition_variable.cpp | 22 ++++++++++------------ src/core/hle/kernel/k_server_session.cpp | 2 +- src/core/hle/kernel/k_thread.cpp | 7 ++----- src/core/hle/kernel/k_thread.h | 12 ------------ src/core/hle/kernel/svc.cpp | 3 +-- 6 files changed, 21 insertions(+), 41 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 6771ef621..c5c81a880 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -97,7 +97,7 @@ ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { KThread* target_thread = std::addressof(*it); - target_thread->SetSyncedObject(nullptr, ResultSuccess); + target_thread->SetWaitResult(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->Wakeup(); @@ -130,7 +130,7 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { KThread* target_thread = std::addressof(*it); - target_thread->SetSyncedObject(nullptr, ResultSuccess); + target_thread->SetWaitResult(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->Wakeup(); @@ -198,7 +198,7 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { KThread* target_thread = std::addressof(*it); - target_thread->SetSyncedObject(nullptr, ResultSuccess); + target_thread->SetWaitResult(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->Wakeup(); @@ -225,7 +225,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement } // Set the synced object. - cur_thread->SetSyncedObject(nullptr, ResultTimedOut); + cur_thread->SetWaitResult(ResultTimedOut); // Read the value from userspace. s32 user_value{}; @@ -274,8 +274,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement } // Get the result. - KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(&dummy); + return cur_thread->GetWaitResult(); } ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { @@ -292,7 +291,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { } // Set the synced object. - cur_thread->SetSyncedObject(nullptr, ResultTimedOut); + cur_thread->SetWaitResult(ResultTimedOut); // Read the value from userspace. s32 user_value{}; @@ -334,8 +333,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { } // Get the result. - KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(&dummy); + return cur_thread->GetWaitResult(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index ed6f328fc..9eacbed7e 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -84,14 +84,14 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { next_value |= Svc::HandleWaitMask; } - next_owner_thread->SetSyncedObject(nullptr, ResultSuccess); + next_owner_thread->SetWaitResult(ResultSuccess); next_owner_thread->Wakeup(); } // Write the value to userspace. if (!WriteToUser(system, addr, std::addressof(next_value))) { if (next_owner_thread) { - next_owner_thread->SetSyncedObject(nullptr, ResultInvalidCurrentMemory); + next_owner_thread->SetWaitResult(ResultInvalidCurrentMemory); } return ResultInvalidCurrentMemory; @@ -110,7 +110,7 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val ASSERT(owner_thread.IsNull()); { KScopedSchedulerLock sl(kernel); - cur_thread->SetSyncedObject(nullptr, ResultSuccess); + cur_thread->SetWaitResult(ResultSuccess); // Check if the thread should terminate. R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested); @@ -151,8 +151,7 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val } // Get the wait result. - KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(std::addressof(dummy)); + return cur_thread->GetWaitResult(); } KThread* KConditionVariable::SignalImpl(KThread* thread) { @@ -179,7 +178,7 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { if (can_access) { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. - thread->SetSyncedObject(nullptr, ResultSuccess); + thread->SetWaitResult(ResultSuccess); thread->Wakeup(); } else { // Get the previous owner. @@ -195,13 +194,13 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { thread_to_close = owner_thread; } else { // The lock was tagged with a thread that doesn't exist. - thread->SetSyncedObject(nullptr, ResultInvalidState); + thread->SetWaitResult(ResultInvalidState); thread->Wakeup(); } } } else { // If the address wasn't accessible, note so. - thread->SetSyncedObject(nullptr, ResultInvalidCurrentMemory); + thread->SetWaitResult(ResultInvalidCurrentMemory); thread->Wakeup(); } @@ -265,7 +264,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; // Set the synced object. - cur_thread->SetSyncedObject(nullptr, ResultTimedOut); + cur_thread->SetWaitResult(ResultTimedOut); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -290,7 +289,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) } // Wake up the next owner. - next_owner_thread->SetSyncedObject(nullptr, ResultSuccess); + next_owner_thread->SetWaitResult(ResultSuccess); next_owner_thread->Wakeup(); } @@ -340,8 +339,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) } // Get the result. - KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(std::addressof(dummy)); + return cur_thread->GetWaitResult(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 2bd53ccbd..1f7220d48 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -176,7 +176,7 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { KScopedSchedulerLock lock(kernel); if (!context.IsThreadWaiting()) { context.GetThread().Wakeup(); - context.GetThread().SetSyncedObject(nullptr, result); + context.GetThread().SetWaitResult(result); } } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 3331b4845..2c1f29bad 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -130,9 +130,6 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s priority = prio; base_priority = prio; - // Set sync object and waiting lock to null. - synced_object = nullptr; - // Initialize sleeping queue. sleeping_queue = nullptr; @@ -279,7 +276,7 @@ void KThread::Finalize() { while (it != waiter_list.end()) { // The thread shouldn't be a kernel waiter. it->SetLockOwner(nullptr); - it->SetSyncedObject(nullptr, ResultInvalidState); + it->SetWaitResult(ResultInvalidState); it->Wakeup(); it = waiter_list.erase(it); } @@ -650,7 +647,7 @@ void KThread::WaitCancel() { sleeping_queue->WakeupThread(this); wait_cancelled = true; } else { - SetSyncedObject(nullptr, ResultCancelled); + SetWaitResult(ResultCancelled); SetState(ThreadState::Runnable); wait_cancelled = false; } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index bea5fd84d..f9a324eb3 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -197,11 +197,6 @@ public: void Suspend(); - void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) { - synced_object = obj; - wait_result = wait_res; - } - constexpr void SetSyncedIndex(s32 index) { synced_index = index; } @@ -212,18 +207,12 @@ public: constexpr void SetWaitResult(ResultCode wait_res) { wait_result = wait_res; - synced_object = nullptr; } constexpr ResultCode GetWaitResult() const { return wait_result; } - [[nodiscard]] ResultCode GetWaitResult(KSynchronizationObject** out) const { - *out = synced_object; - return wait_result; - } - /* * Returns the Thread Local Storage address of the current thread * @returns VAddr of the thread's TLS @@ -716,7 +705,6 @@ private: KAffinityMask physical_affinity_mask{}; u64 thread_id{}; std::atomic cpu_time{}; - KSynchronizationObject* synced_object{}; VAddr address_key{}; KProcess* parent{}; VAddr kernel_stack_top{}; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index e5e879eb5..50c6e513d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -325,8 +325,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { } } - KSynchronizationObject* dummy{}; - return thread->GetWaitResult(std::addressof(dummy)); + return thread->GetWaitResult(); } static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { -- cgit v1.2.3 From 15c721b90977865d964e26537f8a8f8740134164 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 19:23:37 -0800 Subject: hle: kernel: KAddressArbiter: Migrate to updated KThreadQueue. --- src/core/hle/kernel/k_address_arbiter.cpp | 82 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 43 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index c5c81a880..165475fbf 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -8,6 +8,7 @@ #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/time_manager.h" @@ -85,6 +86,27 @@ bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32 return true; } +class ThreadQueueImplForKAddressArbiter final : public KThreadQueue { +private: + KAddressArbiter::ThreadTree* m_tree; + +public: + explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel_, KAddressArbiter::ThreadTree* t) + : KThreadQueue(kernel_), m_tree(t) {} + + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // If the thread is waiting on an address arbiter, remove it from the tree. + if (waiting_thread->IsWaitingForAddressArbiter()) { + m_tree->erase(m_tree->iterator_to(*waiting_thread)); + waiting_thread->ClearAddressArbiter(); + } + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + } +}; + } // namespace ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { @@ -96,14 +118,14 @@ ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { auto it = thread_tree.nfind_light({addr, -1}); while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { + // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->SetWaitResult(ResultSuccess); + target_thread->EndWait(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); - target_thread->Wakeup(); + target_thread->ClearAddressArbiter(); it = thread_tree.erase(it); - target_thread->ClearAddressArbiter(); ++num_waiters; } } @@ -129,14 +151,14 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 auto it = thread_tree.nfind_light({addr, -1}); while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { + // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->SetWaitResult(ResultSuccess); + target_thread->EndWait(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); - target_thread->Wakeup(); + target_thread->ClearAddressArbiter(); it = thread_tree.erase(it); - target_thread->ClearAddressArbiter(); ++num_waiters; } } @@ -197,14 +219,14 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { + // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->SetWaitResult(ResultSuccess); + target_thread->EndWait(ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); - target_thread->Wakeup(); + target_thread->ClearAddressArbiter(); it = thread_tree.erase(it); - target_thread->ClearAddressArbiter(); ++num_waiters; } } @@ -214,6 +236,7 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { // Prepare to wait. KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); + ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); { KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; @@ -224,9 +247,6 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement return ResultTerminationRequested; } - // Set the synced object. - cur_thread->SetWaitResult(ResultTimedOut); - // Read the value from userspace. s32 user_value{}; bool succeeded{}; @@ -256,21 +276,10 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement // Set the arbiter. cur_thread->SetAddressArbiter(&thread_tree, addr); thread_tree.insert(*cur_thread); - cur_thread->SetState(ThreadState::Waiting); - cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); - } - // Cancel the timer wait. - kernel.TimeManager().UnscheduleTimeEvent(cur_thread); - - // Remove from the address arbiter. - { - KScopedSchedulerLock sl(kernel); - - if (cur_thread->IsWaitingForAddressArbiter()) { - thread_tree.erase(thread_tree.iterator_to(*cur_thread)); - cur_thread->ClearAddressArbiter(); - } + // Wait for the thread to finish. + cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } // Get the result. @@ -280,6 +289,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Prepare to wait. KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); + ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); { KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; @@ -290,9 +300,6 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { return ResultTerminationRequested; } - // Set the synced object. - cur_thread->SetWaitResult(ResultTimedOut); - // Read the value from userspace. s32 user_value{}; if (!ReadFromUser(system, &user_value, addr)) { @@ -315,21 +322,10 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Set the arbiter. cur_thread->SetAddressArbiter(&thread_tree, addr); thread_tree.insert(*cur_thread); - cur_thread->SetState(ThreadState::Waiting); - cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); - } - - // Cancel the timer wait. - kernel.TimeManager().UnscheduleTimeEvent(cur_thread); - // Remove from the address arbiter. - { - KScopedSchedulerLock sl(kernel); - - if (cur_thread->IsWaitingForAddressArbiter()) { - thread_tree.erase(thread_tree.iterator_to(*cur_thread)); - cur_thread->ClearAddressArbiter(); - } + // Wait for the thread to finish. + cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } // Get the result. -- cgit v1.2.3 From 423acf53b740ce96ca37988aad79ddf5013645ef Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 20:51:47 -0800 Subject: hle: kernel: KLightLock: Migrate to updated KThreadQueue. --- src/core/hle/kernel/k_light_lock.cpp | 69 ++++++++++++++++++------------------ src/core/hle/kernel/k_light_lock.h | 2 +- 2 files changed, 36 insertions(+), 35 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index 0896e705f..5e8f1a510 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -5,44 +5,54 @@ #include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" namespace Kernel { +namespace { + +class ThreadQueueImplForKLightLock final : public KThreadQueue { +public: + explicit ThreadQueueImplForKLightLock(KernelCore& kernel_) : KThreadQueue(kernel_) {} + + virtual void CancelWait([[maybe_unused]] KThread* waiting_thread, + [[maybe_unused]] ResultCode wait_result, + [[maybe_unused]] bool cancel_timer_task) override { + // Do nothing, waiting to acquire a light lock cannot be canceled. + } +}; + +} // namespace + void KLightLock::Lock() { const uintptr_t cur_thread = reinterpret_cast(GetCurrentThreadPointer(kernel)); - const uintptr_t cur_thread_tag = (cur_thread | 1); while (true) { uintptr_t old_tag = tag.load(std::memory_order_relaxed); - while (!tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : old_tag | 1, + while (!tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), std::memory_order_acquire)) { - if ((old_tag | 1) == cur_thread_tag) { - return; - } } - if ((old_tag == 0) || ((old_tag | 1) == cur_thread_tag)) { + if (old_tag == 0 || this->LockSlowPath(old_tag | 1, cur_thread)) { break; } - - LockSlowPath(old_tag | 1, cur_thread); } } void KLightLock::Unlock() { const uintptr_t cur_thread = reinterpret_cast(GetCurrentThreadPointer(kernel)); + uintptr_t expected = cur_thread; - do { - if (expected != cur_thread) { - return UnlockSlowPath(cur_thread); - } - } while (!tag.compare_exchange_weak(expected, 0, std::memory_order_release)); + if (!tag.compare_exchange_strong(expected, 0, std::memory_order_release)) { + this->UnlockSlowPath(cur_thread); + } } -void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { +bool KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { KThread* cur_thread = reinterpret_cast(_cur_thread); + ThreadQueueImplForKLightLock wait_queue(kernel); // Pend the current thread waiting on the owner thread. { @@ -50,30 +60,23 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { // Ensure we actually have locking to do. if (tag.load(std::memory_order_relaxed) != _owner) { - return; + return false; } // Add the current thread as a waiter on the owner. - KThread* owner_thread = reinterpret_cast(_owner & ~1ULL); + KThread* owner_thread = reinterpret_cast(_owner & ~1ul); cur_thread->SetAddressKey(reinterpret_cast(std::addressof(tag))); owner_thread->AddWaiter(cur_thread); - // Set thread states. - cur_thread->SetState(ThreadState::Waiting); + // Begin waiting to hold the lock. + cur_thread->BeginWait(std::addressof(wait_queue)); if (owner_thread->IsSuspended()) { owner_thread->ContinueIfHasKernelWaiters(); } } - // We're no longer waiting on the lock owner. - { - KScopedSchedulerLock sl{kernel}; - - if (KThread* owner_thread = cur_thread->GetLockOwner(); owner_thread != nullptr) { - owner_thread->RemoveWaiter(cur_thread); - } - } + return true; } void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { @@ -81,22 +84,20 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { // Unlock. { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl(kernel); // Get the next owner. - s32 num_waiters = 0; + s32 num_waiters; KThread* next_owner = owner_thread->RemoveWaiterByKey( std::addressof(num_waiters), reinterpret_cast(std::addressof(tag))); // Pass the lock to the next owner. uintptr_t next_tag = 0; if (next_owner != nullptr) { - next_tag = reinterpret_cast(next_owner); - if (num_waiters > 1) { - next_tag |= 0x1; - } + next_tag = + reinterpret_cast(next_owner) | static_cast(num_waiters > 1); - next_owner->SetState(ThreadState::Runnable); + next_owner->EndWait(ResultSuccess); if (next_owner->IsSuspended()) { next_owner->ContinueIfHasKernelWaiters(); @@ -110,7 +111,7 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { } // Write the new tag value. - tag.store(next_tag); + tag.store(next_tag, std::memory_order_release); } } diff --git a/src/core/hle/kernel/k_light_lock.h b/src/core/hle/kernel/k_light_lock.h index ad853661d..4163b8a85 100644 --- a/src/core/hle/kernel/k_light_lock.h +++ b/src/core/hle/kernel/k_light_lock.h @@ -20,7 +20,7 @@ public: void Unlock(); - void LockSlowPath(uintptr_t owner, uintptr_t cur_thread); + bool LockSlowPath(uintptr_t owner, uintptr_t cur_thread); void UnlockSlowPath(uintptr_t cur_thread); -- cgit v1.2.3 From 5dff28290fc4fc9bc3db3c32476dd93b2c4414c6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 20:54:44 -0800 Subject: hle: kernel: KLightConditionVariable: Migrate to updated KThreadQueue. --- src/core/CMakeLists.txt | 1 + src/core/hle/kernel/k_light_condition_variable.cpp | 80 ++++++++++++++++++++++ src/core/hle/kernel/k_light_condition_variable.h | 60 ++-------------- 3 files changed, 87 insertions(+), 54 deletions(-) create mode 100644 src/core/hle/kernel/k_light_condition_variable.cpp (limited to 'src/core') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c42a29cc7..cd99b447b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -185,6 +185,7 @@ add_library(core STATIC hle/kernel/k_event.h hle/kernel/k_handle_table.cpp hle/kernel/k_handle_table.h + hle/kernel/k_light_condition_variable.cpp hle/kernel/k_light_condition_variable.h hle/kernel/k_light_lock.cpp hle/kernel/k_light_lock.h diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp new file mode 100644 index 000000000..9ff710084 --- /dev/null +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -0,0 +1,80 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/kernel/k_light_condition_variable.h" +#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" +#include "core/hle/kernel/k_thread_queue.h" +#include "core/hle/kernel/svc_results.h" + +namespace Kernel { + +namespace { + +class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { +private: + KThread::WaiterList* m_wait_list; + bool m_allow_terminating_thread; + +public: + ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl, + bool term) + : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {} + + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // Only process waits if we're allowed to. + if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { + return; + } + + // Remove the thread from the waiting thread from the light condition variable. + m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + } +}; + +} // namespace + +void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { + // Create thread queue. + KThread* owner = GetCurrentThreadPointer(kernel); + + ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list), + allow_terminating_thread); + + // Sleep the thread. + { + KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); + + if (!allow_terminating_thread && owner->IsTerminationRequested()) { + lk.CancelSleep(); + return; + } + + lock->Unlock(); + + // Add the thread to the queue. + wait_list.push_back(*owner); + + // Begin waiting. + owner->BeginWait(std::addressof(wait_queue)); + } + + // Re-acquire the lock. + lock->Lock(); +} + +void KLightConditionVariable::Broadcast() { + KScopedSchedulerLock lk(kernel); + + // Signal all threads. + for (auto it = wait_list.begin(); it != wait_list.end(); it = wait_list.erase(it)) { + it->EndWait(ResultSuccess); + } +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index fb0ad783a..65d3bc3e1 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -1,73 +1,25 @@ -// Copyright 2020 yuzu Emulator Project +// Copyright 2021 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphere, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. - #pragma once #include "common/common_types.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" -#include "core/hle/kernel/time_manager.h" +#include "core/hle/kernel/k_thread.h" namespace Kernel { + class KernelCore; +class KLightLock; class KLightConditionVariable { public: explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {} - void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) { - WaitImpl(lock, timeout, allow_terminating_thread); - } - - void Broadcast() { - KScopedSchedulerLock lk{kernel}; - - // Signal all threads. - for (auto& thread : wait_list) { - thread.SetState(ThreadState::Runnable); - } - } + void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true); + void Broadcast(); private: - void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { - KThread* owner = GetCurrentThreadPointer(kernel); - - // Sleep the thread. - { - KScopedSchedulerLockAndSleep lk{kernel, owner, timeout}; - - if (!allow_terminating_thread && owner->IsTerminationRequested()) { - lk.CancelSleep(); - return; - } - - lock->Unlock(); - - // Set the thread as waiting. - GetCurrentThread(kernel).SetState(ThreadState::Waiting); - - // Add the thread to the queue. - wait_list.push_back(GetCurrentThread(kernel)); - } - - // Remove the thread from the wait list. - { - KScopedSchedulerLock sl{kernel}; - - wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel))); - } - - // Cancel the task that the sleep setup. - kernel.TimeManager().UnscheduleTimeEvent(owner); - - // Re-acquire the lock. - lock->Lock(); - } - KernelCore& kernel; KThread::WaiterList wait_list{}; }; -- cgit v1.2.3 From e942d9754028850ea1f6b223e4f1b8da7b13c1c4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 21:02:29 -0800 Subject: hle: kernel: KServerSession: Migrate to updated KThreadQueue. --- src/core/hle/kernel/k_server_session.cpp | 3 +-- src/core/hle/kernel/svc.cpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 1f7220d48..d4e4a6b06 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -175,8 +175,7 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { { KScopedSchedulerLock lock(kernel); if (!context.IsThreadWaiting()) { - context.GetThread().Wakeup(); - context.GetThread().SetWaitResult(result); + context.GetThread().EndWait(result); } } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 50c6e513d..0e79e1be3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -31,6 +31,7 @@ #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" @@ -310,18 +311,24 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { auto& kernel = system.Kernel(); + // Create the wait queue. + KThreadQueue wait_queue(kernel); + auto thread = kernel.CurrentScheduler()->GetCurrentThread(); { KScopedSchedulerLock lock(kernel); - thread->SetState(ThreadState::Waiting); - thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + + // This is a synchronous request, so we should wait for our request to complete. + GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); + GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); { KScopedAutoObject session = kernel.CurrentProcess()->GetHandleTable().GetObject(handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); - session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); + session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), + system.CoreTiming()); } } -- cgit v1.2.3 From beb55cb90ee5a830240cd34ebf2ac236eeeb8653 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 21:28:09 -0800 Subject: hle: kernel: KConditionVariable: Migrate to updated KThreadQueue. --- src/core/hle/kernel/k_condition_variable.cpp | 67 +++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 9eacbed7e..34c1eae65 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -11,6 +11,7 @@ #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_common.h" #include "core/hle/kernel/svc_results.h" @@ -57,6 +58,48 @@ bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero return true; } +class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue { +public: + explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel_) + : KThreadQueue(kernel_) {} + + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // Remove the thread as a waiter from its owner. + waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + } +}; + +class ThreadQueueImplForKConditionVariableWaitConditionVariable final : public KThreadQueue { +private: + KConditionVariable::ThreadTree* m_tree; + +public: + explicit ThreadQueueImplForKConditionVariableWaitConditionVariable( + KernelCore& kernel_, KConditionVariable::ThreadTree* t) + : KThreadQueue(kernel_), m_tree(t) {} + + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // Remove the thread as a waiter from its owner. + if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { + owner->RemoveWaiter(waiting_thread); + } + + // If the thread is waiting on a condvar, remove it from the tree. + if (waiting_thread->IsWaitingForConditionVariable()) { + m_tree->erase(m_tree->iterator_to(*waiting_thread)); + waiting_thread->ClearConditionVariable(); + } + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + } +}; + } // namespace KConditionVariable::KConditionVariable(Core::System& system_) @@ -84,8 +127,7 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { next_value |= Svc::HandleWaitMask; } - next_owner_thread->SetWaitResult(ResultSuccess); - next_owner_thread->Wakeup(); + next_owner_thread->EndWait(ResultSuccess); } // Write the value to userspace. @@ -103,6 +145,7 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); + ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); // Wait for the address. { @@ -133,7 +176,9 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val // Update the lock. cur_thread->SetAddressKey(addr, value); owner_thread->AddWaiter(cur_thread); - cur_thread->SetState(ThreadState::Waiting); + + // Begin waiting. + cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); cur_thread->SetMutexWaitAddressForDebugging(addr); } @@ -178,8 +223,7 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { if (can_access) { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. - thread->SetWaitResult(ResultSuccess); - thread->Wakeup(); + thread->EndWait(ResultSuccess); } else { // Get the previous owner. KThread* owner_thread = kernel.CurrentProcess() @@ -194,14 +238,12 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { thread_to_close = owner_thread; } else { // The lock was tagged with a thread that doesn't exist. - thread->SetWaitResult(ResultInvalidState); - thread->Wakeup(); + thread->EndWait(ResultInvalidState); } } } else { // If the address wasn't accessible, note so. - thread->SetWaitResult(ResultInvalidCurrentMemory); - thread->Wakeup(); + thread->EndWait(ResultInvalidCurrentMemory); } return thread_to_close; @@ -259,6 +301,8 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { // Prepare to wait. KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); + ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( + kernel, std::addressof(thread_tree)); { KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; @@ -289,8 +333,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) } // Wake up the next owner. - next_owner_thread->SetWaitResult(ResultSuccess); - next_owner_thread->Wakeup(); + next_owner_thread->EndWait(ResultSuccess); } // Write to the cv key. @@ -315,7 +358,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) // If the timeout is non-zero, set the thread as waiting. if (timeout != 0) { - cur_thread->SetState(ThreadState::Waiting); + cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); cur_thread->SetMutexWaitAddressForDebugging(addr); } -- cgit v1.2.3 From b0671c7cfaa8bdb9704827af83be9223a5890f97 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 10 Nov 2021 22:28:30 -0800 Subject: hle: kernel: KThread: Migrate to updated KThreadQueue (part 1). --- src/core/hle/kernel/k_thread.cpp | 121 ++++++++++++++++++----------------- src/core/hle/kernel/k_thread.h | 4 +- src/core/hle/kernel/time_manager.cpp | 6 +- 3 files changed, 71 insertions(+), 60 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 2c1f29bad..995f0ca50 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -59,6 +59,35 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, namespace Kernel { +namespace { + +class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait { +public: + explicit ThreadQueueImplForKThreadSleep(KernelCore& kernel_) + : KThreadQueueWithoutEndWait(kernel_) {} +}; + +class ThreadQueueImplForKThreadSetProperty final : public KThreadQueue { +private: + KThread::WaiterList* m_wait_list; + +public: + explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel_, KThread::WaiterList* wl) + : KThreadQueue(kernel_), m_wait_list(wl) { // ... + } + + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // Remove the thread from the wait list. + m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + } +}; + +} // namespace + KThread::KThread(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {} KThread::~KThread() = default; @@ -274,11 +303,14 @@ void KThread::Finalize() { auto it = waiter_list.begin(); while (it != waiter_list.end()) { - // The thread shouldn't be a kernel waiter. + // Clear the lock owner it->SetLockOwner(nullptr); - it->SetWaitResult(ResultInvalidState); - it->Wakeup(); + + // Erase the waiter from our list. it = waiter_list.erase(it); + + // Cancel the thread's wait. + it->CancelWait(ResultInvalidState, true); } } @@ -295,15 +327,12 @@ bool KThread::IsSignaled() const { return signaled; } -void KThread::Wakeup() { - KScopedSchedulerLock sl{kernel}; +void KThread::OnTimer() { + ASSERT(kernel.GlobalSchedulerContext().IsLocked()); + // If we're waiting, cancel the wait. if (GetState() == ThreadState::Waiting) { - if (sleeping_queue != nullptr) { - sleeping_queue->EndWait(this, ResultSuccess); - } else { - SetState(ThreadState::Runnable); - } + sleeping_queue->CancelWait(this, ResultTimedOut, false); } } @@ -475,7 +504,6 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m return ResultSuccess; } - ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { ASSERT(parent != nullptr); ASSERT(v_affinity_mask != 0); @@ -642,15 +670,9 @@ void KThread::WaitCancel() { KScopedSchedulerLock sl{kernel}; // Check if we're waiting and cancellable. - if (GetState() == ThreadState::Waiting && cancellable) { - if (sleeping_queue != nullptr) { - sleeping_queue->WakeupThread(this); - wait_cancelled = true; - } else { - SetWaitResult(ResultCancelled); - SetState(ThreadState::Runnable); - wait_cancelled = false; - } + if (this->GetState() == ThreadState::Waiting && cancellable) { + wait_cancelled = false; + sleeping_queue->CancelWait(this, ResultCancelled, true); } else { // Otherwise, note that we cancelled a wait. wait_cancelled = true; @@ -701,60 +723,59 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) { // Set the activity. { // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl(kernel); // Verify our state. - const auto cur_state = GetState(); + const auto cur_state = this->GetState(); R_UNLESS((cur_state == ThreadState::Waiting || cur_state == ThreadState::Runnable), ResultInvalidState); // Either pause or resume. if (activity == Svc::ThreadActivity::Paused) { // Verify that we're not suspended. - R_UNLESS(!IsSuspendRequested(SuspendType::Thread), ResultInvalidState); + R_UNLESS(!this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Suspend. - RequestSuspend(SuspendType::Thread); + this->RequestSuspend(SuspendType::Thread); } else { ASSERT(activity == Svc::ThreadActivity::Runnable); // Verify that we're suspended. - R_UNLESS(IsSuspendRequested(SuspendType::Thread), ResultInvalidState); + R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Resume. - Resume(SuspendType::Thread); + this->Resume(SuspendType::Thread); } } // If the thread is now paused, update the pinned waiter list. if (activity == Svc::ThreadActivity::Paused) { - bool thread_is_pinned{}; - bool thread_is_current{}; + ThreadQueueImplForKThreadSetProperty wait_queue_(kernel, + std::addressof(pinned_waiter_list)); + + bool thread_is_current; do { // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl(kernel); // Don't do any further management if our termination has been requested. - R_SUCCEED_IF(IsTerminationRequested()); + R_SUCCEED_IF(this->IsTerminationRequested()); + + // By default, treat the thread as not current. + thread_is_current = false; // Check whether the thread is pinned. - if (GetStackParameters().is_pinned) { + if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); - // Note that the thread was pinned and not current. - thread_is_pinned = true; - thread_is_current = false; - // Wait until the thread isn't pinned any more. pinned_waiter_list.push_back(GetCurrentThread(kernel)); - GetCurrentThread(kernel).SetState(ThreadState::Waiting); + GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue_)); } else { // Check if the thread is currently running. // If it is, we'll need to retry. - thread_is_current = false; - for (auto i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { if (kernel.Scheduler(i).GetCurrentThread() == this) { thread_is_current = true; @@ -763,16 +784,6 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) { } } } while (thread_is_current); - - // If the thread was pinned, it no longer is, and we should remove the current thread from - // our waiter list. - if (thread_is_pinned) { - // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; - - // Remove from the list. - pinned_waiter_list.erase(pinned_waiter_list.iterator_to(GetCurrentThread(kernel))); - } } return ResultSuccess; @@ -1000,26 +1011,22 @@ ResultCode KThread::Sleep(s64 timeout) { ASSERT(this == GetCurrentThreadPointer(kernel)); ASSERT(timeout > 0); + ThreadQueueImplForKThreadSleep wait_queue(kernel); { // Setup the scheduling lock and sleep. - KScopedSchedulerLockAndSleep slp{kernel, this, timeout}; + KScopedSchedulerLockAndSleep slp(kernel, this, timeout); // Check if the thread should terminate. - if (IsTerminationRequested()) { + if (this->IsTerminationRequested()) { slp.CancelSleep(); return ResultTerminationRequested; } - // Mark the thread as waiting. - SetState(ThreadState::Waiting); + // Wait for the sleep to end. + this->BeginWait(std::addressof(wait_queue)); SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); } - // The lock/sleep is done. - - // Cancel the timer. - kernel.TimeManager().UnscheduleTimeEvent(this); - return ResultSuccess; } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index f9a324eb3..6d68c2399 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -161,8 +161,6 @@ public: } } - void Wakeup(); - void SetBasePriority(s32 value); [[nodiscard]] ResultCode Run(); @@ -380,6 +378,8 @@ public: [[nodiscard]] bool IsSignaled() const override; + void OnTimer(); + static void PostDestroy(uintptr_t arg); [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 8cd7279a3..aa985d820 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp @@ -5,6 +5,7 @@ #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" @@ -15,7 +16,10 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} { Core::Timing::CreateEvent("Kernel::TimeManagerCallback", [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) { KThread* thread = reinterpret_cast(thread_handle); - thread->Wakeup(); + { + KScopedSchedulerLock sl(system.Kernel()); + thread->OnTimer(); + } }); } -- cgit v1.2.3 From f62c7091a2bb0c70211b7424c4285906f5dccf4b Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 10 Nov 2021 22:46:07 -0800 Subject: hle: kernel: KThread: Migrate to updated KThreadQueue (part 2). --- src/core/hle/kernel/k_thread.cpp | 48 ++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 995f0ca50..7ef52a240 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -504,30 +504,33 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m return ResultSuccess; } -ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { + +ResultCode KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) { ASSERT(parent != nullptr); ASSERT(v_affinity_mask != 0); - KScopedLightLock lk{activity_pause_lock}; + KScopedLightLock lk(activity_pause_lock); // Set the core mask. u64 p_affinity_mask = 0; { - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl(kernel); ASSERT(num_core_migration_disables >= 0); - // If the core id is no-update magic, preserve the ideal core id. - if (cpu_core_id == Svc::IdealCoreNoUpdate) { - cpu_core_id = virtual_ideal_core_id; - R_UNLESS(((1ULL << cpu_core_id) & v_affinity_mask) != 0, ResultInvalidCombination); + // If we're updating, set our ideal virtual core. + if (core_id_ != Svc::IdealCoreNoUpdate) { + virtual_ideal_core_id = core_id_; + } else { + // Preserve our ideal core id. + core_id_ = virtual_ideal_core_id; + R_UNLESS(((1ULL << core_id_) & v_affinity_mask) != 0, ResultInvalidCombination); } - // Set the virtual core/affinity mask. - virtual_ideal_core_id = cpu_core_id; + // Set our affinity mask. virtual_affinity_mask = v_affinity_mask; // Translate the virtual core to a physical core. - if (cpu_core_id >= 0) { - cpu_core_id = Core::Hardware::VirtualToPhysicalCoreMap[cpu_core_id]; + if (core_id_ >= 0) { + core_id_ = Core::Hardware::VirtualToPhysicalCoreMap[core_id_]; } // Translate the virtual affinity mask to a physical one. @@ -542,7 +545,7 @@ ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { const KAffinityMask old_mask = physical_affinity_mask; // Set our new ideals. - physical_ideal_core_id = cpu_core_id; + physical_ideal_core_id = core_id_; physical_affinity_mask.SetAffinityMask(p_affinity_mask); if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) { @@ -560,18 +563,18 @@ ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { } } else { // Otherwise, we edit the original affinity for restoration later. - original_physical_ideal_core_id = cpu_core_id; + original_physical_ideal_core_id = core_id_; original_physical_affinity_mask.SetAffinityMask(p_affinity_mask); } } // Update the pinned waiter list. + ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(pinned_waiter_list)); { bool retry_update{}; - bool thread_is_pinned{}; do { // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl(kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(IsTerminationRequested()); @@ -599,12 +602,9 @@ ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); - // Note that the thread was pinned. - thread_is_pinned = true; - // Wait until the thread isn't pinned any more. pinned_waiter_list.push_back(GetCurrentThread(kernel)); - GetCurrentThread(kernel).SetState(ThreadState::Waiting); + GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); } else { // If the thread isn't pinned, release the scheduler lock and retry until it's // not current. @@ -612,16 +612,6 @@ ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { } } } while (retry_update); - - // If the thread was pinned, it no longer is, and we should remove the current thread from - // our waiter list. - if (thread_is_pinned) { - // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; - - // Remove from the list. - pinned_waiter_list.erase(pinned_waiter_list.iterator_to(GetCurrentThread(kernel))); - } } return ResultSuccess; -- cgit v1.2.3 From f3d6e31e7805711803d11607fd807f23715d3449 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 9 Nov 2021 22:06:49 -0800 Subject: hle: kernel: KConditionVariable: Various updates & simplifications. --- src/core/hle/kernel/k_condition_variable.cpp | 184 ++++++++++----------------- src/core/hle/kernel/k_condition_variable.h | 2 +- 2 files changed, 65 insertions(+), 121 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 34c1eae65..f343e3c2f 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -121,26 +121,31 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { // Determine the next tag. u32 next_value{}; - if (next_owner_thread) { + if (next_owner_thread != nullptr) { next_value = next_owner_thread->GetAddressKeyValue(); if (num_waiters > 1) { next_value |= Svc::HandleWaitMask; } - next_owner_thread->EndWait(ResultSuccess); - } - - // Write the value to userspace. - if (!WriteToUser(system, addr, std::addressof(next_value))) { - if (next_owner_thread) { - next_owner_thread->SetWaitResult(ResultInvalidCurrentMemory); + // Write the value to userspace. + ResultCode result{ResultSuccess}; + if (WriteToUser(system, addr, std::addressof(next_value))) [[likely]] { + result = ResultSuccess; + } else { + result = ResultInvalidCurrentMemory; } - return ResultInvalidCurrentMemory; + // Signal the next owner thread. + next_owner_thread->EndWait(result); + return result; + } else { + // Just write the value to userspace. + R_UNLESS(WriteToUser(system, addr, std::addressof(next_value)), + ResultInvalidCurrentMemory); + + return ResultSuccess; } } - - return ResultSuccess; } ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { @@ -148,58 +153,45 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); // Wait for the address. + KThread* owner_thread{}; { - KScopedAutoObject owner_thread; - ASSERT(owner_thread.IsNull()); - { - KScopedSchedulerLock sl(kernel); - cur_thread->SetWaitResult(ResultSuccess); + KScopedSchedulerLock sl(kernel); - // Check if the thread should terminate. - R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested); + // Check if the thread should terminate. + R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested); - { - // Read the tag from userspace. - u32 test_tag{}; - R_UNLESS(ReadFromUser(system, std::addressof(test_tag), addr), - ResultInvalidCurrentMemory); - - // If the tag isn't the handle (with wait mask), we're done. - R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), ResultSuccess); - - // Get the lock owner thread. - owner_thread = - kernel.CurrentProcess()->GetHandleTable().GetObjectWithoutPseudoHandle( - handle); - R_UNLESS(owner_thread.IsNotNull(), ResultInvalidHandle); - - // Update the lock. - cur_thread->SetAddressKey(addr, value); - owner_thread->AddWaiter(cur_thread); - - // Begin waiting. - cur_thread->BeginWait(std::addressof(wait_queue)); - cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); - cur_thread->SetMutexWaitAddressForDebugging(addr); - } - } - ASSERT(owner_thread.IsNotNull()); - } + // Read the tag from userspace. + u32 test_tag{}; + R_UNLESS(ReadFromUser(system, std::addressof(test_tag), addr), ResultInvalidCurrentMemory); - // Remove the thread as a waiter from the lock owner. - { - KScopedSchedulerLock sl(kernel); - KThread* owner_thread = cur_thread->GetLockOwner(); - if (owner_thread != nullptr) { - owner_thread->RemoveWaiter(cur_thread); - } + // If the tag isn't the handle (with wait mask), we're done. + R_SUCCEED_IF(test_tag != (handle | Svc::HandleWaitMask)); + + // Get the lock owner thread. + owner_thread = kernel.CurrentProcess() + ->GetHandleTable() + .GetObjectWithoutPseudoHandle(handle) + .ReleasePointerUnsafe(); + R_UNLESS(owner_thread != nullptr, ResultInvalidHandle); + + // Update the lock. + cur_thread->SetAddressKey(addr, value); + owner_thread->AddWaiter(cur_thread); + + // Begin waiting. + cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); + cur_thread->SetMutexWaitAddressForDebugging(addr); } + // Close our reference to the owner thread, now that the wait is over. + owner_thread->Close(); + // Get the wait result. return cur_thread->GetWaitResult(); } -KThread* KConditionVariable::SignalImpl(KThread* thread) { +void KConditionVariable::SignalImpl(KThread* thread) { // Check pre-conditions. ASSERT(kernel.GlobalSchedulerContext().IsLocked()); @@ -213,14 +205,13 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { // TODO(bunnei): We should disable interrupts here via KScopedInterruptDisable. // TODO(bunnei): We should call CanAccessAtomic(..) here. can_access = true; - if (can_access) { + if (can_access) [[likely]] { UpdateLockAtomic(system, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask); } } - KThread* thread_to_close = nullptr; - if (can_access) { + if (can_access) [[likely]] { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. thread->EndWait(ResultSuccess); @@ -232,10 +223,10 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { static_cast(prev_tag & ~Svc::HandleWaitMask)) .ReleasePointerUnsafe(); - if (owner_thread) { + if (owner_thread) [[likely]] { // Add the thread as a waiter on the owner. owner_thread->AddWaiter(thread); - thread_to_close = owner_thread; + owner_thread->Close(); } else { // The lock was tagged with a thread that doesn't exist. thread->EndWait(ResultInvalidState); @@ -245,20 +236,11 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { // If the address wasn't accessible, note so. thread->EndWait(ResultInvalidCurrentMemory); } - - return thread_to_close; } void KConditionVariable::Signal(u64 cv_key, s32 count) { - // Prepare for signaling. - constexpr int MaxThreads = 16; - - KLinkedList thread_list{kernel}; - std::array thread_array; - s32 num_to_close{}; - // Perform signaling. - s32 num_waiters{}; + int num_waiters = 0; { KScopedSchedulerLock sl(kernel); @@ -267,14 +249,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { (it->GetConditionVariableKey() == cv_key)) { KThread* target_thread = std::addressof(*it); - if (KThread* thread = SignalImpl(target_thread); thread != nullptr) { - if (num_to_close < MaxThreads) { - thread_array[num_to_close++] = thread; - } else { - thread_list.push_back(*thread); - } - } - + this->SignalImpl(target_thread); it = thread_tree.erase(it); target_thread->ClearConditionVariable(); ++num_waiters; @@ -282,33 +257,20 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // If we have no waiters, clear the has waiter flag. if (it == thread_tree.end() || it->GetConditionVariableKey() != cv_key) { - const u32 has_waiter_flag{}; + const u32 has_waiter_flag = 0; WriteToUser(system, cv_key, std::addressof(has_waiter_flag)); } } - - // Close threads in the array. - for (auto i = 0; i < num_to_close; ++i) { - thread_array[i]->Close(); - } - - // Close threads in the list. - for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) { - (*it).Close(); - } } ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); + KThread* cur_thread = GetCurrentThreadPointer(kernel); ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( kernel, std::addressof(thread_tree)); { - KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; - - // Set the synced object. - cur_thread->SetWaitResult(ResultTimedOut); + KScopedSchedulerLockAndSleep slp(kernel, cur_thread, timeout); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -350,38 +312,20 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) } } - // Update condition variable tracking. - { - cur_thread->SetConditionVariable(std::addressof(thread_tree), addr, key, value); - thread_tree.insert(*cur_thread); - } + // If timeout is zero, time out. + R_UNLESS(timeout != 0, ResultTimedOut); - // If the timeout is non-zero, set the thread as waiting. - if (timeout != 0) { - cur_thread->BeginWait(std::addressof(wait_queue)); - cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); - cur_thread->SetMutexWaitAddressForDebugging(addr); - } - } - - // Cancel the timer wait. - kernel.TimeManager().UnscheduleTimeEvent(cur_thread); - - // Remove from the condition variable. - { - KScopedSchedulerLock sl(kernel); - - if (KThread* owner = cur_thread->GetLockOwner(); owner != nullptr) { - owner->RemoveWaiter(cur_thread); - } + // Update condition variable tracking. + cur_thread->SetConditionVariable(std::addressof(thread_tree), addr, key, value); + thread_tree.insert(*cur_thread); - if (cur_thread->IsWaitingForConditionVariable()) { - thread_tree.erase(thread_tree.iterator_to(*cur_thread)); - cur_thread->ClearConditionVariable(); - } + // Begin waiting. + cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); + cur_thread->SetMutexWaitAddressForDebugging(addr); } - // Get the result. + // Get the wait result. return cur_thread->GetWaitResult(); } diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h index 861dbd420..5e4815d08 100644 --- a/src/core/hle/kernel/k_condition_variable.h +++ b/src/core/hle/kernel/k_condition_variable.h @@ -34,7 +34,7 @@ public: [[nodiscard]] ResultCode Wait(VAddr addr, u64 key, u32 value, s64 timeout); private: - [[nodiscard]] KThread* SignalImpl(KThread* thread); + void SignalImpl(KThread* thread); ThreadTree thread_tree; -- cgit v1.2.3 From 4c747611555068817f76e72b2cb9c7af99480d12 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 10 Nov 2021 22:53:19 -0800 Subject: hle: kernel: KThreadQueue: Remove deprecated code. --- src/core/hle/kernel/k_thread_queue.h | 63 ------------------------------------ 1 file changed, 63 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 74e76e7cb..fddf16e8b 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -20,69 +20,6 @@ public: virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, bool cancel_timer_task); - // Deprecated, will be removed in subsequent commits. -public: - bool IsEmpty() const { - return wait_list.empty(); - } - - KThread::WaiterList::iterator begin() { - return wait_list.begin(); - } - KThread::WaiterList::iterator end() { - return wait_list.end(); - } - - bool SleepThread(KThread* t) { - KScopedSchedulerLock sl{kernel}; - - // If the thread needs terminating, don't enqueue it. - if (t->IsTerminationRequested()) { - return false; - } - - // Set the thread's queue and mark it as waiting. - t->SetSleepingQueue(this); - t->SetState(ThreadState::Waiting); - - // Add the thread to the queue. - wait_list.push_back(*t); - - return true; - } - - void WakeupThread(KThread* t) { - KScopedSchedulerLock sl{kernel}; - - // Remove the thread from the queue. - wait_list.erase(wait_list.iterator_to(*t)); - - // Mark the thread as no longer sleeping. - t->SetState(ThreadState::Runnable); - t->SetSleepingQueue(nullptr); - } - - KThread* WakeupFrontThread() { - KScopedSchedulerLock sl{kernel}; - - if (wait_list.empty()) { - return nullptr; - } else { - // Remove the thread from the queue. - auto it = wait_list.begin(); - KThread* thread = std::addressof(*it); - wait_list.erase(it); - - ASSERT(thread->GetState() == ThreadState::Waiting); - - // Mark the thread as no longer sleeping. - thread->SetState(ThreadState::Runnable); - thread->SetSleepingQueue(nullptr); - - return thread; - } - } - private: KernelCore& kernel; KThread::WaiterList wait_list{}; -- cgit v1.2.3 From 316a2dd22a25e4cfb31b364ab6595d8bb054411c Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 10 Nov 2021 23:02:45 -0800 Subject: hle: kernel: KProcess: Improvements for thread pinning. --- src/core/hle/kernel/k_process.cpp | 27 ++++++++++++++++++++++----- src/core/hle/kernel/k_process.h | 7 ++++--- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 7cc2061ea..90dda40dc 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -228,12 +228,15 @@ void KProcess::PinCurrentThread() { const s32 core_id = GetCurrentCoreId(kernel); KThread* cur_thread = GetCurrentThreadPointer(kernel); - // Pin it. - PinThread(core_id, cur_thread); - cur_thread->Pin(); + // If the thread isn't terminated, pin it. + if (!cur_thread->IsTerminationRequested()) { + // Pin it. + PinThread(core_id, cur_thread); + cur_thread->Pin(); - // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(kernel); + // An update is needed. + KScheduler::SetSchedulerUpdateNeeded(kernel); + } } void KProcess::UnpinCurrentThread() { @@ -251,6 +254,20 @@ void KProcess::UnpinCurrentThread() { KScheduler::SetSchedulerUpdateNeeded(kernel); } +void KProcess::UnpinThread(KThread* thread) { + ASSERT(kernel.GlobalSchedulerContext().IsLocked()); + + // Get the thread's core id. + const auto core_id = thread->GetActiveCore(); + + // Unpin it. + UnpinThread(core_id, thread); + thread->Unpin(); + + // An update is needed. + KScheduler::SetSchedulerUpdateNeeded(kernel); +} + ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address, [[maybe_unused]] size_t size) { // Lock ourselves, to prevent concurrent access. diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 8a8c1fcbb..d972c9de0 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -259,7 +259,7 @@ public: [[nodiscard]] KThread* GetPinnedThread(s32 core_id) const { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); - return pinned_threads[core_id]; + return pinned_threads.at(core_id); } /// Gets 8 bytes of random data for svcGetInfo RandomEntropy @@ -347,6 +347,7 @@ public: void PinCurrentThread(); void UnpinCurrentThread(); + void UnpinThread(KThread* thread); KLightLock& GetStateLock() { return state_lock; @@ -368,14 +369,14 @@ private: void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); ASSERT(thread != nullptr); - ASSERT(pinned_threads[core_id] == nullptr); + ASSERT(pinned_threads.at(core_id) == nullptr); pinned_threads[core_id] = thread; } void UnpinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); ASSERT(thread != nullptr); - ASSERT(pinned_threads[core_id] == thread); + ASSERT(pinned_threads.at(core_id) == thread); pinned_threads[core_id] = nullptr; } -- cgit v1.2.3 From 8f4ff06c4cf807ff68619eb69cc69dc20659d6d6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 21 Nov 2021 02:29:53 -0800 Subject: hle: kernel: Cleanup to match coding style. --- src/core/hle/kernel/k_address_arbiter.cpp | 6 +++--- src/core/hle/kernel/k_light_condition_variable.cpp | 8 ++++---- src/core/hle/kernel/k_synchronization_object.cpp | 18 +++++++----------- src/core/hle/kernel/k_thread.cpp | 9 ++++----- src/core/hle/kernel/k_thread.h | 4 ++-- src/core/hle/kernel/k_thread_queue.h | 2 +- 6 files changed, 21 insertions(+), 26 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 165475fbf..a4ce99402 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -87,9 +87,6 @@ bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32 } class ThreadQueueImplForKAddressArbiter final : public KThreadQueue { -private: - KAddressArbiter::ThreadTree* m_tree; - public: explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel_, KAddressArbiter::ThreadTree* t) : KThreadQueue(kernel_), m_tree(t) {} @@ -105,6 +102,9 @@ public: // Invoke the base cancel wait handler. KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } + +private: + KAddressArbiter::ThreadTree* m_tree; }; } // namespace diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp index 9ff710084..7319a0ca0 100644 --- a/src/core/hle/kernel/k_light_condition_variable.cpp +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -13,10 +13,6 @@ namespace Kernel { namespace { class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { -private: - KThread::WaiterList* m_wait_list; - bool m_allow_terminating_thread; - public: ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl, bool term) @@ -35,6 +31,10 @@ public: // Invoke the base cancel wait handler. KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } + +private: + KThread::WaiterList* m_wait_list; + bool m_allow_terminating_thread; }; } // namespace diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index ba8fc4010..ffeb4b73f 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -17,19 +17,10 @@ namespace Kernel { namespace { class ThreadQueueImplForKSynchronizationObjectWait final : public KThreadQueueWithoutEndWait { -private: - using ThreadListNode = KSynchronizationObject::ThreadListNode; - -private: - KSynchronizationObject** m_objects; - ThreadListNode* m_nodes; - s32 m_count; - public: ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel_, KSynchronizationObject** o, - ThreadListNode* n, s32 c) - : KThreadQueueWithoutEndWait(kernel_), m_objects(o), m_nodes(n), m_count(c) { // ... - } + KSynchronizationObject::ThreadListNode* n, s32 c) + : KThreadQueueWithoutEndWait(kernel_), m_objects(o), m_nodes(n), m_count(c) {} virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, ResultCode wait_result) override { @@ -68,6 +59,11 @@ public: // Invoke the base cancel wait handler. KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } + +private: + KSynchronizationObject** m_objects; + KSynchronizationObject::ThreadListNode* m_nodes; + s32 m_count; }; } // namespace diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 7ef52a240..813b92ea4 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -68,13 +68,9 @@ public: }; class ThreadQueueImplForKThreadSetProperty final : public KThreadQueue { -private: - KThread::WaiterList* m_wait_list; - public: explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel_, KThread::WaiterList* wl) - : KThreadQueue(kernel_), m_wait_list(wl) { // ... - } + : KThreadQueue(kernel_), m_wait_list(wl) {} virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, bool cancel_timer_task) override { @@ -84,6 +80,9 @@ public: // Invoke the base cancel wait handler. KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } + +private: + KThread::WaiterList* m_wait_list; }; } // namespace diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 6d68c2399..1cde71e89 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -199,7 +199,7 @@ public: synced_index = index; } - constexpr s32 GetSyncedIndex() const { + [[nodiscard]] constexpr s32 GetSyncedIndex() const { return synced_index; } @@ -207,7 +207,7 @@ public: wait_result = wait_res; } - constexpr ResultCode GetWaitResult() const { + [[nodiscard]] constexpr ResultCode GetWaitResult() const { return wait_result; } diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index fddf16e8b..1f13cde83 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -12,7 +12,7 @@ namespace Kernel { class KThreadQueue { public: explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {} - virtual ~KThreadQueue(){}; + virtual ~KThreadQueue() = default; virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, ResultCode wait_result); -- cgit v1.2.3 From 2c49a65d2be9cc18bf6e72bb09ad4ce6a8e7588f Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 21 Nov 2021 02:30:16 -0800 Subject: hle: kernel: KSynchronizationObject: Fix variable shadowing. --- src/core/hle/kernel/k_synchronization_object.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index 789ff4780..ec235437b 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -35,18 +35,18 @@ public: [[nodiscard]] std::vector GetWaitingThreadsForDebugging() const; - void LinkNode(ThreadListNode* node) { + void LinkNode(ThreadListNode* node_) { // Link the node to the list. if (thread_list_tail == nullptr) { - thread_list_head = node; + thread_list_head = node_; } else { - thread_list_tail->next = node; + thread_list_tail->next = node_; } - thread_list_tail = node; + thread_list_tail = node_; } - void UnlinkNode(ThreadListNode* node) { + void UnlinkNode(ThreadListNode* node_) { // Unlink the node from the list. ThreadListNode* prev_ptr = reinterpret_cast(std::addressof(thread_list_head)); @@ -58,13 +58,13 @@ public: prev_ptr = prev_ptr->next; tail_prev = prev_val; prev_val = prev_ptr; - } while (prev_ptr != node); + } while (prev_ptr != node_); - if (thread_list_tail == node) { + if (thread_list_tail == node_) { thread_list_tail = tail_prev; } - prev->next = node->next; + prev->next = node_->next; } protected: -- cgit v1.2.3 From abbea575cfcc9e933fbe8f277a5e9f754deb669d Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 25 Nov 2021 20:46:17 -0800 Subject: hle: kernel: Add a flag for indicating that the kernel is currently shutting down. --- src/core/hle/kernel/k_scheduler.cpp | 10 ++++++++++ src/core/hle/kernel/k_scheduler_lock.h | 10 ++++++++++ src/core/hle/kernel/k_thread.cpp | 5 +++++ src/core/hle/kernel/k_thread.h | 4 ++++ src/core/hle/kernel/kernel.cpp | 18 ++++++++++++++++++ src/core/hle/kernel/kernel.h | 2 ++ 6 files changed, 49 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 6ddbae52c..5423b187e 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -376,11 +376,21 @@ void KScheduler::ClearSchedulerUpdateNeeded(KernelCore& kernel) { } void KScheduler::DisableScheduling(KernelCore& kernel) { + // If we are shutting down the kernel, none of this is relevant anymore. + if (kernel.IsShuttingDown()) { + return; + } + ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 0); GetCurrentThreadPointer(kernel)->DisableDispatch(); } void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) { + // If we are shutting down the kernel, none of this is relevant anymore. + if (kernel.IsShuttingDown()) { + return; + } + ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 1); if (GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() > 1) { diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h index c571f2992..93c47f1b1 100644 --- a/src/core/hle/kernel/k_scheduler_lock.h +++ b/src/core/hle/kernel/k_scheduler_lock.h @@ -23,6 +23,11 @@ public: } void Lock() { + // If we are shutting down the kernel, none of this is relevant anymore. + if (kernel.IsShuttingDown()) { + return; + } + if (IsLockedByCurrentThread()) { // If we already own the lock, we can just increment the count. ASSERT(lock_count > 0); @@ -43,6 +48,11 @@ public: } void Unlock() { + // If we are shutting down the kernel, none of this is relevant anymore. + if (kernel.IsShuttingDown()) { + return; + } + ASSERT(IsLockedByCurrentThread()); ASSERT(lock_count > 0); diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 813b92ea4..f69978caf 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -1089,6 +1089,11 @@ s32 GetCurrentCoreId(KernelCore& kernel) { } KScopedDisableDispatch::~KScopedDisableDispatch() { + // If we are shutting down the kernel, none of this is relevant anymore. + if (kernel.IsShuttingDown()) { + return; + } + if (GetCurrentThread(kernel).GetDisableDispatchCount() <= 1) { auto scheduler = kernel.CurrentScheduler(); diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 1cde71e89..be1bc59ae 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -794,6 +794,10 @@ public: class KScopedDisableDispatch { public: [[nodiscard]] explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} { + // If we are shutting down the kernel, none of this is relevant anymore. + if (kernel.IsShuttingDown()) { + return; + } GetCurrentThread(kernel).DisableDispatch(); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index cf155ff66..1a47d4716 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -14,6 +14,7 @@ #include "common/assert.h" #include "common/logging/log.h" #include "common/microprofile.h" +#include "common/scope_exit.h" #include "common/thread.h" #include "common/thread_worker.h" #include "core/arm/arm_interface.h" @@ -90,6 +91,9 @@ struct KernelCore::Impl { } void Shutdown() { + is_shutting_down.store(true, std::memory_order_relaxed); + SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); }); + process_list.clear(); // Close all open server ports. @@ -338,7 +342,16 @@ struct KernelCore::Impl { is_phantom_mode_for_singlecore = value; } + bool IsShuttingDown() const { + return is_shutting_down.load(std::memory_order_relaxed); + } + KThread* GetCurrentEmuThread() { + // If we are shutting down the kernel, none of this is relevant anymore. + if (IsShuttingDown()) { + return {}; + } + const auto thread_id = GetCurrentHostThreadID(); if (thread_id >= Core::Hardware::NUM_CPU_CORES) { return GetHostDummyThread(); @@ -754,6 +767,7 @@ struct KernelCore::Impl { std::vector> dummy_threads; bool is_multicore{}; + std::atomic_bool is_shutting_down{}; bool is_phantom_mode_for_singlecore{}; u32 single_core_thread_id{}; @@ -1066,6 +1080,10 @@ bool KernelCore::IsMulticore() const { return impl->is_multicore; } +bool KernelCore::IsShuttingDown() const { + return impl->IsShuttingDown(); +} + void KernelCore::ExceptionalExit() { exception_exited = true; Suspend(true); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3499f8b90..eacf9dc61 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -274,6 +274,8 @@ public: bool IsMulticore() const; + bool IsShuttingDown() const; + void EnterSVCProfile(); void ExitSVCProfile(); -- cgit v1.2.3 From 3c2a451f47c54cb39870f8f106edbdd09b3a458d Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Fri, 26 Nov 2021 18:15:43 +0100 Subject: hle: kernel: fix scheduling ops from HLE host thread. --- src/core/hle/kernel/k_scheduler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 5423b187e..d3b1b2419 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -240,8 +240,8 @@ void KScheduler::OnThreadPriorityChanged(KernelCore& kernel, KThread* thread, s3 // If the thread is runnable, we want to change its priority in the queue. if (thread->GetRawState() == ThreadState::Runnable) { - GetPriorityQueue(kernel).ChangePriority( - old_priority, thread == kernel.CurrentScheduler()->GetCurrentThread(), thread); + GetPriorityQueue(kernel).ChangePriority(old_priority, + thread == kernel.GetCurrentEmuThread(), thread); IncrementScheduledCount(thread); SetSchedulerUpdateNeeded(kernel); } @@ -360,7 +360,7 @@ void KScheduler::RotateScheduledQueue(s32 cpu_core_id, s32 priority) { } bool KScheduler::CanSchedule(KernelCore& kernel) { - return kernel.CurrentScheduler()->GetCurrentThread()->GetDisableDispatchCount() <= 1; + return kernel.GetCurrentEmuThread()->GetDisableDispatchCount() <= 1; } bool KScheduler::IsSchedulerUpdateNeeded(const KernelCore& kernel) { -- cgit v1.2.3 From 894ed14ebc0ca938f2f240f37a5d8f1eda4cd66f Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Fri, 26 Nov 2021 18:16:54 +0100 Subject: hle: kernel: fix timing on thread preemption --- src/core/hle/kernel/kernel.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1a47d4716..2e4e4cb1c 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -251,13 +251,11 @@ struct KernelCore::Impl { KScopedSchedulerLock lock(kernel); global_scheduler_context->PreemptThreads(); } - const auto time_interval = std::chrono::nanoseconds{ - Core::Timing::msToCycles(std::chrono::milliseconds(10))}; + const auto time_interval = std::chrono::nanoseconds{std::chrono::milliseconds(10)}; system.CoreTiming().ScheduleEvent(time_interval, preemption_event); }); - const auto time_interval = - std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))}; + const auto time_interval = std::chrono::nanoseconds{std::chrono::milliseconds(10)}; system.CoreTiming().ScheduleEvent(time_interval, preemption_event); } -- cgit v1.2.3 From 0d9afdedc4ef9c0861739b04fc9a53926305e1f3 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 26 Nov 2021 15:10:21 -0800 Subject: hle: kernel: k_thread: Treat dummy threads as a special type. --- src/core/hle/kernel/k_thread.cpp | 4 +++- src/core/hle/kernel/k_thread.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index f69978caf..334487d8a 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -113,6 +113,8 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s [[fallthrough]]; case ThreadType::HighPriority: [[fallthrough]]; + case ThreadType::Dummy: + [[fallthrough]]; case ThreadType::User: ASSERT(((owner == nullptr) || (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); @@ -248,7 +250,7 @@ ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uint } ResultCode KThread::InitializeDummyThread(KThread* thread) { - return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Main); + return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Dummy); } ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index be1bc59ae..94b87bef1 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -48,6 +48,7 @@ enum class ThreadType : u32 { Kernel = 1, HighPriority = 2, User = 3, + Dummy = 100, // Special thread type for emulation purposes only }; DECLARE_ENUM_FLAG_OPERATORS(ThreadType); -- cgit v1.2.3 From e3d156ab0e020ade2a96ae82eba226d5f187aa2e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 26 Nov 2021 15:35:11 -0800 Subject: hle: kernel: svc: Fix deadlock that can occur with single core. --- src/core/hle/kernel/svc.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 0e79e1be3..359cf515d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -308,12 +308,18 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, /// Makes a blocking IPC call to an OS service. static ResultCode SendSyncRequest(Core::System& system, Handle handle) { - auto& kernel = system.Kernel(); // Create the wait queue. KThreadQueue wait_queue(kernel); + // Get the client session from its handle. + KScopedAutoObject session = + kernel.CurrentProcess()->GetHandleTable().GetObject(handle); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); + + LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); + auto thread = kernel.CurrentScheduler()->GetCurrentThread(); { KScopedSchedulerLock lock(kernel); @@ -321,15 +327,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { // This is a synchronous request, so we should wait for our request to complete. GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - - { - KScopedAutoObject session = - kernel.CurrentProcess()->GetHandleTable().GetObject(handle); - R_UNLESS(session.IsNotNull(), ResultInvalidHandle); - LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); - session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), - system.CoreTiming()); - } + session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming()); } return thread->GetWaitResult(); -- cgit v1.2.3 From 42697527ba6e981237f03f850826b5e722917414 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 28 Nov 2021 00:40:25 -0800 Subject: hle: kernel: k_thread: Rename sleeping_queue -> wait_queue. --- src/core/hle/kernel/k_thread.cpp | 22 +++++++++++----------- src/core/hle/kernel/k_thread.h | 8 ++------ 2 files changed, 13 insertions(+), 17 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 334487d8a..245437387 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -161,7 +161,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s base_priority = prio; // Initialize sleeping queue. - sleeping_queue = nullptr; + wait_queue = nullptr; // Set suspend flags. suspend_request_flags = 0; @@ -333,7 +333,7 @@ void KThread::OnTimer() { // If we're waiting, cancel the wait. if (GetState() == ThreadState::Waiting) { - sleeping_queue->CancelWait(this, ResultTimedOut, false); + wait_queue->CancelWait(this, ResultTimedOut, false); } } @@ -570,7 +570,7 @@ ResultCode KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) { } // Update the pinned waiter list. - ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(pinned_waiter_list)); + ThreadQueueImplForKThreadSetProperty wait_queue_(kernel, std::addressof(pinned_waiter_list)); { bool retry_update{}; do { @@ -605,7 +605,7 @@ ResultCode KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) { // Wait until the thread isn't pinned any more. pinned_waiter_list.push_back(GetCurrentThread(kernel)); - GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); + GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue_)); } else { // If the thread isn't pinned, release the scheduler lock and retry until it's // not current. @@ -663,7 +663,7 @@ void KThread::WaitCancel() { // Check if we're waiting and cancellable. if (this->GetState() == ThreadState::Waiting && cancellable) { wait_cancelled = false; - sleeping_queue->CancelWait(this, ResultCancelled, true); + wait_queue->CancelWait(this, ResultCancelled, true); } else { // Otherwise, note that we cancelled a wait. wait_cancelled = true; @@ -1002,7 +1002,7 @@ ResultCode KThread::Sleep(s64 timeout) { ASSERT(this == GetCurrentThreadPointer(kernel)); ASSERT(timeout > 0); - ThreadQueueImplForKThreadSleep wait_queue(kernel); + ThreadQueueImplForKThreadSleep wait_queue_(kernel); { // Setup the scheduling lock and sleep. KScopedSchedulerLockAndSleep slp(kernel, this, timeout); @@ -1014,7 +1014,7 @@ ResultCode KThread::Sleep(s64 timeout) { } // Wait for the sleep to end. - this->BeginWait(std::addressof(wait_queue)); + this->BeginWait(std::addressof(wait_queue_)); SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); } @@ -1026,7 +1026,7 @@ void KThread::BeginWait(KThreadQueue* queue) { SetState(ThreadState::Waiting); // Set our wait queue. - sleeping_queue = queue; + wait_queue = queue; } void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { @@ -1035,7 +1035,7 @@ void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCod // If we're waiting, notify our queue that we're available. if (GetState() == ThreadState::Waiting) { - sleeping_queue->NotifyAvailable(this, signaled_object, wait_result_); + wait_queue->NotifyAvailable(this, signaled_object, wait_result_); } } @@ -1045,7 +1045,7 @@ void KThread::EndWait(ResultCode wait_result_) { // If we're waiting, notify our queue that we're available. if (GetState() == ThreadState::Waiting) { - sleeping_queue->EndWait(this, wait_result_); + wait_queue->EndWait(this, wait_result_); } } @@ -1055,7 +1055,7 @@ void KThread::CancelWait(ResultCode wait_result_, bool cancel_timer_task) { // If we're waiting, notify our queue that we're available. if (GetState() == ThreadState::Waiting) { - sleeping_queue->CancelWait(this, wait_result_, cancel_timer_task); + wait_queue->CancelWait(this, wait_result_, cancel_timer_task); } } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 94b87bef1..c8a08bd71 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -453,10 +453,6 @@ public: return per_core_priority_queue_entry[core]; } - void SetSleepingQueue(KThreadQueue* q) { - sleeping_queue = q; - } - [[nodiscard]] bool IsKernelThread() const { return GetActiveCore() == 3; } @@ -604,7 +600,7 @@ public: } void ClearWaitQueue() { - sleeping_queue = nullptr; + wait_queue = nullptr; } void BeginWait(KThreadQueue* queue); @@ -715,7 +711,7 @@ private: s64 schedule_count{}; s64 last_scheduled_tick{}; std::array per_core_priority_queue_entry{}; - KThreadQueue* sleeping_queue{}; + KThreadQueue* wait_queue{}; WaiterList waiter_list{}; WaiterList pinned_waiter_list{}; KThread* lock_owner{}; -- cgit v1.2.3 From a2384a18fad1d7541c0e11b3c6d762aa46cd1b15 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 28 Nov 2021 00:40:50 -0800 Subject: hle: kernel: k_thread: Skip reschedule on DisableDispatch with SC. --- src/core/hle/kernel/k_thread.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 245437387..03175e5c2 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -1096,6 +1096,11 @@ KScopedDisableDispatch::~KScopedDisableDispatch() { return; } + // Skip the reschedule if single-core, as dispatch tracking is disabled here. + if (!Settings::values.use_multi_core.GetValue()) { + return; + } + if (GetCurrentThread(kernel).GetDisableDispatchCount() <= 1) { auto scheduler = kernel.CurrentScheduler(); -- cgit v1.2.3 From efb5de1c5f1c26de7d8346caf4bf09cc48f9906a Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 28 Nov 2021 13:05:18 -0800 Subject: hle: kernel: service_thread: Use std::jthread. - Fixes a potential deadlock on service thread shutdown. --- src/core/hle/kernel/service_thread.cpp | 37 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index 6721b6276..00657bc4c 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp @@ -25,24 +25,27 @@ public: void QueueSyncRequest(KSession& session, std::shared_ptr&& context); private: - std::vector threads; + std::vector threads; std::queue> requests; std::mutex queue_mutex; - std::condition_variable condition; + std::condition_variable_any condition; const std::string service_name; - bool stop{}; }; ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name) : service_name{name} { - for (std::size_t i = 0; i < num_threads; ++i) - threads.emplace_back([this, &kernel] { + for (std::size_t i = 0; i < num_threads; ++i) { + threads.emplace_back([this, &kernel](std::stop_token stop_token) { Common::SetCurrentThreadName(std::string{"yuzu:HleService:" + service_name}.c_str()); // Wait for first request before trying to acquire a render context { std::unique_lock lock{queue_mutex}; - condition.wait(lock, [this] { return stop || !requests.empty(); }); + condition.wait(lock, stop_token, [this] { return !requests.empty(); }); + } + + if (stop_token.stop_requested()) { + return; } kernel.RegisterHostThread(); @@ -52,10 +55,16 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std { std::unique_lock lock{queue_mutex}; - condition.wait(lock, [this] { return stop || !requests.empty(); }); - if (stop || requests.empty()) { + condition.wait(lock, stop_token, [this] { return !requests.empty(); }); + + if (stop_token.stop_requested()) { return; } + + if (requests.empty()) { + continue; + } + task = std::move(requests.front()); requests.pop(); } @@ -63,6 +72,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std task(); } }); + } } void ServiceThread::Impl::QueueSyncRequest(KSession& session, @@ -87,16 +97,7 @@ void ServiceThread::Impl::QueueSyncRequest(KSession& session, condition.notify_one(); } -ServiceThread::Impl::~Impl() { - { - std::unique_lock lock{queue_mutex}; - stop = true; - } - condition.notify_all(); - for (std::thread& thread : threads) { - thread.join(); - } -} +ServiceThread::Impl::~Impl() = default; ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name) : impl{std::make_unique(kernel, num_threads, name)} {} -- cgit v1.2.3 From e596fac6ee174d9e232c1a2291dfb8e8b5825aba Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:36:15 -0800 Subject: hle: kernel: k_light_lock: Implement CancelWait. - Fixes a crash in Megadimension Neptunia VII. --- src/core/hle/kernel/k_light_lock.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index 5e8f1a510..9830506ff 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -16,10 +16,15 @@ class ThreadQueueImplForKLightLock final : public KThreadQueue { public: explicit ThreadQueueImplForKLightLock(KernelCore& kernel_) : KThreadQueue(kernel_) {} - virtual void CancelWait([[maybe_unused]] KThread* waiting_thread, - [[maybe_unused]] ResultCode wait_result, - [[maybe_unused]] bool cancel_timer_task) override { - // Do nothing, waiting to acquire a light lock cannot be canceled. + virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { + // Remove the thread as a waiter from its owner. + if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { + owner->RemoveWaiter(waiting_thread); + } + + // Invoke the base cancel wait handler. + KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); } }; @@ -64,7 +69,7 @@ bool KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { } // Add the current thread as a waiter on the owner. - KThread* owner_thread = reinterpret_cast(_owner & ~1ul); + KThread* owner_thread = reinterpret_cast(_owner & ~1ULL); cur_thread->SetAddressKey(reinterpret_cast(std::addressof(tag))); owner_thread->AddWaiter(cur_thread); -- cgit v1.2.3 From d7f6d516cefed79dea14465abd7c2a0f036f78b9 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:42:58 -0800 Subject: hle: kernel: service_thread: Force stop threads on destruction. --- src/core/hle/kernel/service_thread.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index 00657bc4c..03f3dec10 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp @@ -97,7 +97,13 @@ void ServiceThread::Impl::QueueSyncRequest(KSession& session, condition.notify_one(); } -ServiceThread::Impl::~Impl() = default; +ServiceThread::Impl::~Impl() { + condition.notify_all(); + for (auto& thread : threads) { + thread.request_stop(); + thread.join(); + } +} ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name) : impl{std::make_unique(kernel, num_threads, name)} {} -- cgit v1.2.3 From 0d1bdfc1d4f9cb9ceecdb2dd9c784a664f6ba0c8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:49:26 -0800 Subject: hle: kernel: Remove unnecessary virtual specifier on CancelWait. --- src/core/hle/kernel/k_address_arbiter.cpp | 4 ++-- src/core/hle/kernel/k_condition_variable.cpp | 8 ++++---- src/core/hle/kernel/k_light_condition_variable.cpp | 4 ++-- src/core/hle/kernel/k_light_lock.cpp | 4 ++-- src/core/hle/kernel/k_synchronization_object.cpp | 4 ++-- src/core/hle/kernel/k_thread.cpp | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index a4ce99402..783c69858 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -91,8 +91,8 @@ public: explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel_, KAddressArbiter::ThreadTree* t) : KThreadQueue(kernel_), m_tree(t) {} - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // If the thread is waiting on an address arbiter, remove it from the tree. if (waiting_thread->IsWaitingForAddressArbiter()) { m_tree->erase(m_tree->iterator_to(*waiting_thread)); diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index f343e3c2f..fcfb74ec1 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -63,8 +63,8 @@ public: explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel_) : KThreadQueue(kernel_) {} - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); @@ -82,8 +82,8 @@ public: KernelCore& kernel_, KConditionVariable::ThreadTree* t) : KThreadQueue(kernel_), m_tree(t) {} - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { owner->RemoveWaiter(waiting_thread); diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp index 7319a0ca0..a8001fffc 100644 --- a/src/core/hle/kernel/k_light_condition_variable.cpp +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -18,8 +18,8 @@ public: bool term) : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {} - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // Only process waits if we're allowed to. if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { return; diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index 9830506ff..4620342eb 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -16,8 +16,8 @@ class ThreadQueueImplForKLightLock final : public KThreadQueue { public: explicit ThreadQueueImplForKLightLock(KernelCore& kernel_) : KThreadQueue(kernel_) {} - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { owner->RemoveWaiter(waiting_thread); diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index ffeb4b73f..6ae93b0ad 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -46,8 +46,8 @@ public: KThreadQueue::EndWait(waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // Remove all nodes from our list. for (auto i = 0; i < m_count; ++i) { m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 03175e5c2..752592e2e 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -72,8 +72,8 @@ public: explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel_, KThread::WaiterList* wl) : KThreadQueue(kernel_), m_wait_list(wl) {} - virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, - bool cancel_timer_task) override { + void CancelWait(KThread* waiting_thread, ResultCode wait_result, + bool cancel_timer_task) override { // Remove the thread from the wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); -- cgit v1.2.3 From 2e8d737a96f2326fe773ff29d2103d3a38c62df1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:51:24 -0800 Subject: hle: kernel: k_condition_variable: Revert unnecessary style changes. --- src/core/hle/kernel/k_condition_variable.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index fcfb74ec1..aadcc297a 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -240,7 +240,7 @@ void KConditionVariable::SignalImpl(KThread* thread) { void KConditionVariable::Signal(u64 cv_key, s32 count) { // Perform signaling. - int num_waiters = 0; + s32 num_waiters{}; { KScopedSchedulerLock sl(kernel); @@ -257,7 +257,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // If we have no waiters, clear the has waiter flag. if (it == thread_tree.end() || it->GetConditionVariableKey() != cv_key) { - const u32 has_waiter_flag = 0; + const u32 has_waiter_flag{}; WriteToUser(system, cv_key, std::addressof(has_waiter_flag)); } } -- cgit v1.2.3 From 3f8eb44e7d9c5ec97cf7c032f92ed3fa34b5ebaa Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:52:38 -0800 Subject: hle: kernel: k_light_condition_variable: Revert unnecessary license comment changes. --- src/core/hle/kernel/k_light_condition_variable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index 65d3bc3e1..5d6d7f128 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -1,4 +1,4 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2020 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -- cgit v1.2.3 From a63af9860b428b09aa9baf023334d6d1080094f7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:53:51 -0800 Subject: hle: kernel: Remove unnecessary virtual specifier on EndWait. --- src/core/hle/kernel/k_thread_queue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 1f13cde83..ccb718e49 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -29,7 +29,7 @@ class KThreadQueueWithoutEndWait : public KThreadQueue { public: explicit KThreadQueueWithoutEndWait(KernelCore& kernel_) : KThreadQueue(kernel_) {} - virtual void EndWait(KThread* waiting_thread, ResultCode wait_result) override final; + void EndWait(KThread* waiting_thread, ResultCode wait_result) override final; }; } // namespace Kernel -- cgit v1.2.3 From 834c25f4d95c99c614e72b5c342a8a84eb20d7aa Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:54:35 -0800 Subject: hle: kernel: Remove unnecessary virtual specifier on NotifyAvailable. --- src/core/hle/kernel/k_synchronization_object.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 6ae93b0ad..e4c5eb74f 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -22,8 +22,8 @@ public: KSynchronizationObject::ThreadListNode* n, s32 c) : KThreadQueueWithoutEndWait(kernel_), m_objects(o), m_nodes(n), m_count(c) {} - virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - ResultCode wait_result) override { + void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, + ResultCode wait_result) override { // Determine the sync index, and unlink all nodes. s32 sync_index = -1; for (auto i = 0; i < m_count; ++i) { -- cgit v1.2.3 From 9a9e7dd78ba12908a5c9ae0691c549783251ce53 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:57:09 -0800 Subject: hle: kernel k_process: Remove unnecessary .at usage with thread pinning methods. --- src/core/hle/kernel/k_process.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index d972c9de0..cb93c7e24 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -259,7 +259,7 @@ public: [[nodiscard]] KThread* GetPinnedThread(s32 core_id) const { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); - return pinned_threads.at(core_id); + return pinned_threads[core_id]; } /// Gets 8 bytes of random data for svcGetInfo RandomEntropy @@ -369,14 +369,14 @@ private: void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); ASSERT(thread != nullptr); - ASSERT(pinned_threads.at(core_id) == nullptr); + ASSERT(pinned_threads[core_id] == nullptr); pinned_threads[core_id] = thread; } void UnpinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); ASSERT(thread != nullptr); - ASSERT(pinned_threads.at(core_id) == thread); + ASSERT(pinned_threads[core_id] == thread); pinned_threads[core_id] = nullptr; } -- cgit v1.2.3 From 257d3c9ecf2730fad3b68918f108fa652061cabd Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 5 Dec 2021 23:59:23 -0800 Subject: hle: kernel k_scheduler: EnableScheduling: Remove redundant GetCurrentThreadPointer calls. --- src/core/hle/kernel/k_scheduler.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index d3b1b2419..277201de4 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -391,10 +391,12 @@ void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduli return; } - ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 1); + auto* current_thread = GetCurrentThreadPointer(kernel); - if (GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() > 1) { - GetCurrentThreadPointer(kernel)->EnableDispatch(); + ASSERT(current_thread->GetDisableDispatchCount() >= 1); + + if (current_thread->GetDisableDispatchCount() > 1) { + current_thread->EnableDispatch(); } else { RescheduleCores(kernel, cores_needing_scheduling); } -- cgit v1.2.3 From d19724688022952c37143dc189240916910b0c6f Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Tue, 7 Dec 2021 07:58:33 -0500 Subject: make KCodeMemory::GetSourceAddress const Co-authored-by: Mai M. --- src/core/hle/kernel/k_code_memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index e8e83a0e5..c45939afa 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -46,7 +46,7 @@ public: KProcess* GetOwner() const { return m_owner; } - VAddr GetSourceAddress() { + VAddr GetSourceAddress() const { return m_address; } size_t GetSize() const { -- cgit v1.2.3 From e05c86aa3cbd7a0da638111d2520b93b7f757f22 Mon Sep 17 00:00:00 2001 From: itsmeft24 <57544858+itsmeft24@users.noreply.github.com> Date: Tue, 7 Dec 2021 16:58:23 -0500 Subject: Update k_code_memory.h --- src/core/hle/kernel/k_code_memory.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index c45939afa..e0ba19a53 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -54,13 +54,13 @@ public: } private: - KPageLinkedList m_page_group; - KProcess* m_owner; - VAddr m_address; + KPageLinkedList m_page_group{}; + KProcess* m_owner{}; + VAddr m_address{}; KLightLock m_lock; - bool m_is_initialized; - bool m_is_owner_mapped; - bool m_is_mapped; + bool m_is_initialized{}; + bool m_is_owner_mapped{}; + bool m_is_mapped{}; }; } // namespace Kernel -- cgit v1.2.3 From 04301e1a8a825069ebda5eec850b3056d4b45cc8 Mon Sep 17 00:00:00 2001 From: Valeri Date: Mon, 13 Dec 2021 16:49:01 +0300 Subject: Remove erroneous #pragma once --- src/core/hle/kernel/k_thread_queue.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp index 46f27172b..d5248b547 100644 --- a/src/core/hle/kernel/k_thread_queue.cpp +++ b/src/core/hle/kernel/k_thread_queue.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#pragma once - #include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/time_manager.h" -- cgit v1.2.3 From e05d2a70b24e550d67fcdd24aae7094ad41745f8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 13 Dec 2021 21:09:28 -0500 Subject: common/input: Avoid numerous large copies of CallbackStatus CallbackStatus instances aren't the cheapest things to copy around (relative to everything else), given that they're currently 520 bytes in size and are currently copied numerous times when callbacks are invoked. Instead, we can pass the status by const reference to avoid all the copying. --- src/core/hid/emulated_console.cpp | 21 ++++---- src/core/hid/emulated_console.h | 4 +- src/core/hid/emulated_controller.cpp | 95 ++++++++++++++++++++---------------- src/core/hid/emulated_controller.h | 13 +++-- src/core/hid/emulated_devices.cpp | 66 ++++++++++++++----------- src/core/hid/emulated_devices.h | 11 ++--- 6 files changed, 118 insertions(+), 92 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 80db8e9c6..685ec080c 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -66,9 +66,10 @@ void EmulatedConsole::ReloadInput() { motion_devices = Common::Input::CreateDevice(motion_params); if (motion_devices) { - Common::Input::InputCallback motion_callback{ - [this](Common::Input::CallbackStatus callback) { SetMotion(callback); }}; - motion_devices->SetCallback(motion_callback); + motion_devices->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback) { SetMotion(callback); }, + }); } // Unique index for identifying touch device source @@ -78,9 +79,12 @@ void EmulatedConsole::ReloadInput() { if (!touch_device) { continue; } - Common::Input::InputCallback touch_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetTouch(callback, index); }}; - touch_device->SetCallback(touch_callback); + touch_device->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetTouch(callback, index); + }, + }); index++; } } @@ -127,7 +131,7 @@ void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { ReloadInput(); } -void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) { +void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { std::lock_guard lock{mutex}; auto& raw_status = console.motion_values.raw_status; auto& emulated = console.motion_values.emulated; @@ -162,8 +166,7 @@ void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) { TriggerOnChange(ConsoleTriggerType::Motion); } -void EmulatedConsole::SetTouch(Common::Input::CallbackStatus callback, - [[maybe_unused]] std::size_t index) { +void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { if (index >= console.touch_values.size()) { return; } diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index bb3d7ab90..3afd284d5 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -155,14 +155,14 @@ private: * Updates the motion status of the console * @param callback A CallbackStatus containing gyro and accelerometer data */ - void SetMotion(Common::Input::CallbackStatus callback); + void SetMotion(const Common::Input::CallbackStatus& callback); /** * Updates the touch status of the console * @param callback A CallbackStatus containing the touch position * @param index Finger ID to be updated */ - void SetTouch(Common::Input::CallbackStatus callback, std::size_t index); + void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Triggers a callback that something has changed on the console status diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index fbb19f230..eb2e0ab4f 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -205,11 +205,12 @@ void EmulatedController::ReloadInput() { continue; } const auto uuid = Common::UUID{button_params[index].Get("guid", "")}; - Common::Input::InputCallback button_callback{ - [this, index, uuid](Common::Input::CallbackStatus callback) { - SetButton(callback, index, uuid); - }}; - button_devices[index]->SetCallback(button_callback); + button_devices[index]->SetCallback({ + .on_change = + [this, index, uuid](const Common::Input::CallbackStatus& callback) { + SetButton(callback, index, uuid); + }, + }); button_devices[index]->ForceUpdate(); } @@ -218,11 +219,12 @@ void EmulatedController::ReloadInput() { continue; } const auto uuid = Common::UUID{stick_params[index].Get("guid", "")}; - Common::Input::InputCallback stick_callback{ - [this, index, uuid](Common::Input::CallbackStatus callback) { - SetStick(callback, index, uuid); - }}; - stick_devices[index]->SetCallback(stick_callback); + stick_devices[index]->SetCallback({ + .on_change = + [this, index, uuid](const Common::Input::CallbackStatus& callback) { + SetStick(callback, index, uuid); + }, + }); stick_devices[index]->ForceUpdate(); } @@ -231,11 +233,12 @@ void EmulatedController::ReloadInput() { continue; } const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")}; - Common::Input::InputCallback trigger_callback{ - [this, index, uuid](Common::Input::CallbackStatus callback) { - SetTrigger(callback, index, uuid); - }}; - trigger_devices[index]->SetCallback(trigger_callback); + trigger_devices[index]->SetCallback({ + .on_change = + [this, index, uuid](const Common::Input::CallbackStatus& callback) { + SetTrigger(callback, index, uuid); + }, + }); trigger_devices[index]->ForceUpdate(); } @@ -243,9 +246,12 @@ void EmulatedController::ReloadInput() { if (!battery_devices[index]) { continue; } - Common::Input::InputCallback battery_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetBattery(callback, index); }}; - battery_devices[index]->SetCallback(battery_callback); + battery_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetBattery(callback, index); + }, + }); battery_devices[index]->ForceUpdate(); } @@ -253,9 +259,12 @@ void EmulatedController::ReloadInput() { if (!motion_devices[index]) { continue; } - Common::Input::InputCallback motion_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetMotion(callback, index); }}; - motion_devices[index]->SetCallback(motion_callback); + motion_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetMotion(callback, index); + }, + }); motion_devices[index]->ForceUpdate(); } @@ -267,22 +276,24 @@ void EmulatedController::ReloadInput() { if (!tas_button_devices[index]) { continue; } - Common::Input::InputCallback button_callback{ - [this, index, tas_uuid](Common::Input::CallbackStatus callback) { - SetButton(callback, index, tas_uuid); - }}; - tas_button_devices[index]->SetCallback(button_callback); + tas_button_devices[index]->SetCallback({ + .on_change = + [this, index, tas_uuid](const Common::Input::CallbackStatus& callback) { + SetButton(callback, index, tas_uuid); + }, + }); } for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) { if (!tas_stick_devices[index]) { continue; } - Common::Input::InputCallback stick_callback{ - [this, index, tas_uuid](Common::Input::CallbackStatus callback) { - SetStick(callback, index, tas_uuid); - }}; - tas_stick_devices[index]->SetCallback(stick_callback); + tas_stick_devices[index]->SetCallback({ + .on_change = + [this, index, tas_uuid](const Common::Input::CallbackStatus& callback) { + SetStick(callback, index, tas_uuid); + }, + }); } } @@ -440,7 +451,7 @@ void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage if (index >= button_params.size()) { return; } - button_params[index] = param; + button_params[index] = std::move(param); ReloadInput(); } @@ -448,7 +459,7 @@ void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage p if (index >= stick_params.size()) { return; } - stick_params[index] = param; + stick_params[index] = std::move(param); ReloadInput(); } @@ -456,11 +467,11 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage if (index >= motion_params.size()) { return; } - motion_params[index] = param; + motion_params[index] = std::move(param); ReloadInput(); } -void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index, +void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, Common::UUID uuid) { if (index >= controller.button_values.size()) { return; @@ -600,7 +611,7 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: TriggerOnChange(ControllerTriggerType::Button, true); } -void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index, +void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, Common::UUID uuid) { if (index >= controller.stick_values.size()) { return; @@ -650,8 +661,8 @@ void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::s TriggerOnChange(ControllerTriggerType::Stick, true); } -void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, - Common::UUID uuid) { +void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, + std::size_t index, Common::UUID uuid) { if (index >= controller.trigger_values.size()) { return; } @@ -692,7 +703,8 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std: TriggerOnChange(ControllerTriggerType::Trigger, true); } -void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, + std::size_t index) { if (index >= controller.motion_values.size()) { return; } @@ -730,7 +742,8 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: TriggerOnChange(ControllerTriggerType::Motion, true); } -void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, + std::size_t index) { if (index >= controller.battery_values.size()) { return; } @@ -1110,7 +1123,7 @@ void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npa int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { std::lock_guard lock{mutex}; - callback_list.insert_or_assign(last_callback_key, update_callback); + callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); return last_callback_key++; } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 425b3e7c4..e42aafebc 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -328,35 +328,38 @@ private: * @param callback A CallbackStatus containing the button status * @param index Button ID of the to be updated */ - void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); + void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, + Common::UUID uuid); /** * Updates the analog stick status of the controller * @param callback A CallbackStatus containing the analog stick status * @param index stick ID of the to be updated */ - void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); + void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, + Common::UUID uuid); /** * Updates the trigger status of the controller * @param callback A CallbackStatus containing the trigger status * @param index trigger ID of the to be updated */ - void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); + void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index, + Common::UUID uuid); /** * Updates the motion status of the controller * @param callback A CallbackStatus containing gyro and accelerometer data * @param index motion ID of the to be updated */ - void SetMotion(Common::Input::CallbackStatus callback, std::size_t index); + void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Updates the battery status of the controller * @param callback A CallbackStatus containing the battery status * @param index Button ID of the to be updated */ - void SetBattery(Common::Input::CallbackStatus callback, std::size_t index); + void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Triggers a callback that something has changed on the controller status diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 874780ec2..708480f2d 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -70,50 +70,55 @@ void EmulatedDevices::ReloadInput() { if (!mouse_button_devices[index]) { continue; } - Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { - SetMouseButton(callback, index); - }}; - mouse_button_devices[index]->SetCallback(button_callback); + mouse_button_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetMouseButton(callback, index); + }, + }); } for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) { if (!mouse_analog_devices[index]) { continue; } - Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { - SetMouseAnalog(callback, index); - }}; - mouse_analog_devices[index]->SetCallback(button_callback); + mouse_analog_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetMouseAnalog(callback, index); + }, + }); } if (mouse_stick_device) { - Common::Input::InputCallback button_callback{ - [this](Common::Input::CallbackStatus callback) { SetMouseStick(callback); }}; - mouse_stick_device->SetCallback(button_callback); + mouse_stick_device->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback) { SetMouseStick(callback); }, + }); } for (std::size_t index = 0; index < keyboard_devices.size(); ++index) { if (!keyboard_devices[index]) { continue; } - Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { - SetKeyboardButton(callback, index); - }}; - keyboard_devices[index]->SetCallback(button_callback); + keyboard_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetKeyboardButton(callback, index); + }, + }); } for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) { if (!keyboard_modifier_devices[index]) { continue; } - Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { - SetKeyboardModifier(callback, index); - }}; - keyboard_modifier_devices[index]->SetCallback(button_callback); + keyboard_modifier_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetKeyboardModifier(callback, index); + }, + }); } } @@ -159,7 +164,8 @@ void EmulatedDevices::RestoreConfig() { ReloadFromSettings(); } -void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback, + std::size_t index) { if (index >= device_status.keyboard_values.size()) { return; } @@ -216,7 +222,7 @@ void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { } } -void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback, +void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& callback, std::size_t index) { if (index >= device_status.keyboard_moddifier_values.size()) { return; @@ -286,7 +292,8 @@ void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback TriggerOnChange(DeviceTriggerType::KeyboardModdifier); } -void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callback, + std::size_t index) { if (index >= device_status.mouse_button_values.size()) { return; } @@ -347,7 +354,8 @@ void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std TriggerOnChange(DeviceTriggerType::Mouse); } -void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callback, + std::size_t index) { if (index >= device_status.mouse_analog_values.size()) { return; } @@ -374,7 +382,7 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std TriggerOnChange(DeviceTriggerType::Mouse); } -void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) { +void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callback) { std::lock_guard lock{mutex}; const auto touch_value = TransformToTouch(callback); @@ -435,7 +443,7 @@ void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { std::lock_guard lock{mutex}; - callback_list.insert_or_assign(last_callback_key, update_callback); + callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); return last_callback_key++; } diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index c72327681..790d3b411 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -156,35 +156,34 @@ private: * @param callback A CallbackStatus containing the key status * @param index key ID to be updated */ - void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index); + void SetKeyboardButton(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Updates the keyboard status of the keyboard device * @param callback A CallbackStatus containing the modifier key status * @param index modifier key ID to be updated */ - void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index); + void SetKeyboardModifier(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Updates the mouse button status of the mouse device * @param callback A CallbackStatus containing the button status * @param index Button ID to be updated */ - void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index); + void SetMouseButton(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Updates the mouse wheel status of the mouse device * @param callback A CallbackStatus containing the wheel status * @param index wheel ID to be updated */ - void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index); + void SetMouseAnalog(const Common::Input::CallbackStatus& callback, std::size_t index); /** * Updates the mouse position status of the mouse device * @param callback A CallbackStatus containing the position status - * @param index stick ID to be updated */ - void SetMouseStick(Common::Input::CallbackStatus callback); + void SetMouseStick(const Common::Input::CallbackStatus& callback); /** * Triggers a callback that something has changed on the device status -- cgit v1.2.3 From 6aac5d4c27411a43200e0a9c0f96b2ec7fac9b7c Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 14 Dec 2021 19:20:07 -0600 Subject: core/hid: Fix faulty analog triggers --- src/core/hid/emulated_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index eb2e0ab4f..93372445b 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -670,7 +670,7 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac const auto trigger_value = TransformToTrigger(callback); // Only read trigger values that have the same uuid or are pressed once - if (controller.stick_values[index].uuid != uuid) { + if (controller.trigger_values[index].uuid != uuid) { if (!trigger_value.pressed.value) { return; } @@ -686,7 +686,7 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac return; } - const auto trigger = controller.trigger_values[index]; + const auto& trigger = controller.trigger_values[index]; switch (index) { case Settings::NativeTrigger::LTrigger: -- cgit v1.2.3