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 +---------- src/video_core/video_core.cpp | 6 ------ src/video_core/video_core.h | 2 -- src/yuzu/bootmanager.cpp | 2 +- 5 files changed, 8 insertions(+), 20 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{}; }; /** diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index e852c817e..329bf4def 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -55,10 +55,4 @@ std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor } } -float GetResolutionScaleFactor(const RendererBase& renderer) { - return Settings::values.resolution_info.active - ? Settings::values.resolution_info.up_factor - : renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio(); -} - } // namespace VideoCore diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index f86877e86..084df641f 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -25,6 +25,4 @@ class RendererBase; /// Creates an emulated GPU instance using the given system context. std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system); -float GetResolutionScaleFactor(const RendererBase& renderer); - } // namespace VideoCore diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 976acd176..822ba1a34 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -630,7 +630,7 @@ void GRenderWindow::ReleaseRenderTarget() { void GRenderWindow::CaptureScreenshot(const QString& screenshot_path) { auto& renderer = system.Renderer(); - const f32 res_scale = VideoCore::GetResolutionScaleFactor(renderer); + const f32 res_scale = Settings::values.resolution_info.up_factor; const Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(res_scale)}; screenshot_image = QImage(QSize(layout.width, layout.height), QImage::Format_RGB32); -- 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 ++++++++++++++++++++++++++++++++ src/yuzu/applets/qt_web_browser.cpp | 2 +- 6 files changed, 209 insertions(+), 209 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{}; +}; diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp index da8c6882a..24d72a496 100644 --- a/src/yuzu/applets/qt_web_browser.cpp +++ b/src/yuzu/applets/qt_web_browser.cpp @@ -15,7 +15,7 @@ #include "common/fs/path_util.h" #include "core/core.h" -#include "core/frontend/input_interpreter.h" +#include "core/hid/input_interpreter.h" #include "input_common/keyboard.h" #include "input_common/main.h" #include "yuzu/applets/qt_web_browser.h" -- 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 ++++++++++ src/yuzu/main.cpp | 5 ++++- 3 files changed, 25 insertions(+), 4 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(); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 7f36f6e2f..19cb5313f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -26,6 +26,7 @@ #include "core/frontend/applets/controller.h" #include "core/frontend/applets/general_frontend.h" #include "core/frontend/applets/software_keyboard.h" +#include "core/hid/hid_core.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" @@ -227,6 +228,8 @@ GMainWindow::GMainWindow() ConnectMenuEvents(); ConnectWidgetEvents(); + Core::System::GetInstance().HIDCore().ReloadInputDevices(); + const auto branch_name = std::string(Common::g_scm_branch); const auto description = std::string(Common::g_scm_desc); const auto build_id = std::string(Common::g_build_id); @@ -2969,7 +2972,7 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie QString GMainWindow::GetTasStateDescription() const { auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus(); switch (tas_status) { - case InputCommon::TasInput::TasState::Running: + case InputCommon::TasInput::TasState::Running : return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames); case InputCommon::TasInput::TasState::Recording: return tr("TAS state: Recording %1").arg(total_tas_frames); -- 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/common/settings.h | 3 --- src/common/settings_input.h | 13 ++++++++++++- 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 +-- 6 files changed, 16 insertions(+), 9 deletions(-) (limited to 'src/core') diff --git a/src/common/settings.h b/src/common/settings.h index fa4aa8747..4cf28617c 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -572,7 +572,6 @@ struct Values { BasicSetting mouse_panning{false, "mouse_panning"}; BasicRangedSetting mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; BasicSetting mouse_enabled{false, "mouse_enabled"}; - std::string mouse_device; MouseButtonsRaw mouse_buttons; BasicSetting emulate_analog_keyboard{false, "emulate_analog_keyboard"}; @@ -592,8 +591,6 @@ struct Values { BasicSetting touch_from_button_map_index{0, "touch_from_button_map"}; std::vector touch_from_button_maps; - std::atomic_bool is_device_reload_pending{true}; - // Data Storage BasicSetting use_virtual_sd{true, "use_virtual_sd"}; BasicSetting gamecard_inserted{false, "gamecard_inserted"}; diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 609600582..2c0eb31d3 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h @@ -62,11 +62,22 @@ enum Values : int { constexpr int STICK_HID_BEGIN = LStick; constexpr int STICK_HID_END = NumAnalogs; -constexpr int NUM_STICKS_HID = NumAnalogs; extern const std::array mapping; } // namespace NativeAnalog +namespace NativeTrigger { +enum Values : int { + LTrigger, + RTrigger, + + NumTriggers, +}; + +constexpr int TRIGGER_HID_BEGIN = LTrigger; +constexpr int TRIGGER_HID_END = NumTriggers; +} // namespace NativeTrigger + namespace NativeVibration { enum Values : int { LeftVibrationDevice, 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 ++++++++------------------------------ src/yuzu/applets/qt_controller.cpp | 2 -- src/yuzu_cmd/config.cpp | 1 - 4 files changed, 18 insertions(+), 54 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) || ...); } diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 4dd577a18..2cd5ed718 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -9,8 +9,6 @@ #include "common/param_package.h" #include "common/string_util.h" #include "core/core.h" -#include "core/hid/emulated_controller.h -#include "core/hid/hid_types.h #include "core/hle/lock.h" #include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/hid.h" diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 33241ea98..103a12b12 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -24,7 +24,6 @@ #include "common/settings.h" #include "core/hle/service/acc/profile_manager.h" #include "input_common/main.h" -#include "input_common/udp/client.h" #include "yuzu_cmd/config.h" #include "yuzu_cmd/default_ini.h" -- 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/common/input.h | 39 +++++++ 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 +--- src/input_common/drivers/gc_adapter.cpp | 8 +- src/input_common/drivers/gc_adapter.h | 2 +- src/input_common/drivers/sdl_driver.cpp | 8 +- src/input_common/drivers/sdl_driver.h | 2 +- src/input_common/helpers/stick_from_buttons.cpp | 3 +- src/input_common/helpers/stick_from_buttons.h | 3 +- src/input_common/helpers/touch_from_buttons.cpp | 4 +- src/input_common/input_engine.h | 18 ++-- src/input_common/input_poller.cpp | 40 ++++++- src/input_common/input_poller.h | 28 ++++- src/input_common/main.cpp | 30 ++++-- src/yuzu/configuration/configure_input_player.cpp | 7 ++ .../configure_input_player_widget.cpp | 59 ++++------ .../configuration/configure_input_player_widget.h | 10 +- 20 files changed, 312 insertions(+), 144 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 6eefc55f9..3a28b77a7 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -38,6 +38,27 @@ enum class BatteryLevel { Charging, }; +enum class PollingMode { + Active, + Pasive, + Camera, + NCF, + IR, +}; + +enum class VibrationError { + None, + NotSupported, + Disabled, + Unknown, +}; + +enum class PollingError { + None, + NotSupported, + Unknown, +}; + struct AnalogProperties { float deadzone{}; float range{1.0f}; @@ -149,6 +170,24 @@ private: InputCallback callback; }; +/// An abstract class template for an output device (rumble, LED pattern, polling mode). +class OutputDevice { +public: + virtual ~OutputDevice() = default; + + virtual void SetLED([[maybe_unused]] LedStatus led_status) { + return; + } + + virtual VibrationError SetVibration([[maybe_unused]] VibrationStatus vibration_status) { + return VibrationError::NotSupported; + } + + virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) { + return PollingError::NotSupported; + } +}; + /// An abstract class template for a factory that can create input devices. template class Factory { 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); diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 6721ba4f7..2aa5a16a6 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -322,13 +322,17 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) { return true; } -bool GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) { +Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) { const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; const auto processed_amplitude = static_cast((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8); pads[identifier.port].rumble_amplitude = processed_amplitude; - return rumble_enabled; + + if (!rumble_enabled) { + return Input::VibrationError::Disabled; + } + return Input::VibrationError::None; } void GCAdapter::UpdateVibrations() { diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index c0bf1ed7a..dd23dd9f3 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -24,7 +24,7 @@ public: explicit GCAdapter(const std::string input_engine_); ~GCAdapter(); - bool SetRumble(const PadIdentifier& identifier, + Input::VibrationError SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) override; /// Used for automapping features diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index efb4a2106..f7f03c5f2 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -506,7 +506,8 @@ std::vector SDLDriver::GetInputDevices() const { } return devices; } -bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) { +Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, + const Input::VibrationStatus vibration) { const auto joystick = GetSDLJoystickByGUID(identifier.guid.Format(), static_cast(identifier.port)); const auto process_amplitude = [](f32 amplitude) { @@ -519,7 +520,10 @@ bool SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::Vibratio .high_frequency = vibration.high_frequency, }; - return joystick->RumblePlay(new_vibration); + if (!joystick->RumblePlay(new_vibration)) { + return Input::VibrationError::Unknown; + } + return Input::VibrationError::None; } Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, float value) const { diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index d8d350184..f66b33c77 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -58,7 +58,7 @@ public: std::string GetHatButtonName(u8 direction_value) const override; u8 GetHatButtonId(const std::string direction_name) const override; - bool SetRumble(const PadIdentifier& identifier, + Input::VibrationError SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) override; private: diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 38f150746..89ba4aeb1 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -251,7 +251,8 @@ private: std::chrono::time_point last_update; }; -std::unique_ptr StickFromButton::Create(const Common::ParamPackage& params) { +std::unique_ptr StickFromButton::Create( + const Common::ParamPackage& params) { const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); auto up = Input::CreateDeviceFromString(params.Get("up", null_engine)); auto down = Input::CreateDeviceFromString(params.Get("down", null_engine)); diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h index 1d6e24c98..87165e022 100644 --- a/src/input_common/helpers/stick_from_buttons.h +++ b/src/input_common/helpers/stick_from_buttons.h @@ -25,7 +25,8 @@ public: * - "modifier": a serialized ParamPackage for creating a button device as the modifier * - "modifier_scale": a float for the multiplier the modifier gives to the position */ - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create( + const Common::ParamPackage& params) override; }; } // namespace InputCommon diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index 2abfaf841..6c9046ffb 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -57,7 +57,9 @@ private: const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; }; -std::unique_ptr TouchFromButton::Create(const Common::ParamPackage& params) { + +std::unique_ptr TouchFromButton::Create( + const Common::ParamPackage& params) { const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); auto button = Input::CreateDeviceFromString(params.Get("button", null_engine)); diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index 86a8e00d8..8a953c382 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -114,18 +114,24 @@ public: // Disable configuring mode for mapping void EndConfiguration(); - // Sets rumble to a controller - virtual bool SetRumble([[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Input::VibrationStatus vibration) { - return false; - } - // Sets a led pattern for a controller virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const Input::LedStatus led_status) { return; } + // Sets rumble to a controller + virtual Input::VibrationError SetRumble([[maybe_unused]] const PadIdentifier& identifier, + [[maybe_unused]] const Input::VibrationStatus vibration) { + return Input::VibrationError::NotSupported; + } + + // Sets polling mode to a controller + virtual Input::PollingError SetPollingMode([[maybe_unused]] const PadIdentifier& identifier, + [[maybe_unused]] const Input::PollingMode vibration) { + return Input::PollingError::NotSupported; + } + // Returns the engine name [[nodiscard]] const std::string& GetEngineName() const; diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 46a7dd276..781012886 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -592,6 +592,28 @@ private: InputEngine* input_engine; }; +class OutputFromIdentifier final : public Input::OutputDevice { +public: + explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) + : identifier(identifier_), input_engine(input_engine_) {} + + virtual void SetLED( Input::LedStatus led_status) { + input_engine->SetLeds(identifier, led_status); + } + + virtual Input::VibrationError SetVibration(Input::VibrationStatus vibration_status) { + return input_engine->SetRumble(identifier, vibration_status); + } + + virtual Input::PollingError SetPollingMode(Input::PollingMode polling_mode) { + return input_engine->SetPollingMode(identifier, polling_mode); + } + +private: + const PadIdentifier identifier; + InputEngine* input_engine; +}; + std::unique_ptr InputFactory::CreateButtonDevice( const Common::ParamPackage& params) { const PadIdentifier identifier = { @@ -825,7 +847,8 @@ std::unique_ptr InputFactory::CreateMotionDevice(Common::Par InputFactory::InputFactory(std::shared_ptr input_engine_) : input_engine(std::move(input_engine_)) {} -std::unique_ptr InputFactory::Create(const Common::ParamPackage& params) { +std::unique_ptr InputFactory::Create( + const Common::ParamPackage& params) { if (params.Has("button") && params.Has("axis")) { return CreateTriggerDevice(params); } @@ -857,4 +880,19 @@ std::unique_ptr InputFactory::Create(const Common::ParamPack return std::make_unique(); } +OutputFactory::OutputFactory(std::shared_ptr input_engine_) + : input_engine(std::move(input_engine_)) {} + +std::unique_ptr OutputFactory::Create( + const Common::ParamPackage& params) { + const PadIdentifier identifier = { + .guid = Common::UUID{params.Get("guid", "")}, + .port = static_cast(params.Get("port", 0)), + .pad = static_cast(params.Get("pad", 0)), + }; + + input_engine->PreSetController(identifier); + return std::make_unique(identifier, input_engine.get()); +} + } // namespace InputCommon diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h index 3c1e5b541..16cade5fa 100644 --- a/src/input_common/input_poller.h +++ b/src/input_common/input_poller.h @@ -16,12 +16,32 @@ class InputEngine; /** * An Input factory. It receives input events and forward them to all input devices it created. */ + +class OutputFactory final : public Input::Factory { +public: + explicit OutputFactory(std::shared_ptr input_engine_); + + /** + * Creates an output device from the parameters given. + * @param params contains parameters for creating the device: + * @param - "guid": text string for identifing controllers + * @param - "port": port of the connected device + * @param - "pad": slot of the connected controller + * @return an unique ouput device with the parameters specified + */ + std::unique_ptr Create( + const Common::ParamPackage& params) override; + +private: + std::shared_ptr input_engine; +}; + class InputFactory final : public Input::Factory { public: explicit InputFactory(std::shared_ptr input_engine_); /** - * Creates a input device from the parameters given. Identifies the type of input to be returned + * Creates an input device from the parameters given. Identifies the type of input to be returned * if it contains the following parameters: * - button: Contains "button" or "code" * - hat_button: Contains "hat" @@ -32,6 +52,7 @@ public: * - motion: Contains "motion" * - touch: Contains "button", "axis_x" and "axis_y" * - battery: Contains "battery" + * - output: Contains "output" * @param params contains parameters for creating the device: * @param - "code": the code of the keyboard key to bind with the input * @param - "button": same as "code" but for controller buttons @@ -41,10 +62,11 @@ public: * @param - "axis_x": same as axis but specifing horizontal direction * @param - "axis_y": same as axis but specifing vertical direction * @param - "axis_z": same as axis but specifing forward direction - * @param - "battery": Only used as a placeholder to set the input type + * @param - "battery": Only used as a placeholder to set the input type * @return an unique input device with the parameters specified */ - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create( + const Common::ParamPackage& params) override; private: /** diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 46ca6b76c..b7fe9cb37 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -46,8 +46,10 @@ struct InputSubsystem::Impl { gcadapter = std::make_shared("gcpad"); gcadapter->SetMappingCallback(mapping_callback); - gcadapter_factory = std::make_shared(gcadapter); - Input::RegisterFactory(gcadapter->GetEngineName(), gcadapter_factory); + gcadapter_input_factory = std::make_shared(gcadapter); + gcadapter_output_factory = std::make_shared(gcadapter); + Input::RegisterFactory(gcadapter->GetEngineName(), gcadapter_input_factory); + Input::RegisterFactory(gcadapter->GetEngineName(), gcadapter_output_factory); udp_client = std::make_shared("cemuhookudp"); udp_client->SetMappingCallback(mapping_callback); @@ -62,8 +64,10 @@ struct InputSubsystem::Impl { #ifdef HAVE_SDL2 sdl = std::make_shared("sdl"); sdl->SetMappingCallback(mapping_callback); - sdl_factory = std::make_shared(sdl); - Input::RegisterFactory(sdl->GetEngineName(), sdl_factory); + sdl_input_factory = std::make_shared(sdl); + sdl_output_factory = std::make_shared(sdl); + Input::RegisterFactory(sdl->GetEngineName(), sdl_input_factory); + Input::RegisterFactory(sdl->GetEngineName(), sdl_output_factory); #endif Input::RegisterFactory("touch_from_button", @@ -247,21 +251,27 @@ struct InputSubsystem::Impl { } std::shared_ptr mapping_factory; + std::shared_ptr keyboard; - std::shared_ptr keyboard_factory; std::shared_ptr mouse; - std::shared_ptr mouse_factory; std::shared_ptr gcadapter; - std::shared_ptr gcadapter_factory; std::shared_ptr touch_screen; - std::shared_ptr touch_screen_factory; + std::shared_ptr tas_input; std::shared_ptr udp_client; + + std::shared_ptr keyboard_factory; + std::shared_ptr mouse_factory; + std::shared_ptr gcadapter_input_factory; + std::shared_ptr touch_screen_factory; std::shared_ptr udp_client_factory; - std::shared_ptr tas_input; std::shared_ptr tas_input_factory; + + std::shared_ptr gcadapter_output_factory; + #ifdef HAVE_SDL2 std::shared_ptr sdl; - std::shared_ptr sdl_factory; + std::shared_ptr sdl_input_factory; + std::shared_ptr sdl_output_factory; #endif }; diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index adc9706f1..ed9c3facf 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -465,6 +465,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); + emulated_controller->SetNpadType( + GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())); }); connect(ui->comboDevices, qOverload(&QComboBox::activated), this, @@ -540,6 +542,11 @@ void ConfigureInputPlayer::LoadConfiguration() { void ConfigureInputPlayer::ConnectPlayer(bool connected) { ui->groupConnectedController->setChecked(connected); + if (connected) { + emulated_controller->Connect(); + } else { + emulated_controller->Disconnect(); + } } void ConfigureInputPlayer::UpdateInputDeviceCombobox() { diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 03d29f194..2ba9d7290 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -24,34 +24,6 @@ PlayerControlPreview::~PlayerControlPreview() { } }; -PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index, - bool player_on) { - if (!player_on) { - return {0, 0, 0, 0}; - } - - switch (index) { - case 0: - return {1, 0, 0, 0}; - case 1: - return {1, 1, 0, 0}; - case 2: - return {1, 1, 1, 0}; - case 3: - return {1, 1, 1, 1}; - case 4: - return {1, 0, 0, 1}; - case 5: - return {1, 0, 1, 0}; - case 6: - return {1, 0, 1, 1}; - case 7: - return {0, 1, 1, 0}; - default: - return {0, 0, 0, 0}; - } -} - void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) { if (is_controller_set) { controller->DeleteCallback(callback_key); @@ -160,8 +132,13 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ switch (type) { case Core::HID::ControllerTriggerType::Connected: + is_connected = true; + led_pattern = controller->GetLedPattern(); + needs_redraw = true; + break; case Core::HID::ControllerTriggerType::Disconnected: - is_connected = controller->IsConnected(); + is_connected = false; + led_pattern.raw = 0; needs_redraw = true; break; case Core::HID::ControllerTriggerType::Type: @@ -1853,10 +1830,14 @@ void PlayerControlPreview::DrawLeftBody(QPainter& p, const QPointF center) { const float led_size = 5.0f; const QPointF led_position = sideview_center + QPointF(0, -36); int led_count = 0; - for (const auto& color : led_color) { - p.setBrush(color); - DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); - } + p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); } void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) { @@ -1949,10 +1930,14 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) { const float led_size = 5.0f; const QPointF led_position = sideview_center + QPointF(0, -36); int led_count = 0; - for (const auto& color : led_color) { - p.setBrush(color); - DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); - } + p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); } void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index b44a2e347..16f9748f5 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -59,13 +59,6 @@ private: SR, }; - struct LedPattern { - bool position1; - bool position2; - bool position3; - bool position4; - }; - struct ColorMapping { QColor outline{}; QColor primary{}; @@ -88,7 +81,6 @@ private: QColor deadzone{}; }; - static LedPattern GetColorPattern(std::size_t index, bool player_on); void UpdateColors(); void ResetInputs(); @@ -194,7 +186,7 @@ private: int callback_key; QColor button_color{}; ColorMapping colors{}; - std::array led_color{}; + Core::HID::LedPattern led_pattern{0, 0, 0, 0}; std::size_t player_index{}; Core::HID::EmulatedController* controller; std::size_t button_mapping_index{Settings::NativeButton::NumButtons}; -- 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 - src/input_common/drivers/gc_adapter.cpp | 3 ++- src/input_common/drivers/gc_adapter.h | 2 +- src/input_common/drivers/sdl_driver.h | 2 +- src/input_common/helpers/stick_from_buttons.cpp | 3 +-- src/input_common/helpers/stick_from_buttons.h | 3 +-- src/input_common/helpers/touch_from_buttons.cpp | 4 +--- src/input_common/input_engine.h | 10 +++++---- src/input_common/input_poller.cpp | 8 +++---- src/input_common/input_poller.h | 10 ++++----- src/input_common/main.cpp | 6 ++++-- src/yuzu/applets/qt_controller.h | 1 - src/yuzu/configuration/configure_dialog.cpp | 2 +- src/yuzu/configuration/configure_input.cpp | 9 ++++---- .../configure_input_player_widget.cpp | 25 ++++++++++++---------- .../configuration/configure_input_player_widget.h | 16 +++++++++++++- src/yuzu/debugger/controller.cpp | 9 ++++++-- src/yuzu/debugger/controller.h | 9 +++++++- src/yuzu/main.cpp | 7 +++--- 20 files changed, 83 insertions(+), 53 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" diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 2aa5a16a6..4a56abb99 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -322,7 +322,8 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) { return true; } -Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) { +Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, + const Input::VibrationStatus vibration) { const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; const auto processed_amplitude = static_cast((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8); diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index dd23dd9f3..dd0e4aa1d 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -25,7 +25,7 @@ public: ~GCAdapter(); Input::VibrationError SetRumble(const PadIdentifier& identifier, - const Input::VibrationStatus vibration) override; + const Input::VibrationStatus vibration) override; /// Used for automapping features std::vector GetInputDevices() const override; diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index f66b33c77..1ff85f48d 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -59,7 +59,7 @@ public: u8 GetHatButtonId(const std::string direction_name) const override; Input::VibrationError SetRumble(const PadIdentifier& identifier, - const Input::VibrationStatus vibration) override; + const Input::VibrationStatus vibration) override; private: void InitJoystick(int joystick_index); diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 89ba4aeb1..38f150746 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -251,8 +251,7 @@ private: std::chrono::time_point last_update; }; -std::unique_ptr StickFromButton::Create( - const Common::ParamPackage& params) { +std::unique_ptr StickFromButton::Create(const Common::ParamPackage& params) { const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); auto up = Input::CreateDeviceFromString(params.Get("up", null_engine)); auto down = Input::CreateDeviceFromString(params.Get("down", null_engine)); diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h index 87165e022..1d6e24c98 100644 --- a/src/input_common/helpers/stick_from_buttons.h +++ b/src/input_common/helpers/stick_from_buttons.h @@ -25,8 +25,7 @@ public: * - "modifier": a serialized ParamPackage for creating a button device as the modifier * - "modifier_scale": a float for the multiplier the modifier gives to the position */ - std::unique_ptr Create( - const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; }; } // namespace InputCommon diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index 6c9046ffb..2abfaf841 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -57,9 +57,7 @@ private: const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; }; - -std::unique_ptr TouchFromButton::Create( - const Common::ParamPackage& params) { +std::unique_ptr TouchFromButton::Create(const Common::ParamPackage& params) { const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); auto button = Input::CreateDeviceFromString(params.Get("button", null_engine)); diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index 8a953c382..31ce900d7 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -121,14 +121,16 @@ public: } // Sets rumble to a controller - virtual Input::VibrationError SetRumble([[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Input::VibrationStatus vibration) { + virtual Input::VibrationError SetRumble( + [[maybe_unused]] const PadIdentifier& identifier, + [[maybe_unused]] const Input::VibrationStatus vibration) { return Input::VibrationError::NotSupported; } // Sets polling mode to a controller - virtual Input::PollingError SetPollingMode([[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Input::PollingMode vibration) { + virtual Input::PollingError SetPollingMode( + [[maybe_unused]] const PadIdentifier& identifier, + [[maybe_unused]] const Input::PollingMode vibration) { return Input::PollingError::NotSupported; } diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 781012886..62ade951c 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -597,7 +597,7 @@ public: explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) : identifier(identifier_), input_engine(input_engine_) {} - virtual void SetLED( Input::LedStatus led_status) { + virtual void SetLED(Input::LedStatus led_status) { input_engine->SetLeds(identifier, led_status); } @@ -847,8 +847,7 @@ std::unique_ptr InputFactory::CreateMotionDevice(Common::Par InputFactory::InputFactory(std::shared_ptr input_engine_) : input_engine(std::move(input_engine_)) {} -std::unique_ptr InputFactory::Create( - const Common::ParamPackage& params) { +std::unique_ptr InputFactory::Create(const Common::ParamPackage& params) { if (params.Has("button") && params.Has("axis")) { return CreateTriggerDevice(params); } @@ -883,8 +882,7 @@ std::unique_ptr InputFactory::Create( OutputFactory::OutputFactory(std::shared_ptr input_engine_) : input_engine(std::move(input_engine_)) {} -std::unique_ptr OutputFactory::Create( - const Common::ParamPackage& params) { +std::unique_ptr OutputFactory::Create(const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, .port = static_cast(params.Get("port", 0)), diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h index 16cade5fa..1357e104b 100644 --- a/src/input_common/input_poller.h +++ b/src/input_common/input_poller.h @@ -29,8 +29,7 @@ public: * @param - "pad": slot of the connected controller * @return an unique ouput device with the parameters specified */ - std::unique_ptr Create( - const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; private: std::shared_ptr input_engine; @@ -41,8 +40,8 @@ public: explicit InputFactory(std::shared_ptr input_engine_); /** - * Creates an input device from the parameters given. Identifies the type of input to be returned - * if it contains the following parameters: + * Creates an input device from the parameters given. Identifies the type of input to be + * returned if it contains the following parameters: * - button: Contains "button" or "code" * - hat_button: Contains "hat" * - analog: Contains "axis" @@ -65,8 +64,7 @@ public: * @param - "battery": Only used as a placeholder to set the input type * @return an unique input device with the parameters specified */ - std::unique_ptr Create( - const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; private: /** diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index b7fe9cb37..7807dd38f 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -48,8 +48,10 @@ struct InputSubsystem::Impl { gcadapter->SetMappingCallback(mapping_callback); gcadapter_input_factory = std::make_shared(gcadapter); gcadapter_output_factory = std::make_shared(gcadapter); - Input::RegisterFactory(gcadapter->GetEngineName(), gcadapter_input_factory); - Input::RegisterFactory(gcadapter->GetEngineName(), gcadapter_output_factory); + Input::RegisterFactory(gcadapter->GetEngineName(), + gcadapter_input_factory); + Input::RegisterFactory(gcadapter->GetEngineName(), + gcadapter_output_factory); udp_client = std::make_shared("cemuhookudp"); udp_client->SetMappingCallback(mapping_callback); diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h index 98060e6f8..ca09fde04 100644 --- a/src/yuzu/applets/qt_controller.h +++ b/src/yuzu/applets/qt_controller.h @@ -106,7 +106,6 @@ private: Core::Frontend::ControllerParameters parameters; InputCommon::InputSubsystem* input_subsystem; - Core::System& system; std::unique_ptr input_profiles; diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 642a5f966..1eb9d70e5 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -74,7 +74,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, hotkeys_tab->Populate(registry); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - input_tab->Initialize(input_subsystem); + input_tab->Initialize(input_subsystem, system_); general_tab->SetResetCallback([&] { this->close(); }); diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 61513865f..a8611f77f 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -146,10 +146,11 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Co advanced = new ConfigureInputAdvanced(this); ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); ui->tabAdvanced->layout()->addWidget(advanced); - connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { - CallConfigureDialog(*this, input_subsystem, profiles.get(), - system); - }); + connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, + [this, input_subsystem, &system] { + CallConfigureDialog(*this, input_subsystem, + profiles.get(), system); + }); connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { CallConfigureDialog(*this, input_subsystem); }); diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 2ba9d7290..446b72e55 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -19,15 +19,11 @@ PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) { } PlayerControlPreview::~PlayerControlPreview() { - if (is_controller_set) { - controller->DeleteCallback(callback_key); - } + UnloadController(); }; void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) { - if (is_controller_set) { - controller->DeleteCallback(callback_key); - } + UnloadController(); is_controller_set = true; controller = controller_; Core::HID::ControllerUpdateCallback engine_callback{ @@ -36,14 +32,21 @@ void PlayerControlPreview::SetController(Core::HID::EmulatedController* controll ControllerUpdate(Core::HID::ControllerTriggerType::All); } -void PlayerControlPreview::BeginMappingButton(std::size_t index) { - button_mapping_index = index; +void PlayerControlPreview::UnloadController() { + if (is_controller_set) { + controller->DeleteCallback(callback_key); + is_controller_set = false; + } +} + +void PlayerControlPreview::BeginMappingButton(std::size_t button_id) { + button_mapping_index = button_id; mapping_active = true; } -void PlayerControlPreview::BeginMappingAnalog(std::size_t index) { - button_mapping_index = Settings::NativeButton::LStick + index; - analog_mapping_index = index; +void PlayerControlPreview::BeginMappingAnalog(std::size_t stick_id) { + button_mapping_index = Settings::NativeButton::LStick + stick_id; + analog_mapping_index = stick_id; mapping_active = true; } diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 16f9748f5..333c3fc56 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -25,11 +25,25 @@ public: explicit PlayerControlPreview(QWidget* parent); ~PlayerControlPreview() override; + // Sets the emulated controller to be displayed void SetController(Core::HID::EmulatedController* controller); + + // Disables events from the emulated controller + void UnloadController(); + + // Starts blinking animation at the button specified void BeginMappingButton(std::size_t button_id); - void BeginMappingAnalog(std::size_t button_id); + + // Starts moving animation at the stick specified + void BeginMappingAnalog(std::size_t stick_id); + + // Stops any ongoing animation void EndMapping(); + + // Handles emulated controller events void ControllerUpdate(Core::HID::ControllerTriggerType type); + + // Updates input on sheduled interval void UpdateInput(); protected: diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp index d8e41f8b6..3619aed26 100644 --- a/src/yuzu/debugger/controller.cpp +++ b/src/yuzu/debugger/controller.cpp @@ -10,7 +10,8 @@ #include "yuzu/configuration/configure_input_player_widget.h" #include "yuzu/debugger/controller.h" -ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { +ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent) + : QWidget(parent, Qt::Dialog) { setObjectName(QStringLiteral("Controller")); setWindowTitle(tr("Controller P1")); resize(500, 350); @@ -20,7 +21,7 @@ ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog Qt::WindowMaximizeButtonHint); widget = new PlayerControlPreview(this); - widget->SetController(Core::System::GetInstance().HIDCore().GetEmulatedController( + widget->SetController(system.HIDCore().GetEmulatedController( Core::HID::NpadIdType::Player1)); QLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); @@ -45,6 +46,10 @@ QAction* ControllerDialog::toggleViewAction() { return toggle_view_action; } +void ControllerDialog::UnloadController() { + widget->UnloadController(); +} + void ControllerDialog::showEvent(QShowEvent* ev) { if (toggle_view_action) { toggle_view_action->setChecked(isVisible()); diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h index 697489cbb..33f617b9b 100644 --- a/src/yuzu/debugger/controller.h +++ b/src/yuzu/debugger/controller.h @@ -11,6 +11,10 @@ class QHideEvent; class QShowEvent; class PlayerControlPreview; +namespace Core { +class System; +} + namespace InputCommon { class InputSubsystem; } @@ -19,11 +23,14 @@ class ControllerDialog : public QWidget { Q_OBJECT public: - explicit ControllerDialog(QWidget* parent = nullptr); + explicit ControllerDialog(Core::System& system, QWidget* parent = nullptr); /// Returns a QAction that can be used to toggle visibility of this dialog. QAction* toggleViewAction(); + // Disables events from the emulated controller + void UnloadController(); + protected: void showEvent(QShowEvent* ev) override; void hideEvent(QHideEvent* ev) override; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 19cb5313f..ae997ccfa 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -228,7 +228,7 @@ GMainWindow::GMainWindow() ConnectMenuEvents(); ConnectWidgetEvents(); - Core::System::GetInstance().HIDCore().ReloadInputDevices(); + system->HIDCore().ReloadInputDevices(); const auto branch_name = std::string(Common::g_scm_branch); const auto description = std::string(Common::g_scm_desc); @@ -924,7 +924,7 @@ void GMainWindow::InitializeDebugWidgets() { waitTreeWidget->hide(); debug_menu->addAction(waitTreeWidget->toggleViewAction()); - controller_dialog = new ControllerDialog(this); + controller_dialog = new ControllerDialog(*system, this); controller_dialog->hide(); debug_menu->addAction(controller_dialog->toggleViewAction()); @@ -3372,7 +3372,8 @@ void GMainWindow::closeEvent(QCloseEvent* event) { UpdateUISettings(); game_list->SaveInterfaceLayout(); hotkey_registry.SaveHotkeys(); - Core::System::GetInstance().HIDCore().UnloadInputDevices(); + controller_dialog->UnloadController(); + system->HIDCore().UnloadInputDevices(); // Shutdown session if the emu thread is active... if (emu_thread != nullptr) { -- 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 + src/yuzu/configuration/configure_input.cpp | 1 + src/yuzu/configuration/configure_input_player.cpp | 81 ++++++++++++++++-- .../configure_input_player_widget.cpp | 2 +- 10 files changed, 226 insertions(+), 65 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{}; diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index a8611f77f..67faa8be8 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -114,6 +114,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Co player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i])); player_tabs[i]->layout()->addWidget(player_controllers[i]); connect(player_controllers[i], &ConfigureInputPlayer::Connected, [&, i](bool is_connected) { + // Ensures that the controllers are always connected in sequential order if (is_connected) { for (std::size_t index = 0; index <= i; ++index) { player_connected[index]->setChecked(is_connected); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index ed9c3facf..81310a5b3 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -143,8 +143,26 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i timeout_timer(std::make_unique()), poll_timer(std::make_unique()), bottom_row(bottom_row), system{system_} { - emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index); - emulated_controller->EnableConfiguration(); + if (player_index == 0) { + auto* emulated_controller_p1 = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + emulated_controller_p1->SaveCurrentConfig(); + emulated_controller_p1->EnableConfiguration(); + emulated_controller_hanheld->SaveCurrentConfig(); + emulated_controller_hanheld->EnableConfiguration(); + if (emulated_controller_hanheld->IsConnected(true)) { + emulated_controller_p1->Disconnect(); + emulated_controller = emulated_controller_hanheld; + } else { + emulated_controller = emulated_controller_p1; + } + } else { + emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index); + emulated_controller->SaveCurrentConfig(); + emulated_controller->EnableConfiguration(); + } ui->setupUi(this); setFocusPolicy(Qt::ClickFocus); @@ -460,13 +478,36 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); - connect(ui->comboControllerType, qOverload(&QComboBox::currentIndexChanged), [this](int) { + connect(ui->comboControllerType, qOverload(&QComboBox::currentIndexChanged), [this, player_index](int) { UpdateControllerAvailableButtons(); UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); - emulated_controller->SetNpadType( - GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())); + const Core::HID::NpadType type = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); + + if (player_index == 0) { + auto* emulated_controller_p1 = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + bool is_connected = emulated_controller->IsConnected(true); + + emulated_controller_p1->SetNpadType(type); + emulated_controller_hanheld->SetNpadType(type); + if (is_connected) { + if (type == Core::HID::NpadType::Handheld) { + emulated_controller_p1->Disconnect(); + emulated_controller_hanheld->Connect(); + emulated_controller = emulated_controller_hanheld; + } else { + emulated_controller_hanheld->Disconnect(); + emulated_controller_p1->Connect(); + emulated_controller = emulated_controller_p1; + } + } + ui->controllerFrame->SetController(emulated_controller); + } + emulated_controller->SetNpadType(type); }); connect(ui->comboDevices, qOverload(&QComboBox::activated), this, @@ -504,11 +545,35 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i } ConfigureInputPlayer::~ConfigureInputPlayer() { - emulated_controller->DisableConfiguration(); + if (player_index == 0) { + auto* emulated_controller_p1 = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + emulated_controller_p1->DisableConfiguration(); + emulated_controller_hanheld->DisableConfiguration(); + } else { + emulated_controller->DisableConfiguration(); + } }; void ConfigureInputPlayer::ApplyConfiguration() { + if (player_index == 0) { + auto* emulated_controller_p1 = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + emulated_controller_p1->DisableConfiguration(); + emulated_controller_p1->SaveCurrentConfig(); + emulated_controller_p1->EnableConfiguration(); + emulated_controller_hanheld->DisableConfiguration(); + emulated_controller_hanheld->SaveCurrentConfig(); + emulated_controller_hanheld->EnableConfiguration(); + return; + } + emulated_controller->DisableConfiguration(); emulated_controller->SaveCurrentConfig(); + emulated_controller->EnableConfiguration(); } void ConfigureInputPlayer::showEvent(QShowEvent* event) { @@ -535,9 +600,9 @@ void ConfigureInputPlayer::RetranslateUI() { void ConfigureInputPlayer::LoadConfiguration() { UpdateUI(); UpdateInputDeviceCombobox(); - const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType()); + const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType(true)); ui->comboControllerType->setCurrentIndex(comboBoxIndex); - ui->groupConnectedController->setChecked(emulated_controller->IsConnected()); + ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true)); } void ConfigureInputPlayer::ConnectPlayer(bool connected) { diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 446b72e55..3b79b6076 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -145,7 +145,7 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ needs_redraw = true; break; case Core::HID::ControllerTriggerType::Type: - controller_type = controller->GetNpadType(); + controller_type = controller->GetNpadType(true); needs_redraw = true; break; case Core::HID::ControllerTriggerType::Color: -- 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/common/input.h | 1 + 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 +- src/input_common/drivers/gc_adapter.cpp | 75 +++++- src/input_common/drivers/gc_adapter.h | 6 +- src/input_common/drivers/keyboard.cpp | 2 +- src/input_common/drivers/sdl_driver.cpp | 22 +- src/input_common/drivers/tas_input.cpp | 2 +- .../configure_input_player_widget.cpp | 12 +- 11 files changed, 240 insertions(+), 153 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 3a28b77a7..8871a9d07 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -30,6 +30,7 @@ enum class InputType { }; enum class BatteryLevel { + None, Empty, Critical, Low, 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); diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 4a56abb99..4fb6ab5af 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -150,7 +150,10 @@ void GCAdapter::UpdatePadType(std::size_t port, ControllerTypes pad_type) { return; } // Device changed reset device and set new type - pads[port] = {}; + pads[port].axis_origin = {}; + pads[port].reset_origin_counter = {}; + pads[port].enable_vibration = {}; + pads[port].rumble_amplitude = {}; pads[port].type = pad_type; } @@ -396,12 +399,11 @@ std::vector GCAdapter::GetInputDevices() const { if (!DeviceConnected(port)) { continue; } - const std::string name = fmt::format("Gamecube Controller {}", port + 1); - devices.emplace_back(Common::ParamPackage{ - {"engine", "gcpad"}, - {"display", std::move(name)}, - {"port", std::to_string(port)}, - }); + Common::ParamPackage identifier{}; + identifier.Set("engine", GetEngineName()); + identifier.Set("display", fmt::format("Gamecube Controller {}", port + 1)); + identifier.Set("port", static_cast(port)); + devices.emplace_back(identifier); } return devices; } @@ -431,7 +433,8 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p ButtonMapping mapping{}; for (const auto& [switch_button, gcadapter_button] : switch_to_gcadapter_button) { - Common::ParamPackage button_params({{"engine", "gcpad"}}); + Common::ParamPackage button_params{}; + button_params.Set("engine", GetEngineName()); button_params.Set("port", params.Get("port", 0)); button_params.Set("button", static_cast(gcadapter_button)); mapping.insert_or_assign(switch_button, std::move(button_params)); @@ -444,7 +447,8 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p {Settings::NativeButton::ZR, PadButton::TriggerR, PadAxes::TriggerRight}, }; for (const auto& [switch_button, gcadapter_buton, gcadapter_axis] : switch_to_gcadapter_axis) { - Common::ParamPackage button_params({{"engine", "gcpad"}}); + Common::ParamPackage button_params{}; + button_params.Set("engine", GetEngineName()); button_params.Set("port", params.Get("port", 0)); button_params.Set("button", static_cast(gcadapter_buton)); button_params.Set("axis", static_cast(gcadapter_axis)); @@ -463,13 +467,13 @@ AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& p AnalogMapping mapping = {}; Common::ParamPackage left_analog_params; - left_analog_params.Set("engine", "gcpad"); + left_analog_params.Set("engine", GetEngineName()); left_analog_params.Set("port", params.Get("port", 0)); left_analog_params.Set("axis_x", static_cast(PadAxes::StickX)); left_analog_params.Set("axis_y", static_cast(PadAxes::StickY)); mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params)); Common::ParamPackage right_analog_params; - right_analog_params.Set("engine", "gcpad"); + right_analog_params.Set("engine", GetEngineName()); right_analog_params.Set("port", params.Get("port", 0)); right_analog_params.Set("axis_x", static_cast(PadAxes::SubstickX)); right_analog_params.Set("axis_y", static_cast(PadAxes::SubstickY)); @@ -477,9 +481,56 @@ AnalogMapping GCAdapter::GetAnalogMappingForDevice(const Common::ParamPackage& p return mapping; } +std::string GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const { + PadButton button = static_cast(params.Get("button", 0)); + switch (button) { + case PadButton::ButtonLeft: + return "left"; + break; + case PadButton::ButtonRight: + return "right"; + break; + case PadButton::ButtonDown: + return "down"; + break; + case PadButton::ButtonUp: + return "up"; + break; + case PadButton::TriggerZ: + return "Z"; + break; + case PadButton::TriggerR: + return "R"; + break; + case PadButton::TriggerL: + return "L"; + break; + case PadButton::ButtonA: + return "A"; + break; + case PadButton::ButtonB: + return "B"; + break; + case PadButton::ButtonX: + return "X"; + break; + case PadButton::ButtonY: + return "Y"; + break; + case PadButton::ButtonStart: + return "start"; + break; + default: + return "Unkown GC"; + } +} + std::string GCAdapter::GetUIName(const Common::ParamPackage& params) const { if (params.Has("button")) { - return fmt::format("Button {}", params.Get("button", 0)); + return fmt::format("Button {}", GetUIButtonName(params)); + } + if (params.Has("axis")) { + return fmt::format("Axis {}", params.Get("axis",0)); } return "Bad GC Adapter"; diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index dd0e4aa1d..b82e4803d 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -105,8 +105,12 @@ private: void Reset(); void UpdateVibrations(); - // Updates vibration state of all controllers + + /// Updates vibration state of all controllers void SendVibrations(); + + std::string GetUIButtonName(const Common::ParamPackage& params) const; + std::unique_ptr usb_adapter_handle; std::array pads; diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp index b00a4b8d9..85a781a30 100644 --- a/src/input_common/drivers/keyboard.cpp +++ b/src/input_common/drivers/keyboard.cpp @@ -26,7 +26,7 @@ void Keyboard::ReleaseAllKeys() { std::vector Keyboard::GetInputDevices() const { std::vector devices; devices.emplace_back(Common::ParamPackage{ - {"engine", "keyboard"}, + {"engine", GetEngineName()}, {"display", "Keyboard Only"}, }); return devices; diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index f7f03c5f2..cee2d965f 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -305,6 +305,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (joystick_map.find(guid) == joystick_map.end()) { auto joystick = std::make_shared(guid, 0, sdl_joystick, sdl_gamecontroller); PreSetController(joystick->GetPadIdentifier()); + SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); joystick_map[guid].emplace_back(std::move(joystick)); return; } @@ -322,6 +323,7 @@ void SDLDriver::InitJoystick(int joystick_index) { const int port = static_cast(joystick_guid_list.size()); auto joystick = std::make_shared(guid, port, sdl_joystick, sdl_gamecontroller); PreSetController(joystick->GetPadIdentifier()); + SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); joystick_guid_list.emplace_back(std::move(joystick)); } @@ -472,7 +474,7 @@ std::vector SDLDriver::GetInputDevices() const { const std::string name = fmt::format("{} {}", joystick->GetControllerName(), joystick->GetPort()); devices.emplace_back(Common::ParamPackage{ - {"engine", "sdl"}, + {"engine", GetEngineName()}, {"display", std::move(name)}, {"guid", joystick->GetGUID()}, {"port", std::to_string(joystick->GetPort())}, @@ -495,7 +497,7 @@ std::vector SDLDriver::GetInputDevices() const { const std::string name = fmt::format("{} {}", "Nintendo Dual Joy-Con", joystick->GetPort()); devices.emplace_back(Common::ParamPackage{ - {"engine", "sdl"}, + {"engine", GetEngineName()}, {"display", std::move(name)}, {"guid", joystick->GetGUID()}, {"guid2", joystick2->GetGUID()}, @@ -527,7 +529,8 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, } Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, float value) const { - Common::ParamPackage params({{"engine", "sdl"}}); + Common::ParamPackage params{}; + params.Set("engine", GetEngineName()); params.Set("port", port); params.Set("guid", std::move(guid)); params.Set("axis", axis); @@ -538,7 +541,8 @@ Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std:: Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::string guid, s32 button) const { - Common::ParamPackage params({{"engine", "sdl"}}); + Common::ParamPackage params{}; + params.Set("engine", GetEngineName()); params.Set("port", port); params.Set("guid", std::move(guid)); params.Set("button", button); @@ -547,8 +551,8 @@ Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std:: Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::string guid, s32 hat, u8 value) const { - Common::ParamPackage params({{"engine", "sdl"}}); - + Common::ParamPackage params{}; + params.Set("engine", GetEngineName()); params.Set("port", port); params.Set("guid", std::move(guid)); params.Set("hat", hat); @@ -557,7 +561,9 @@ Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::str } Common::ParamPackage SDLDriver::BuildMotionParam(int port, std::string guid) const { - Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}}); + Common::ParamPackage params{}; + params.Set("engine", GetEngineName()); + params.Set("motion", 0); params.Set("port", port); params.Set("guid", std::move(guid)); return params; @@ -583,7 +589,7 @@ Common::ParamPackage SDLDriver::BuildParamPackageForAnalog(PadIdentifier identif int axis_y, float offset_x, float offset_y) const { Common::ParamPackage params; - params.Set("engine", "sdl"); + params.Set("engine", GetEngineName()); params.Set("port", static_cast(identifier.port)); params.Set("guid", identifier.guid.Format()); params.Set("axis_x", axis_x); diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 5e2101b27..7e7a1d58f 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -127,7 +127,7 @@ void Tas::WriteTasFile(std::u8string file_name) { std::string output_text; for (size_t frame = 0; frame < record_commands.size(); frame++) { const TASCommand& line = record_commands[frame]; - output_text += fmt::format("{} {} {} {} {}\n", frame, WriteCommandButtons(line.buttons), + output_text += fmt::format("{} {} {} {}\n", frame, WriteCommandButtons(line.buttons), WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis)); } const auto bytes_written = Common::FS::WriteStringToFile( diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 3b79b6076..93f7eddc9 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -27,7 +27,9 @@ void PlayerControlPreview::SetController(Core::HID::EmulatedController* controll is_controller_set = true; controller = controller_; Core::HID::ControllerUpdateCallback engine_callback{ - [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }}; + .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, + .is_service = false, + }; callback_key = controller->SetCallback(engine_callback); ControllerUpdate(Core::HID::ControllerTriggerType::All); } @@ -810,7 +812,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); // Draw battery - DrawBattery(p, center + QPoint(-30, -165), battery_values[0]); + DrawBattery(p, center + QPoint(-30, -160), battery_values[0]); } void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { @@ -2655,6 +2657,9 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery) { + if (battery == Input::BatteryLevel::None) { + return; + } p.setPen(colors.outline); p.setBrush(colors.transparent); p.drawRect(center.x(), center.y(), 56, 20); @@ -2669,6 +2674,7 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::Batte p.drawRect(center.x() + 42, center.y(), 14, 20); p.drawRect(center.x() + 28, center.y(), 14, 20); p.drawRect(center.x() + 14, center.y(), 14, 20); + p.drawRect(center.x(), center.y(), 14, 20); break; case Input::BatteryLevel::Medium: p.drawRect(center.x() + 28, center.y(), 14, 20); @@ -2685,6 +2691,8 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::Batte case Input::BatteryLevel::Empty: p.drawRect(center.x(), center.y(), 5, 20); break; + default: + break; } } -- 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/common/input.h | 7 +++++++ src/core/hid/emulated_controller.cpp | 34 +++++++++++++++++++++------------ src/input_common/drivers/sdl_driver.cpp | 20 ++++++++++++++++++- 3 files changed, 48 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 8871a9d07..cdacd4689 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -60,6 +60,12 @@ enum class PollingError { Unknown, }; +// Hint for amplification curve to be used +enum class VibrationAmplificationType { + Linear, + Exponential, +}; + struct AnalogProperties { float deadzone{}; float range{1.0f}; @@ -126,6 +132,7 @@ struct VibrationStatus { f32 low_frequency{}; f32 high_amplitude{}; f32 high_frequency{}; + VibrationAmplificationType type; }; struct LedStatus { 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 { diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index cee2d965f..d56351815 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -107,6 +107,14 @@ public: return false; } + + bool HasHDRumble() const { + if (sdl_controller) { + return (SDL_GameControllerGetType(sdl_controller.get()) == + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO); + } + return false; + } /** * The Pad identifier of the joystick */ @@ -515,16 +523,26 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, const auto process_amplitude = [](f32 amplitude) { return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF; }; - const Input::VibrationStatus new_vibration{ + const Input::VibrationStatus exponential_vibration{ .low_amplitude = process_amplitude(vibration.low_amplitude), .low_frequency = vibration.low_frequency, .high_amplitude = process_amplitude(vibration.high_amplitude), .high_frequency = vibration.high_frequency, + .type = Input::VibrationAmplificationType::Exponential, }; + Input::VibrationStatus new_vibration{}; + + if (vibration.type == Input::VibrationAmplificationType::Linear || joystick->HasHDRumble()) { + new_vibration = vibration; + } else { + new_vibration = exponential_vibration; + } + if (!joystick->RumblePlay(new_vibration)) { return Input::VibrationError::Unknown; } + return Input::VibrationError::None; } Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, -- 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 +- src/input_common/main.cpp | 10 ++ src/yuzu/applets/qt_controller.cpp | 143 +++++++++------------ src/yuzu/applets/qt_controller.h | 14 +- src/yuzu/applets/qt_software_keyboard.cpp | 21 +-- src/yuzu/configuration/configure_input.cpp | 17 ++- .../configure_input_player_widget.cpp | 4 +- src/yuzu/main.cpp | 11 +- 12 files changed, 141 insertions(+), 127 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; diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 7807dd38f..b048783c9 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -32,12 +32,17 @@ struct InputSubsystem::Impl { keyboard = std::make_shared("keyboard"); keyboard->SetMappingCallback(mapping_callback); keyboard_factory = std::make_shared(keyboard); + keyboard_output_factory = std::make_shared(keyboard); Input::RegisterFactory(keyboard->GetEngineName(), keyboard_factory); + Input::RegisterFactory(keyboard->GetEngineName(), + keyboard_output_factory); mouse = std::make_shared("mouse"); mouse->SetMappingCallback(mapping_callback); mouse_factory = std::make_shared(mouse); + mouse_output_factory = std::make_shared(mouse); Input::RegisterFactory(mouse->GetEngineName(), mouse_factory); + Input::RegisterFactory(mouse->GetEngineName(), mouse_output_factory); touch_screen = std::make_shared("touch"); touch_screen_factory = std::make_shared(touch_screen); @@ -61,7 +66,9 @@ struct InputSubsystem::Impl { tas_input = std::make_shared("tas"); tas_input->SetMappingCallback(mapping_callback); tas_input_factory = std::make_shared(tas_input); + tas_output_factory = std::make_shared(tas_input); Input::RegisterFactory(tas_input->GetEngineName(), tas_input_factory); + Input::RegisterFactory(tas_input->GetEngineName(), tas_output_factory); #ifdef HAVE_SDL2 sdl = std::make_shared("sdl"); @@ -268,7 +275,10 @@ struct InputSubsystem::Impl { std::shared_ptr udp_client_factory; std::shared_ptr tas_input_factory; + std::shared_ptr keyboard_output_factory; + std::shared_ptr mouse_output_factory; std::shared_ptr gcadapter_output_factory; + std::shared_ptr tas_output_factory; #ifdef HAVE_SDL2 std::shared_ptr sdl; diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 2cd5ed718..32cb5b5ff 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -9,6 +9,8 @@ #include "common/param_package.h" #include "common/string_util.h" #include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_types.h" #include "core/hle/lock.h" #include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/hid.h" @@ -26,48 +28,31 @@ namespace { constexpr std::size_t HANDHELD_INDEX = 8; -constexpr std::array, 8> led_patterns{{ - {true, false, false, false}, - {true, true, false, false}, - {true, true, true, false}, - {true, true, true, true}, - {true, false, false, true}, - {true, false, true, false}, - {true, false, true, true}, - {false, true, true, false}, -}}; - -void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, - bool connected, Core::System& system) { - if (!system.IsPoweredOn()) { - return; +void UpdateController(Core::HID::EmulatedController* controller, Core::HID::NpadType controller_type, bool connected) { + if (controller->IsConnected()) { + controller->Disconnect(); + } + controller->SetNpadType(controller_type); + if (connected) { + controller->Connect(); } - - auto& npad = - system.ServiceManager() - .GetService("hid") - ->GetAppletResource() - ->GetController(Service::HID::HidController::NPad); - - npad.UpdateControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(controller_type), - npad_index, connected); } // Returns true if the given controller type is compatible with the given parameters. -bool IsControllerCompatible(Settings::ControllerType controller_type, +bool IsControllerCompatible(Core::HID::NpadType controller_type, Core::Frontend::ControllerParameters parameters) { switch (controller_type) { - case Settings::ControllerType::ProController: + case Core::HID::NpadType::ProController: return parameters.allow_pro_controller; - case Settings::ControllerType::DualJoyconDetached: + case Core::HID::NpadType::JoyconDual: return parameters.allow_dual_joycons; - case Settings::ControllerType::LeftJoycon: + case Core::HID::NpadType::JoyconLeft: return parameters.allow_left_joycon; - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadType::JoyconRight: return parameters.allow_right_joycon; - case Settings::ControllerType::Handheld: + case Core::HID::NpadType::Handheld: return parameters.enable_single_mode && parameters.allow_handheld; - case Settings::ControllerType::GameCube: + case Core::HID::NpadType::GameCube: return parameters.allow_gamecube_controller; default: return false; @@ -198,7 +183,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( connect(emulated_controllers[i], qOverload(&QComboBox::currentIndexChanged), [this, i](int index) { UpdateDockedState(GetControllerTypeFromIndex(index, i) == - Settings::ControllerType::Handheld); + Core::HID::NpadType::Handheld); }); } } @@ -251,17 +236,17 @@ void QtControllerSelectorDialog::ApplyConfiguration() { } void QtControllerSelectorDialog::LoadConfiguration() { + const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { - const auto connected = - Settings::values.players.GetValue()[index].connected || - (index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected); + const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); + const auto connected = controller->IsConnected() || (index == 0 && handheld->IsConnected()); player_groupboxes[index]->setChecked(connected); connected_controller_checkboxes[index]->setChecked(connected); - emulated_controllers[index]->setCurrentIndex(GetIndexFromControllerType( - Settings::values.players.GetValue()[index].controller_type, index)); + emulated_controllers[index]->setCurrentIndex( + GetIndexFromControllerType(controller->GetNpadType(), index)); } - UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected); + UpdateDockedState(handheld->IsConnected()); ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); @@ -417,33 +402,32 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index emulated_controllers[player_index]->clear(); pairs.emplace_back(emulated_controllers[player_index]->count(), - Settings::ControllerType::ProController); + Core::HID::NpadType::ProController); emulated_controllers[player_index]->addItem(tr("Pro Controller")); pairs.emplace_back(emulated_controllers[player_index]->count(), - Settings::ControllerType::DualJoyconDetached); + Core::HID::NpadType::JoyconDual); emulated_controllers[player_index]->addItem(tr("Dual Joycons")); pairs.emplace_back(emulated_controllers[player_index]->count(), - Settings::ControllerType::LeftJoycon); + Core::HID::NpadType::JoyconLeft); emulated_controllers[player_index]->addItem(tr("Left Joycon")); pairs.emplace_back(emulated_controllers[player_index]->count(), - Settings::ControllerType::RightJoycon); + Core::HID::NpadType::JoyconRight); emulated_controllers[player_index]->addItem(tr("Right Joycon")); if (player_index == 0) { pairs.emplace_back(emulated_controllers[player_index]->count(), - Settings::ControllerType::Handheld); + Core::HID::NpadType::Handheld); emulated_controllers[player_index]->addItem(tr("Handheld")); } - pairs.emplace_back(emulated_controllers[player_index]->count(), - Settings::ControllerType::GameCube); + pairs.emplace_back(emulated_controllers[player_index]->count(), Core::HID::NpadType::GameCube); emulated_controllers[player_index]->addItem(tr("GameCube Controller")); } -Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex( +Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex( int index, std::size_t player_index) const { const auto& pairs = index_controller_type_pairs[player_index]; @@ -451,13 +435,13 @@ Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex( [index](const auto& pair) { return pair.first == index; }); if (it == pairs.end()) { - return Settings::ControllerType::ProController; + return Core::HID::NpadType::ProController; } return it->second; } -int QtControllerSelectorDialog::GetIndexFromControllerType(Settings::ControllerType type, +int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadType type, std::size_t player_index) const { const auto& pairs = index_controller_type_pairs[player_index]; @@ -481,16 +465,16 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) const QString stylesheet = [this, player_index] { switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), player_index)) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::GameCube: + case Core::HID::NpadType::ProController: + case Core::HID::NpadType::GameCube: return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); - case Settings::ControllerType::DualJoyconDetached: + case Core::HID::NpadType::JoyconDual: return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); "); - case Settings::ControllerType::LeftJoycon: + case Core::HID::NpadType::JoyconLeft: return QStringLiteral("image: url(:/controller/applet_joycon_left%0); "); - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadType::JoyconRight: return QStringLiteral("image: url(:/controller/applet_joycon_right%0); "); - case Settings::ControllerType::Handheld: + case Core::HID::NpadType::Handheld: return QStringLiteral("image: url(:/controller/applet_handheld%0); "); default: return QString{}; @@ -518,54 +502,42 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) } void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { - auto& player = Settings::values.players.GetValue()[player_index]; + auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index); const auto controller_type = GetControllerTypeFromIndex( emulated_controllers[player_index]->currentIndex(), player_index); const auto player_connected = player_groupboxes[player_index]->isChecked() && - controller_type != Settings::ControllerType::Handheld; + controller_type != Core::HID::NpadType::Handheld; - if (player.controller_type == controller_type && player.connected == player_connected) { + if (controller->GetNpadType() == controller_type && + controller->IsConnected() == player_connected) { // Set vibration devices in the event that the input device has changed. ConfigureVibration::SetVibrationDevices(player_index); return; } // Disconnect the controller first. - UpdateController(controller_type, player_index, false, system); - - player.controller_type = controller_type; - player.connected = player_connected; + UpdateController(controller, controller_type, false); ConfigureVibration::SetVibrationDevices(player_index); // Handheld if (player_index == 0) { - auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; - if (controller_type == Settings::ControllerType::Handheld) { - handheld = player; + if (controller_type == Core::HID::NpadType::Handheld) { + auto* handheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + UpdateController(handheld, Core::HID::NpadType::Handheld, + player_groupboxes[player_index]->isChecked()); } - handheld.connected = player_groupboxes[player_index]->isChecked() && - controller_type == Settings::ControllerType::Handheld; - UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected, system); } - if (!player.connected) { - return; - } - - // This emulates a delay between disconnecting and reconnecting controllers as some games - // do not respond to a change in controller type if it was instantaneous. - using namespace std::chrono_literals; - std::this_thread::sleep_for(60ms); - - UpdateController(controller_type, player_index, player_connected, system); + UpdateController(controller, controller_type, player_connected); } void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { if (!player_groupboxes[player_index]->isChecked() || GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), - player_index) == Settings::ControllerType::Handheld) { + player_index) == Core::HID::NpadType::Handheld) { led_patterns_boxes[player_index][0]->setChecked(false); led_patterns_boxes[player_index][1]->setChecked(false); led_patterns_boxes[player_index][2]->setChecked(false); @@ -573,10 +545,12 @@ void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { return; } - led_patterns_boxes[player_index][0]->setChecked(led_patterns[player_index][0]); - led_patterns_boxes[player_index][1]->setChecked(led_patterns[player_index][1]); - led_patterns_boxes[player_index][2]->setChecked(led_patterns[player_index][2]); - led_patterns_boxes[player_index][3]->setChecked(led_patterns[player_index][3]); + const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index); + const auto led_pattern = controller->GetLedPattern(); + led_patterns_boxes[player_index][0]->setChecked(led_pattern.position1); + led_patterns_boxes[player_index][1]->setChecked(led_pattern.position2); + led_patterns_boxes[player_index][2]->setChecked(led_pattern.position3); + led_patterns_boxes[player_index][3]->setChecked(led_pattern.position4); } void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) { @@ -656,10 +630,9 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { } for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { + auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); // Disconnect any unsupported players here and disable or hide them if applicable. - Settings::values.players.GetValue()[index].connected = false; - UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false, - system); + UpdateController(controller, controller->GetNpadType(), false); // Hide the player widgets when max_supported_controllers is less than or equal to 4. if (max_supported_players <= 4) { player_widgets[index]->hide(); diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h index ca09fde04..dd981f479 100644 --- a/src/yuzu/applets/qt_controller.h +++ b/src/yuzu/applets/qt_controller.h @@ -23,10 +23,6 @@ namespace InputCommon { class InputSubsystem; } -namespace Settings { -enum class ControllerType; -} - namespace Ui { class QtControllerSelectorDialog; } @@ -35,6 +31,10 @@ namespace Core { class System; } +namespace Core::HID { +enum class NpadType : u8; +} + class QtControllerSelectorDialog final : public QDialog { Q_OBJECT @@ -74,10 +74,10 @@ private: void SetEmulatedControllers(std::size_t player_index); // Gets the Controller Type for a given controller combobox index per player. - Settings::ControllerType GetControllerTypeFromIndex(int index, std::size_t player_index) const; + Core::HID::NpadType GetControllerTypeFromIndex(int index, std::size_t player_index) const; // Gets the controller combobox index for a given Controller Type per player. - int GetIndexFromControllerType(Settings::ControllerType type, std::size_t player_index) const; + int GetIndexFromControllerType(Core::HID::NpadType type, std::size_t player_index) const; // Updates the controller icons per player. void UpdateControllerIcon(std::size_t player_index); @@ -139,7 +139,7 @@ private: std::array emulated_controllers; /// Pairs of emulated controller index and Controller Type enum per player. - std::array>, NUM_PLAYERS> + std::array>, NUM_PLAYERS> index_controller_type_pairs; // Labels representing the number of connected controllers diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index 7e8731232..3d91f8034 100644 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp @@ -10,6 +10,8 @@ #include "common/settings.h" #include "common/string_util.h" #include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hid/input_interpreter.h" #include "ui_qt_software_keyboard.h" @@ -796,9 +798,10 @@ void QtSoftwareKeyboardDialog::SetTextDrawType() { } void QtSoftwareKeyboardDialog::SetControllerImage() { - const auto controller_type = Settings::values.players.GetValue()[8].connected - ? Settings::values.players.GetValue()[8].controller_type - : Settings::values.players.GetValue()[0].controller_type; + const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + const auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + const auto controller_type = + handheld->IsConnected() ? handheld->GetNpadType() : player_1->GetNpadType(); const QString theme = [] { if (QIcon::themeName().contains(QStringLiteral("dark")) || @@ -810,8 +813,8 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { }(); switch (controller_type) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::GameCube: + case Core::HID::NpadType::ProController: + case Core::HID::NpadType::GameCube: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); ui->icon_controller_shift->setStyleSheet( @@ -819,7 +822,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { ui->icon_controller_num->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); break; - case Settings::ControllerType::DualJoyconDetached: + case Core::HID::NpadType::JoyconDual: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); ui->icon_controller_shift->setStyleSheet( @@ -827,7 +830,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { ui->icon_controller_num->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); break; - case Settings::ControllerType::LeftJoycon: + case Core::HID::NpadType::JoyconLeft: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") .arg(theme)); @@ -838,7 +841,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") .arg(theme)); break; - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadType::JoyconRight: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") .arg(theme)); @@ -849,7 +852,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") .arg(theme)); break; - case Settings::ControllerType::Handheld: + case Core::HID::NpadType::Handheld: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); ui->icon_controller_shift->setStyleSheet( diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 67faa8be8..dece27fde 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -211,8 +211,10 @@ void ConfigureInput::RetranslateUI() { } void ConfigureInput::LoadConfiguration() { + const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + LoadPlayerControllerIndices(); - UpdateDockedState(Settings::values.players.GetValue()[8].connected); + UpdateDockedState(handheld->IsConnected()); ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); @@ -220,9 +222,16 @@ void ConfigureInput::LoadConfiguration() { void ConfigureInput::LoadPlayerControllerIndices() { for (std::size_t i = 0; i < player_connected.size(); ++i) { - const auto connected = Settings::values.players.GetValue()[i].connected || - (i == 0 && Settings::values.players.GetValue()[8].connected); - player_connected[i]->setChecked(connected); + if (i == 0) { + auto* handheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + if (handheld->IsConnected()) { + player_connected[i]->setChecked(true); + continue; + } + } + const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(i); + player_connected[i]->setChecked(controller->IsConnected()); } } diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 93f7eddc9..be87204fc 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -104,8 +104,8 @@ void PlayerControlPreview::UpdateColors() { colors.left = colors.primary; colors.right = colors.primary; // Possible alternative to set colors from settings - // colors.left = QColor(Settings::values.players.GetValue()[player_index].body_color_left); - // colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right); + // colors.left = QColor(controller->GetColors().left.body); + // colors.right = QColor(controller->GetColors().right.body); } void PlayerControlPreview::ResetInputs() { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index ae997ccfa..46a5f62ad 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -832,15 +832,16 @@ void GMainWindow::InitializeWidgets() { dock_status_button->setFocusPolicy(Qt::NoFocus); connect(dock_status_button, &QPushButton::clicked, [&] { const bool is_docked = Settings::values.use_docked_mode.GetValue(); - auto& controller_type = Settings::values.players.GetValue()[0].controller_type; + auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - if (!is_docked && controller_type == Settings::ControllerType::Handheld) { + if (!is_docked && handheld->IsConnected()) { QMessageBox::warning(this, tr("Invalid config detected"), tr("Handheld controller can't be used on docked mode. Pro " "controller will be selected.")); - controller_type = Settings::ControllerType::ProController; - ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), *system); - configure_dialog.ApplyConfiguration(); + handheld->Disconnect(); + player_1->SetNpadType(Core::HID::NpadType::ProController); + player_1->Connect(); } Settings::values.use_docked_mode.SetValue(!is_docked); -- 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 ++++-- src/input_common/drivers/gc_adapter.cpp | 4 +- src/input_common/drivers/udp_client.cpp | 27 +++++ src/yuzu/main.cpp | 2 +- 8 files changed, 159 insertions(+), 91 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{}; diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 4fb6ab5af..25b66f528 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -209,7 +209,7 @@ void GCAdapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_ pads[port].axis_origin[index] = axis_value; pads[port].reset_origin_counter++; } - const f32 axis_status = (axis_value - pads[port].axis_origin[index]) / 110.0f; + const f32 axis_status = (axis_value - pads[port].axis_origin[index]) / 100.0f; SetAxis(pads[port].identifier, static_cast(index), axis_status); } } @@ -530,7 +530,7 @@ std::string GCAdapter::GetUIName(const Common::ParamPackage& params) const { return fmt::format("Button {}", GetUIButtonName(params)); } if (params.Has("axis")) { - return fmt::format("Axis {}", params.Get("axis",0)); + return fmt::format("Axis {}", params.Get("axis", 0)); } return "Bad GC Adapter"; diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 6fcc3a01b..f0c0a6b8b 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -243,6 +243,33 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) { }; const PadIdentifier identifier = GetPadIdentifier(pad_index); SetMotion(identifier, 0, motion); + + for (std::size_t id = 0; id < data.touch.size(); ++id) { + const auto touch_pad = data.touch[id]; + const int touch_id = static_cast(client * 2 + id); + + // TODO: Use custom calibration per device + const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); + const u16 min_x = static_cast(touch_param.Get("min_x", 100)); + const u16 min_y = static_cast(touch_param.Get("min_y", 50)); + const u16 max_x = static_cast(touch_param.Get("max_x", 1800)); + const u16 max_y = static_cast(touch_param.Get("max_y", 850)); + + const f32 x = + static_cast(std::clamp(static_cast(touch_pad.x), min_x, max_x) - min_x) / + static_cast(max_x - min_x); + const f32 y = + static_cast(std::clamp(static_cast(touch_pad.y), min_y, max_y) - min_y) / + static_cast(max_y - min_y); + + if (touch_pad.is_active) { + SetAxis(identifier, touch_id * 2, x); + SetAxis(identifier, touch_id * 2 + 1, y); + SetButton(identifier, touch_id, true); + continue; + } + SetButton(identifier, touch_id, false); + } } void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 46a5f62ad..022d11cc4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2973,7 +2973,7 @@ void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_vie QString GMainWindow::GetTasStateDescription() const { auto [tas_status, current_tas_frame, total_tas_frames] = input_subsystem->GetTas()->GetStatus(); switch (tas_status) { - case InputCommon::TasInput::TasState::Running : + case InputCommon::TasInput::TasState::Running: return tr("TAS state: Running %1/%2").arg(current_tas_frame).arg(total_tas_frames); case InputCommon::TasInput::TasState::Recording: return tr("TAS state: Recording %1").arg(total_tas_frames); -- 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 +- src/input_common/drivers/udp_client.cpp | 2 ++ src/input_common/drivers/udp_client.h | 4 +-- src/input_common/helpers/stick_from_buttons.h | 1 - src/input_common/main.cpp | 7 ++-- 15 files changed, 56 insertions(+), 56 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; diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index f0c0a6b8b..192ab336b 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -268,6 +268,8 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) { SetButton(identifier, touch_id, true); continue; } + SetAxis(identifier, touch_id * 2, 0); + SetAxis(identifier, touch_id * 2 + 1, 0); SetButton(identifier, touch_id, false); } } diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h index 58b2e921d..639325b17 100644 --- a/src/input_common/drivers/udp_client.h +++ b/src/input_common/drivers/udp_client.h @@ -1,6 +1,6 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 Citra Emulator Project // Licensed under GPLv2 or any later version -// Refer to the license.txt file included +// Refer to the license.txt file included. #pragma once diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h index 1d6e24c98..82dff5ca8 100644 --- a/src/input_common/helpers/stick_from_buttons.h +++ b/src/input_common/helpers/stick_from_buttons.h @@ -1,4 +1,3 @@ - // Copyright 2017 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index b048783c9..8f7ce59b7 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -87,25 +87,30 @@ struct InputSubsystem::Impl { void Shutdown() { Input::UnregisterFactory(keyboard->GetEngineName()); + Input::UnregisterFactory(keyboard->GetEngineName()); keyboard.reset(); Input::UnregisterFactory(mouse->GetEngineName()); + Input::UnregisterFactory(mouse->GetEngineName()); mouse.reset(); Input::UnregisterFactory(touch_screen->GetEngineName()); touch_screen.reset(); Input::UnregisterFactory(gcadapter->GetEngineName()); + Input::UnregisterFactory(gcadapter->GetEngineName()); gcadapter.reset(); Input::UnregisterFactory(udp_client->GetEngineName()); udp_client.reset(); Input::UnregisterFactory(tas_input->GetEngineName()); + Input::UnregisterFactory(tas_input->GetEngineName()); tas_input.reset(); #ifdef HAVE_SDL2 Input::UnregisterFactory(sdl->GetEngineName()); + Input::UnregisterFactory(sdl->GetEngineName()); sdl.reset(); #endif @@ -124,8 +129,6 @@ struct InputSubsystem::Impl { devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end()); auto gcadapter_devices = gcadapter->GetInputDevices(); devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end()); - auto tas_input_devices = tas_input->GetInputDevices(); - devices.insert(devices.end(), tas_input_devices.begin(), tas_input_devices.end()); #ifdef HAVE_SDL2 auto sdl_devices = sdl->GetInputDevices(); devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end()); -- 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 ++ src/yuzu/configuration/configure_input_player.cpp | 7 +++++++ 2 files changed, 9 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(); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 81310a5b3..cd33b5711 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -598,8 +598,15 @@ void ConfigureInputPlayer::RetranslateUI() { } void ConfigureInputPlayer::LoadConfiguration() { + emulated_controller->ReloadFromSettings(); + UpdateUI(); UpdateInputDeviceCombobox(); + + if (debug) { + return; + } + const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType(true)); ui->comboControllerType->setCurrentIndex(comboBoxIndex); ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true)); -- 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 ++--- .../configure_input_player_widget.cpp | 2 +- 23 files changed, 117 insertions(+), 136 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 { diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index be87204fc..3f179150d 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -28,7 +28,7 @@ void PlayerControlPreview::SetController(Core::HID::EmulatedController* controll controller = controller_; Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, - .is_service = false, + .is_npad_service = false, }; callback_key = controller->SetCallback(engine_callback); ControllerUpdate(Core::HID::ControllerTriggerType::All); -- 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 + src/input_common/drivers/mouse.cpp | 17 ++- src/input_common/drivers/mouse.h | 1 + src/input_common/input_engine.cpp | 2 + src/input_common/main.cpp | 3 + src/yuzu/configuration/configure_input_player.cpp | 147 +++++++++------------- src/yuzu/configuration/configure_vibration.cpp | 4 +- src/yuzu/debugger/controller.cpp | 3 +- 10 files changed, 102 insertions(+), 105 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 diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 2c2432fb7..1c32b54be 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -121,12 +121,27 @@ void Mouse::StopPanning() { std::vector Mouse::GetInputDevices() const { std::vector devices; devices.emplace_back(Common::ParamPackage{ - {"engine", "keyboard"}, + {"engine", GetEngineName()}, {"display", "Keyboard/Mouse"}, }); return devices; } +AnalogMapping Mouse::GetAnalogMappingForDevice( + [[maybe_unused]] const Common::ParamPackage& params) { + // Only overwrite different buttons from default + AnalogMapping mapping = {}; + Common::ParamPackage right_analog_params; + right_analog_params.Set("engine", GetEngineName()); + right_analog_params.Set("axis_x", 0); + right_analog_params.Set("axis_y", 1); + right_analog_params.Set("threshold", 0.5f); + right_analog_params.Set("range", 1.0f); + right_analog_params.Set("deadzone", 0.0f); + mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params)); + return mapping; +} + std::string Mouse::GetUIName(const Common::ParamPackage& params) const { if (params.Has("button")) { return fmt::format("Mouse {}", params.Get("button", 0)); diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index e8355751a..d3178b1a9 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -55,6 +55,7 @@ public: void ReleaseAllButtons(); std::vector GetInputDevices() const override; + AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; std::string GetUIName(const Common::ParamPackage& params) const override; private: diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 1534f24b0..9cfe0f232 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp @@ -202,6 +202,8 @@ void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int but if (!configuring || !mapping_callback.on_data) { return; } + + PreSetButton(identifier, button); if (value == GetButton(identifier, button)) { return; } diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 8f7ce59b7..07d514ad7 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -143,6 +143,9 @@ struct InputSubsystem::Impl { return {}; } const std::string engine = params.Get("engine", ""); + if (engine == mouse->GetEngineName()) { + return mouse->GetAnalogMappingForDevice(params); + } if (engine == gcadapter->GetEngineName()) { return gcadapter->GetAnalogMappingForDevice(params); } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index cd33b5711..416096333 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -478,37 +478,39 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); - connect(ui->comboControllerType, qOverload(&QComboBox::currentIndexChanged), [this, player_index](int) { - UpdateControllerAvailableButtons(); - UpdateControllerEnabledButtons(); - UpdateControllerButtonNames(); - UpdateMotionButtons(); - const Core::HID::NpadType type = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); - - if (player_index == 0) { - auto* emulated_controller_p1 = - system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = - system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - bool is_connected = emulated_controller->IsConnected(true); - - emulated_controller_p1->SetNpadType(type); - emulated_controller_hanheld->SetNpadType(type); - if (is_connected) { - if (type == Core::HID::NpadType::Handheld) { - emulated_controller_p1->Disconnect(); - emulated_controller_hanheld->Connect(); - emulated_controller = emulated_controller_hanheld; - } else { - emulated_controller_hanheld->Disconnect(); - emulated_controller_p1->Connect(); - emulated_controller = emulated_controller_p1; + connect(ui->comboControllerType, qOverload(&QComboBox::currentIndexChanged), + [this, player_index](int) { + UpdateControllerAvailableButtons(); + UpdateControllerEnabledButtons(); + UpdateControllerButtonNames(); + UpdateMotionButtons(); + const Core::HID::NpadType type = + GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); + + if (player_index == 0) { + auto* emulated_controller_p1 = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + bool is_connected = emulated_controller->IsConnected(true); + + emulated_controller_p1->SetNpadType(type); + emulated_controller_hanheld->SetNpadType(type); + if (is_connected) { + if (type == Core::HID::NpadType::Handheld) { + emulated_controller_p1->Disconnect(); + emulated_controller_hanheld->Connect(); + emulated_controller = emulated_controller_hanheld; + } else { + emulated_controller_hanheld->Disconnect(); + emulated_controller_p1->Connect(); + emulated_controller = emulated_controller_p1; + } + } + ui->controllerFrame->SetController(emulated_controller); } - } - ui->controllerFrame->SetController(emulated_controller); - } - emulated_controller->SetNpadType(type); - }); + emulated_controller->SetNpadType(type); + }); connect(ui->comboDevices, qOverload(&QComboBox::activated), this, &ConfigureInputPlayer::UpdateMappingWithDefaults); @@ -555,7 +557,7 @@ ConfigureInputPlayer::~ConfigureInputPlayer() { } else { emulated_controller->DisableConfiguration(); } -}; +} void ConfigureInputPlayer::ApplyConfiguration() { if (player_index == 0) { @@ -642,7 +644,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { const auto first_engine = devices[0].Get("engine", ""); const auto first_guid = devices[0].Get("guid", ""); - const auto first_port = devices[0].Get("port", ""); + const auto first_port = devices[0].Get("port", 0); if (devices.size() == 1) { const auto devices_it = @@ -650,7 +652,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { [first_engine, first_guid, first_port](const Common::ParamPackage param) { return param.Get("engine", "") == first_engine && param.Get("guid", "") == first_guid && - param.Get("port", "") == first_port; + param.Get("port", 0) == first_port; }); const int device_index = devices_it != input_devices.end() @@ -662,7 +664,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { const auto second_engine = devices[1].Get("engine", ""); const auto second_guid = devices[1].Get("guid", ""); - const auto second_port = devices[1].Get("port", ""); + const auto second_port = devices[1].Get("port", 0); const bool is_keyboard_mouse = (first_engine == "keyboard" || first_engine == "mouse") && (second_engine == "keyboard" || second_engine == "mouse"); @@ -684,7 +686,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { param.Get("guid2", "") == second_guid) || (param.Get("guid", "") == second_guid && param.Get("guid2", "") == first_guid); return param.Get("engine", "") == first_engine && is_guid_valid && - param.Get("port", "") == first_port; + param.Get("port", 0) == first_port; }); const int device_index = devices_it != input_devices.end() @@ -1096,8 +1098,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { emulated_controller->SetMotionParam(motion_id, {}); } - // Reset keyboard bindings - if (ui->comboDevices->currentIndex() == 1) { + // Reset keyboard or mouse bindings + if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) { for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { emulated_controller->SetButtonParam( button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( @@ -1122,63 +1124,30 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { Config::default_motions[motion_id])}); } - UpdateUI(); - return; - } - - // Reset keyboard with mouse bindings - if (ui->comboDevices->currentIndex() == 2) { - for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { - emulated_controller->SetButtonParam( - button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_buttons[button_id])}); - } - - Common::ParamPackage left_analog_param{}; - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { - Common::ParamPackage params{InputCommon::GenerateKeyboardParam( - Config::default_analogs[Settings::NativeAnalog::LStick][sub_button_id])}; - SetAnalogParam(params, left_analog_param, analog_sub_buttons[sub_button_id]); - } - left_analog_param.Set("modifier", - InputCommon::GenerateKeyboardParam( - Config::default_stick_mod[Settings::NativeAnalog::LStick])); - emulated_controller->SetStickParam(Settings::NativeAnalog::LStick, left_analog_param); - - Common::ParamPackage right_analog_param{}; - right_analog_param.Set("engine", "mouse"); - right_analog_param.Set("port", 0); - right_analog_param.Set("axis_x", 0); - right_analog_param.Set("axis_y", 1); - emulated_controller->SetStickParam(Settings::NativeAnalog::RStick, - std::move(right_analog_param)); - - for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { - emulated_controller->SetMotionParam( - motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_motions[motion_id])}); + // If mouse is selected we want to override with mappings from the driver + if (ui->comboDevices->currentIndex() == 1) { + UpdateUI(); + return; } - - UpdateUI(); - return; } // Reset controller bindings const auto& device = input_devices[ui->comboDevices->currentIndex()]; - auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); - auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); - auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device); - for (std::size_t i = 0; i < button_mapping.size(); ++i) { - emulated_controller->SetButtonParam( - i, button_mapping[static_cast(i)]); + auto button_mappings = input_subsystem->GetButtonMappingForDevice(device); + auto analog_mappings = input_subsystem->GetAnalogMappingForDevice(device); + auto motion_mappings = input_subsystem->GetMotionMappingForDevice(device); + + for (const auto& button_mapping : button_mappings) { + const std::size_t index = button_mapping.first; + emulated_controller->SetButtonParam(index, button_mapping.second); } - for (std::size_t i = 0; i < analog_mapping.size(); ++i) { - emulated_controller->SetStickParam( - i, analog_mapping[static_cast(i)]); + for (const auto& analog_mapping : analog_mappings) { + const std::size_t index = analog_mapping.first; + emulated_controller->SetStickParam(index, analog_mapping.second); } - for (std::size_t i = 0; i < motion_mapping.size(); ++i) { - emulated_controller->SetMotionParam( - i, motion_mapping[static_cast(i)]); + for (const auto& motion_mapping : motion_mappings) { + const std::size_t index = motion_mapping.first; + emulated_controller->SetMotionParam(index, motion_mapping.second); } UpdateUI(); @@ -1237,7 +1206,7 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) } // Keyboard/Mouse - if (ui->comboDevices->currentIndex() == 2) { + if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) { return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse"; } @@ -1245,7 +1214,7 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) return params.Get("engine", "") == current_input_device.Get("engine", "") && (params.Get("guid", "") == current_input_device.Get("guid", "") || params.Get("guid", "") == current_input_device.Get("guid2", "")) && - params.Get("port", "") == current_input_device.Get("port", ""); + params.Get("port", 0) == current_input_device.Get("port", 0); } void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index 46a0f3025..f1ce7205d 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -97,7 +97,7 @@ void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { const auto engine = param.Get("engine", ""); const auto guid = param.Get("guid", ""); - const auto port = param.Get("port", ""); + const auto port = param.Get("port", 0); if (engine.empty() || engine == "keyboard" || engine == "mouse" || engine == "tas") { continue; @@ -105,7 +105,7 @@ void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { vibration_param_str += fmt::format("engine:{}", engine); - if (!port.empty()) { + if (port != 0) { vibration_param_str += fmt::format(",port:{}", port); } if (!guid.empty()) { diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp index 3619aed26..f93a46421 100644 --- a/src/yuzu/debugger/controller.cpp +++ b/src/yuzu/debugger/controller.cpp @@ -21,8 +21,7 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent) Qt::WindowMaximizeButtonHint); widget = new PlayerControlPreview(this); - widget->SetController(system.HIDCore().GetEmulatedController( - Core::HID::NpadIdType::Player1)); + widget->SetController(system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1)); QLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(widget); -- 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/common/input.h | 10 ++++++++++ src/core/hid/emulated_controller.cpp | 9 +++++++++ src/input_common/helpers/stick_from_buttons.cpp | 16 ++++++++++++++++ src/input_common/helpers/touch_from_buttons.cpp | 1 + src/input_common/input_poller.cpp | 20 ++++++++++++++++++++ 5 files changed, 56 insertions(+) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index cdacd4689..cb84f1005 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -164,6 +164,16 @@ class InputDevice { public: virtual ~InputDevice() = default; + // Request input device to update if necessary + virtual void SoftUpdate() { + return; + } + + // Force input device to update data regarless of the current state + virtual void ForceUpdate() { + return; + } + void SetCallback(InputCallback callback_) { callback = std::move(callback_); } 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; } diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 38f150746..9101f11ce 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -200,6 +200,22 @@ public: TriggerOnChange(status); } + void ForceUpdate() override{ + up->ForceUpdate(); + down->ForceUpdate(); + left->ForceUpdate(); + right->ForceUpdate(); + modifier->ForceUpdate(); + } + + void SoftUpdate() override { + Input::CallbackStatus status{ + .type = Input::InputType::Stick, + .stick_status = GetStatus(), + }; + TriggerOnChange(status); + } + Input::StickStatus GetStatus() const { Input::StickStatus status{}; status.x.properties = properties; diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index 2abfaf841..bb2bad5b1 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -17,6 +17,7 @@ public: Input::InputCallback button_up_callback{ [this](Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }}; button->SetCallback(button_up_callback); + button->ForceUpdate(); } Input::TouchStatus GetStatus(bool pressed) const { diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 62ade951c..024bd28ef 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -45,6 +45,16 @@ public: }; } + void ForceUpdate() { + const Input::CallbackStatus status{ + .type = Input::InputType::Button, + .button_status = GetStatus(), + }; + + last_button_value = status.button_status.value; + TriggerOnChange(status); + } + void OnChange() { const Input::CallbackStatus status{ .type = Input::InputType::Button, @@ -96,6 +106,16 @@ public: }; } + void ForceUpdate() { + const Input::CallbackStatus status{ + .type = Input::InputType::Button, + .button_status = GetStatus(), + }; + + last_button_value = status.button_status.value; + TriggerOnChange(status); + } + void OnChange() { const Input::CallbackStatus status{ .type = Input::InputType::Button, -- 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 ++++- src/input_common/helpers/stick_from_buttons.cpp | 2 +- src/input_common/input_poller.cpp | 39 +++++++++++++++-- src/yuzu/configuration/configure_input_player.cpp | 2 +- .../configure_input_player_widget.cpp | 17 ++++---- 9 files changed, 109 insertions(+), 46 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; diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 9101f11ce..806a0e8bb 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -200,7 +200,7 @@ public: TriggerOnChange(status); } - void ForceUpdate() override{ + void ForceUpdate() override { up->ForceUpdate(); down->ForceUpdate(); left->ForceUpdate(); diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 024bd28ef..6edb8d900 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -183,6 +183,17 @@ public: return status; } + void ForceUpdate() { + const Input::CallbackStatus status{ + .type = Input::InputType::Stick, + .stick_status = GetStatus(), + }; + + last_axis_x_value = status.stick_status.x.raw_value; + last_axis_y_value = status.stick_status.y.raw_value; + TriggerOnChange(status); + } + void OnChange() { const Input::CallbackStatus status{ .type = Input::InputType::Stick, @@ -448,6 +459,16 @@ public: return static_cast(input_engine->GetBattery(identifier)); } + void ForceUpdate() { + const Input::CallbackStatus status{ + .type = Input::InputType::Battery, + .battery_status = GetStatus(), + }; + + last_battery_value = status.battery_status; + TriggerOnChange(status); + } + void OnChange() { const Input::CallbackStatus status{ .type = Input::InputType::Battery, @@ -579,6 +600,18 @@ public: return status; } + void ForceUpdate() { + const Input::CallbackStatus status{ + .type = Input::InputType::Motion, + .motion_status = GetStatus(), + }; + + last_axis_x_value = status.motion_status.gyro.x.raw_value; + last_axis_y_value = status.motion_status.gyro.y.raw_value; + last_axis_z_value = status.motion_status.gyro.z.raw_value; + TriggerOnChange(status); + } + void OnChange() { const Input::CallbackStatus status{ .type = Input::InputType::Motion, @@ -868,6 +901,9 @@ InputFactory::InputFactory(std::shared_ptr input_engine_) : input_engine(std::move(input_engine_)) {} std::unique_ptr InputFactory::Create(const Common::ParamPackage& params) { + if (params.Has("battery")) { + return CreateBatteryDevice(params); + } if (params.Has("button") && params.Has("axis")) { return CreateTriggerDevice(params); } @@ -892,9 +928,6 @@ std::unique_ptr InputFactory::Create(const Common::ParamPack if (params.Has("axis")) { return CreateAnalogDevice(params); } - if (params.Has("battery")) { - return CreateBatteryDevice(params); - } LOG_ERROR(Input, "Invalid parameters given"); return std::make_unique(); } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 416096333..acb29a6b4 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -630,7 +630,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { return; } - const auto devices = emulated_controller->GetMappedDevices(); + const auto devices = emulated_controller->GetMappedDevices(Core::HID::DeviceIndex::AllDevices); UpdateInputDevices(); if (devices.empty()) { diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 3f179150d..67e56ed3a 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -356,7 +356,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) DrawCircle(p, center + QPoint(26, 71), 5); // Draw battery - DrawBattery(p, center + QPoint(-170, -140), battery_values[0]); + DrawBattery(p, center + QPoint(-170, -140), battery_values[Core::HID::DeviceIndex::LeftIndex]); } void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) { @@ -482,7 +482,7 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); // Draw battery - DrawBattery(p, center + QPoint(110, -140), battery_values[1]); + DrawBattery(p, center + QPoint(110, -140), battery_values[Core::HID::DeviceIndex::RightIndex]); } void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { @@ -618,8 +618,8 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); // Draw battery - DrawBattery(p, center + QPoint(-100, -160), battery_values[0]); - DrawBattery(p, center + QPoint(40, -160), battery_values[1]); + DrawBattery(p, center + QPoint(-100, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(40, -160), battery_values[Core::HID::DeviceIndex::RightIndex]); } void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) { @@ -720,9 +720,8 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); // Draw battery - DrawBattery(p, center + QPoint(-200, 110), battery_values[0]); - DrawBattery(p, center + QPoint(-30, 110), battery_values[1]); - DrawBattery(p, center + QPoint(130, 110), battery_values[2]); + DrawBattery(p, center + QPoint(-200, 110), battery_values[Core::HID::DeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(130, 110), battery_values[Core::HID::DeviceIndex::RightIndex]); } void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { @@ -812,7 +811,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); // Draw battery - DrawBattery(p, center + QPoint(-30, -160), battery_values[0]); + DrawBattery(p, center + QPoint(-30, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]); } void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { @@ -868,7 +867,7 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8); // Draw battery - DrawBattery(p, center + QPoint(-30, -165), battery_values[0]); + DrawBattery(p, center + QPoint(-30, -165), battery_values[Core::HID::DeviceIndex::LeftIndex]); } constexpr std::array symbol_a = { -- 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 +++++++++- src/input_common/drivers/sdl_driver.cpp | 33 +++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 15 deletions(-) (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; diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index d56351815..53e282ef3 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -94,7 +94,6 @@ public: bool RumblePlay(const Input::VibrationStatus vibration) { constexpr u32 rumble_max_duration_ms = 1000; - if (sdl_controller) { return SDL_GameControllerRumble( sdl_controller.get(), static_cast(vibration.low_amplitude), @@ -520,25 +519,31 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, const Input::VibrationStatus vibration) { const auto joystick = GetSDLJoystickByGUID(identifier.guid.Format(), static_cast(identifier.port)); - const auto process_amplitude = [](f32 amplitude) { - return (amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF; + const auto process_amplitude_exp = [](f32 amplitude, f32 factor) { + return (amplitude + std::pow(amplitude, factor)) * 0.5f * 0xFFFF; }; - const Input::VibrationStatus exponential_vibration{ - .low_amplitude = process_amplitude(vibration.low_amplitude), + + // Default exponential curve for rumble + f32 factor = 0.35f; + + // If vibration is set as a linear output use a flatter value + if (vibration.type == Input::VibrationAmplificationType::Linear) { + factor = 0.5f; + } + + // Amplitude for HD rumble needs no modification + if (joystick->HasHDRumble()) { + factor = 1.0f; + } + + const Input::VibrationStatus new_vibration{ + .low_amplitude = process_amplitude_exp(vibration.low_amplitude, factor), .low_frequency = vibration.low_frequency, - .high_amplitude = process_amplitude(vibration.high_amplitude), + .high_amplitude = process_amplitude_exp(vibration.high_amplitude, factor), .high_frequency = vibration.high_frequency, .type = Input::VibrationAmplificationType::Exponential, }; - Input::VibrationStatus new_vibration{}; - - if (vibration.type == Input::VibrationAmplificationType::Linear || joystick->HasHDRumble()) { - new_vibration = vibration; - } else { - new_vibration = exponential_vibration; - } - if (!joystick->RumblePlay(new_vibration)) { return Input::VibrationError::Unknown; } -- 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/common/settings.h | 1 - src/core/hid/emulated_controller.cpp | 72 ++++++++++++++++++++++++++++++++ src/core/hid/emulated_controller.h | 9 ++++ src/yuzu/configuration/config.cpp | 2 - src/yuzu/configuration/configure_tas.cpp | 2 - src/yuzu/configuration/configure_tas.ui | 9 +--- 6 files changed, 82 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/common/settings.h b/src/common/settings.h index 4cf28617c..dac44d000 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -567,7 +567,6 @@ struct Values { BasicSetting pause_tas_on_load{true, "pause_tas_on_load"}; BasicSetting tas_enable{false, "tas_enable"}; BasicSetting tas_loop{false, "tas_loop"}; - BasicSetting tas_swap_controllers{true, "tas_swap_controllers"}; BasicSetting mouse_panning{false, "mouse_panning"}; BasicRangedSetting mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; 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; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 56af07507..7a748d9c8 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -573,7 +573,6 @@ void Config::ReadControlValues() { ReadBasicSetting(Settings::values.tas_enable); ReadBasicSetting(Settings::values.tas_loop); - ReadBasicSetting(Settings::values.tas_swap_controllers); ReadBasicSetting(Settings::values.pause_tas_on_load); ReadGlobalSetting(Settings::values.use_docked_mode); @@ -1209,7 +1208,6 @@ void Config::SaveControlValues() { WriteBasicSetting(Settings::values.tas_enable); WriteBasicSetting(Settings::values.tas_loop); - WriteBasicSetting(Settings::values.tas_swap_controllers); WriteBasicSetting(Settings::values.pause_tas_on_load); qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp index 8e5a4c72d..979a8db61 100644 --- a/src/yuzu/configuration/configure_tas.cpp +++ b/src/yuzu/configuration/configure_tas.cpp @@ -32,7 +32,6 @@ void ConfigureTasDialog::LoadConfiguration() { ui->tas_path_edit->setText( QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir))); ui->tas_enable->setChecked(Settings::values.tas_enable.GetValue()); - ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers.GetValue()); ui->tas_loop_script->setChecked(Settings::values.tas_loop.GetValue()); ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load.GetValue()); } @@ -40,7 +39,6 @@ void ConfigureTasDialog::LoadConfiguration() { void ConfigureTasDialog::ApplyConfiguration() { Common::FS::SetYuzuPath(Common::FS::YuzuPath::TASDir, ui->tas_path_edit->text().toStdString()); Settings::values.tas_enable.SetValue(ui->tas_enable->isChecked()); - Settings::values.tas_swap_controllers.SetValue(ui->tas_control_swap->isChecked()); Settings::values.tas_loop.SetValue(ui->tas_loop_script->isChecked()); Settings::values.pause_tas_on_load.SetValue(ui->tas_pause_on_load->isChecked()); } diff --git a/src/yuzu/configuration/configure_tas.ui b/src/yuzu/configuration/configure_tas.ui index 7d44895c4..cf88a5bf0 100644 --- a/src/yuzu/configuration/configure_tas.ui +++ b/src/yuzu/configuration/configure_tas.ui @@ -59,20 +59,13 @@ - - - Automatic controller profile swapping - - - - Loop script - + false -- 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 ++++++++++++------------- src/input_common/drivers/tas_input.cpp | 23 ++++++------- src/input_common/drivers/tas_input.h | 14 ++++---- src/yuzu/bootmanager.cpp | 1 + src/yuzu/debugger/controller.cpp | 60 ++++++++++++++++++++++++++++++++-- src/yuzu/debugger/controller.h | 26 ++++++++++++--- src/yuzu/main.cpp | 2 +- 7 files changed, 122 insertions(+), 48 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); diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 7e7a1d58f..d2748b240 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -141,7 +141,7 @@ void Tas::WriteTasFile(std::u8string file_name) { } } -void Tas::RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis) { +void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) { last_input = { .buttons = buttons, .l_axis = FlipAxisY(left_axis), @@ -195,7 +195,7 @@ void Tas::UpdateThread() { } if (current_command < script_length) { LOG_DEBUG(Input, "Playing TAS {}/{}", current_command, script_length); - size_t frame = current_command++; + const size_t frame = current_command++; for (size_t player_index = 0; player_index < commands.size(); player_index++) { TASCommand command{}; if (frame < commands[player_index].size()) { @@ -207,8 +207,8 @@ void Tas::UpdateThread() { .port = player_index, .pad = 0, }; - for (std::size_t i = 0; i < sizeof(command.buttons); ++i) { - const bool button_status = (command.buttons & (1U << i)) != 0; + for (std::size_t i = 0; i < sizeof(command.buttons) * 8; ++i) { + const bool button_status = (command.buttons & (1LLU << i)) != 0; const int button = static_cast(i); SetButton(identifier, button, button_status); } @@ -244,14 +244,14 @@ TasAnalog Tas::ReadCommandAxis(const std::string& line) const { return {x, y}; } -u32 Tas::ReadCommandButtons(const std::string& data) const { +u64 Tas::ReadCommandButtons(const std::string& data) const { std::stringstream button_text(data); std::string line; - u32 buttons = 0; + u64 buttons = 0; while (std::getline(button_text, line, ';')) { for (auto [text, tas_button] : text_to_tas_button) { if (text == line) { - buttons |= static_cast(tas_button); + buttons |= static_cast(tas_button); break; } } @@ -259,13 +259,14 @@ u32 Tas::ReadCommandButtons(const std::string& data) const { return buttons; } -std::string Tas::WriteCommandButtons(u32 buttons) const { +std::string Tas::WriteCommandButtons(u64 buttons) const { std::string returns = ""; for (auto [text_button, tas_button] : text_to_tas_button) { - if ((buttons & static_cast(tas_button)) != 0) - returns += fmt::format("{};", text_button.substr(4)); + if ((buttons & static_cast(tas_button)) != 0) { + returns += fmt::format("{};", text_button); + } } - return returns.empty() ? "NONE" : returns.substr(2); + return returns.empty() ? "NONE" : returns; } std::string Tas::WriteCommandAxis(TasAnalog analog) const { diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h index 9fadc118b..5f5c3267c 100644 --- a/src/input_common/drivers/tas_input.h +++ b/src/input_common/drivers/tas_input.h @@ -47,7 +47,7 @@ namespace InputCommon::TasInput { constexpr size_t PLAYER_NUMBER = 10; -enum class TasButton : u32 { +enum class TasButton : u64 { BUTTON_A = 1U << 0, BUTTON_B = 1U << 1, BUTTON_X = 1U << 2, @@ -92,7 +92,7 @@ public: * @param left_axis: value of the left axis * @param right_axis: value of the right axis */ - void RecordInput(u32 buttons, TasAnalog left_axis, TasAnalog right_axis); + void RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis); // Main loop that records or executes input void UpdateThread(); @@ -129,7 +129,7 @@ public: private: struct TASCommand { - u32 buttons{}; + u64 buttons{}; TasAnalog l_axis{}; TasAnalog r_axis{}; }; @@ -164,9 +164,9 @@ private: * Parses a string containing the button values. Each button is represented by it's text format * specified in text_to_tas_button array * @param line: string containing button name with the following format "a;b;c;d..." - * @return Returns a u32 with each bit representing the status of a button + * @return Returns a u64 with each bit representing the status of a button */ - u32 ReadCommandButtons(const std::string& line) const; + u64 ReadCommandButtons(const std::string& line) const; /** * Reset state of all players @@ -174,11 +174,11 @@ private: void ClearInput(); /** - * Converts an u32 containing the button status into the text equivalent + * Converts an u64 containing the button status into the text equivalent * @param buttons: bitfield with the status of the buttons * @return Returns a string with the name of the buttons to be written to the file */ - std::string WriteCommandButtons(u32 buttons) const; + std::string WriteCommandButtons(u64 buttons) const; /** * Converts an TAS analog object containing the axis status into the text equivalent diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 726f789b7..4b3cd9f3e 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -35,6 +35,7 @@ #include "core/frontend/framebuffer_layout.h" #include "input_common/drivers/keyboard.h" #include "input_common/drivers/mouse.h" +#include "input_common/drivers/tas_input.h" #include "input_common/drivers/touch_screen.h" #include "input_common/main.h" #include "video_core/renderer_base.h" diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp index f93a46421..aaca494b8 100644 --- a/src/yuzu/debugger/controller.cpp +++ b/src/yuzu/debugger/controller.cpp @@ -7,11 +7,16 @@ #include #include "common/settings.h" #include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "input_common/drivers/tas_input.h" +#include "input_common/main.h" #include "yuzu/configuration/configure_input_player_widget.h" #include "yuzu/debugger/controller.h" -ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent) - : QWidget(parent, Qt::Dialog) { +ControllerDialog::ControllerDialog(Core::System& system_, + std::shared_ptr input_subsystem_, + QWidget* parent) + : QWidget(parent, Qt::Dialog), system{system_}, input_subsystem{input_subsystem_} { setObjectName(QStringLiteral("Controller")); setWindowTitle(tr("Controller P1")); resize(500, 350); @@ -21,7 +26,7 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent) Qt::WindowMaximizeButtonHint); widget = new PlayerControlPreview(this); - widget->SetController(system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1)); + refreshConfiguration(); QLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(widget); @@ -34,6 +39,22 @@ ControllerDialog::ControllerDialog(Core::System& system, QWidget* parent) widget->setFocus(); } +void ControllerDialog::refreshConfiguration() { + UnloadController(); + auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + // Display the correct controller + controller = handheld->IsConnected() ? handheld : player_1; + + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, + .is_npad_service = true, + }; + callback_key = controller->SetCallback(engine_callback); + widget->SetController(controller); + is_controller_set = true; +} + QAction* ControllerDialog::toggleViewAction() { if (toggle_view_action == nullptr) { toggle_view_action = new QAction(tr("&Controller P1"), this); @@ -47,6 +68,10 @@ QAction* ControllerDialog::toggleViewAction() { void ControllerDialog::UnloadController() { widget->UnloadController(); + if (is_controller_set) { + controller->DeleteCallback(callback_key); + is_controller_set = false; + } } void ControllerDialog::showEvent(QShowEvent* ev) { @@ -62,3 +87,32 @@ void ControllerDialog::hideEvent(QHideEvent* ev) { } QWidget::hideEvent(ev); } + +void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) { + // TODO(german77): Remove TAS from here + switch (type) { + case Core::HID::ControllerTriggerType::Button: + case Core::HID::ControllerTriggerType::Stick: { + const auto buttons_values = controller->GetButtonsValues(); + const auto stick_values = controller->GetSticksValues(); + u64 buttons = 0; + std::size_t index = 0; + for (const auto& button : buttons_values) { + buttons |= button.value ? 1LLU << index : 0; + index++; + } + const InputCommon::TasInput::TasAnalog left_axis = { + .x = stick_values[Settings::NativeAnalog::LStick].x.value, + .y = stick_values[Settings::NativeAnalog::LStick].y.value, + }; + const InputCommon::TasInput::TasAnalog right_axis = { + .x = stick_values[Settings::NativeAnalog::RStick].x.value, + .y = stick_values[Settings::NativeAnalog::RStick].y.value, + }; + input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis); + break; + } + default: + break; + } +} diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h index 33f617b9b..ba4185a4b 100644 --- a/src/yuzu/debugger/controller.h +++ b/src/yuzu/debugger/controller.h @@ -11,24 +11,33 @@ class QHideEvent; class QShowEvent; class PlayerControlPreview; +namespace InputCommon { +class InputSubsystem; +} + namespace Core { class System; } -namespace InputCommon { -class InputSubsystem; +namespace Core::HID { +class EmulatedController; } class ControllerDialog : public QWidget { Q_OBJECT public: - explicit ControllerDialog(Core::System& system, QWidget* parent = nullptr); + explicit ControllerDialog(Core::System& system_, + std::shared_ptr input_subsystem_, + QWidget* parent = nullptr); /// Returns a QAction that can be used to toggle visibility of this dialog. QAction* toggleViewAction(); - // Disables events from the emulated controller + /// Reloads the widget to apply any changes in the configuration + void refreshConfiguration(); + + /// Disables events from the emulated controller void UnloadController(); protected: @@ -36,6 +45,15 @@ protected: void hideEvent(QHideEvent* ev) override; private: + /// Redirects input from the widget to the TAS driver + void ControllerUpdate(Core::HID::ControllerTriggerType type); + + int callback_key; + bool is_controller_set{}; + Core::HID::EmulatedController* controller; + QAction* toggle_view_action = nullptr; PlayerControlPreview* widget; + Core::System& system; + std::shared_ptr input_subsystem; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 022d11cc4..56db337a4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -925,7 +925,7 @@ void GMainWindow::InitializeDebugWidgets() { waitTreeWidget->hide(); debug_menu->addAction(waitTreeWidget->toggleViewAction()); - controller_dialog = new ControllerDialog(*system, this); + controller_dialog = new ControllerDialog(*system, input_subsystem, this); controller_dialog->hide(); debug_menu->addAction(controller_dialog->toggleViewAction()); -- 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/common/input.h | 4 +- src/common/settings.h | 1 - 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 +- src/input_common/drivers/gc_adapter.cpp | 10 +- src/input_common/drivers/gc_adapter.h | 7 +- src/input_common/drivers/keyboard.h | 2 +- src/input_common/drivers/mouse.h | 2 +- src/input_common/drivers/sdl_driver.cpp | 16 +- src/input_common/drivers/sdl_driver.h | 7 +- src/input_common/drivers/touch_screen.h | 2 +- src/input_common/helpers/stick_from_buttons.cpp | 70 +++---- src/input_common/helpers/stick_from_buttons.h | 4 +- src/input_common/helpers/touch_from_buttons.cpp | 29 +-- src/input_common/helpers/touch_from_buttons.h | 4 +- src/input_common/input_engine.h | 14 +- src/input_common/input_poller.cpp | 202 +++++++++++---------- src/input_common/input_poller.h | 32 ++-- src/input_common/main.cpp | 76 ++++---- .../configure_input_player_widget.cpp | 105 ++++++----- .../configuration/configure_input_player_widget.h | 81 +++++---- 31 files changed, 534 insertions(+), 466 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index cb84f1005..6d3227f5e 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -12,7 +12,7 @@ #include "common/logging/log.h" #include "common/param_package.h" -namespace Input { +namespace Common::Input { enum class InputType { None, @@ -296,4 +296,4 @@ std::unique_ptr CreateDevice(const Common::ParamPackage package return pair->second->Create(package); } -} // namespace Input +} // namespace Common::Input diff --git a/src/common/settings.h b/src/common/settings.h index dac44d000..95225fba7 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -6,7 +6,6 @@ #include #include -#include #include #include #include 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; } diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 62dc28711..2550f8cba 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -248,7 +248,7 @@ bool GCAdapter::Setup() { std::size_t port = 0; for (GCController& pad : pads) { pad.identifier = { - .guid = Common::UUID{""}, + .guid = Common::UUID{Common::INVALID_UUID}, .port = port++, .pad = 0, }; @@ -325,8 +325,8 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) { return true; } -Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, - const Input::VibrationStatus vibration) { +Common::Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, + const Common::Input::VibrationStatus vibration) { const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; const auto processed_amplitude = static_cast((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8); @@ -334,9 +334,9 @@ Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier, pads[identifier.port].rumble_amplitude = processed_amplitude; if (!rumble_enabled) { - return Input::VibrationError::Disabled; + return Common::Input::VibrationError::Disabled; } - return Input::VibrationError::None; + return Common::Input::VibrationError::None; } void GCAdapter::UpdateVibrations() { diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index b82e4803d..fba90352e 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -4,8 +4,11 @@ #pragma once +#include +#include #include #include +#include #include #include "input_common/input_engine.h" @@ -24,8 +27,8 @@ public: explicit GCAdapter(const std::string input_engine_); ~GCAdapter(); - Input::VibrationError SetRumble(const PadIdentifier& identifier, - const Input::VibrationStatus vibration) override; + Common::Input::VibrationError SetRumble( + const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override; /// Used for automapping features std::vector GetInputDevices() const override; diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h index a3e0d8a61..58df15050 100644 --- a/src/input_common/drivers/keyboard.h +++ b/src/input_common/drivers/keyboard.h @@ -35,7 +35,7 @@ public: private: const PadIdentifier identifier = { - .guid = Common::UUID{""}, + .guid = Common::UUID{Common::INVALID_UUID}, .port = 0, .pad = 0, }; diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index d3178b1a9..cf0918409 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -63,7 +63,7 @@ private: void StopPanning(); const PadIdentifier identifier = { - .guid = Common::UUID{""}, + .guid = Common::UUID{Common::INVALID_UUID}, .port = 0, .pad = 0, }; diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 53e282ef3..1e3741e0f 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -92,7 +92,7 @@ public: return motion; } - bool RumblePlay(const Input::VibrationStatus vibration) { + bool RumblePlay(const Common::Input::VibrationStatus vibration) { constexpr u32 rumble_max_duration_ms = 1000; if (sdl_controller) { return SDL_GameControllerRumble( @@ -515,8 +515,8 @@ std::vector SDLDriver::GetInputDevices() const { } return devices; } -Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, - const Input::VibrationStatus vibration) { +Common::Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, + const Common::Input::VibrationStatus vibration) { const auto joystick = GetSDLJoystickByGUID(identifier.guid.Format(), static_cast(identifier.port)); const auto process_amplitude_exp = [](f32 amplitude, f32 factor) { @@ -527,7 +527,7 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, f32 factor = 0.35f; // If vibration is set as a linear output use a flatter value - if (vibration.type == Input::VibrationAmplificationType::Linear) { + if (vibration.type == Common::Input::VibrationAmplificationType::Linear) { factor = 0.5f; } @@ -536,19 +536,19 @@ Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier, factor = 1.0f; } - const Input::VibrationStatus new_vibration{ + const Common::Input::VibrationStatus new_vibration{ .low_amplitude = process_amplitude_exp(vibration.low_amplitude, factor), .low_frequency = vibration.low_frequency, .high_amplitude = process_amplitude_exp(vibration.high_amplitude, factor), .high_frequency = vibration.high_frequency, - .type = Input::VibrationAmplificationType::Exponential, + .type = Common::Input::VibrationAmplificationType::Exponential, }; if (!joystick->RumblePlay(new_vibration)) { - return Input::VibrationError::Unknown; + return Common::Input::VibrationError::Unknown; } - return Input::VibrationError::None; + return Common::Input::VibrationError::None; } Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, float value) const { diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 1ff85f48d..b879df8ab 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -58,8 +58,8 @@ public: std::string GetHatButtonName(u8 direction_value) const override; u8 GetHatButtonId(const std::string direction_name) const override; - Input::VibrationError SetRumble(const PadIdentifier& identifier, - const Input::VibrationStatus vibration) override; + Common::Input::VibrationError SetRumble( + const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override; private: void InitJoystick(int joystick_index); @@ -105,9 +105,6 @@ private: /// Returns true if the button is on the left joycon bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; - // Set to true if SDL supports game controller subsystem - bool has_gamecontroller = false; - /// Map of GUID of a list of corresponding virtual Joysticks std::unordered_map>> joystick_map; std::mutex joystick_map_mutex; diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h index 5fbb2f47f..d297d253c 100644 --- a/src/input_common/drivers/touch_screen.h +++ b/src/input_common/drivers/touch_screen.h @@ -41,7 +41,7 @@ public: private: const PadIdentifier identifier = { - .guid = Common::UUID{""}, + .guid = Common::UUID{Common::INVALID_UUID}, .port = 0, .pad = 0, }; diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 806a0e8bb..1d5948f79 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -10,25 +10,27 @@ namespace InputCommon { -class Stick final : public Input::InputDevice { +class Stick final : public Common::Input::InputDevice { public: - using Button = std::unique_ptr; + using Button = std::unique_ptr; Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_, float modifier_scale_, float modifier_angle_) : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_), modifier_angle(modifier_angle_) { - Input::InputCallback button_up_callback{ - [this](Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }}; - Input::InputCallback button_down_callback{ - [this](Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }}; - Input::InputCallback button_left_callback{ - [this](Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }}; - Input::InputCallback button_right_callback{ - [this](Input::CallbackStatus callback_) { UpdateRightButtonStatus(callback_); }}; - Input::InputCallback button_modifier_callback{ - [this](Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }}; + Common::Input::InputCallback button_up_callback{ + [this](Common::Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }}; + Common::Input::InputCallback button_down_callback{ + [this](Common::Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }}; + Common::Input::InputCallback button_left_callback{ + [this](Common::Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }}; + Common::Input::InputCallback button_right_callback{ + [this](Common::Input::CallbackStatus callback_) { + UpdateRightButtonStatus(callback_); + }}; + Common::Input::InputCallback button_modifier_callback{ + [this](Common::Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }}; up->SetCallback(button_up_callback); down->SetCallback(button_down_callback); left->SetCallback(button_left_callback); @@ -129,27 +131,27 @@ public: } } - void UpdateUpButtonStatus(Input::CallbackStatus button_callback) { + void UpdateUpButtonStatus(Common::Input::CallbackStatus button_callback) { up_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateDownButtonStatus(Input::CallbackStatus button_callback) { + void UpdateDownButtonStatus(Common::Input::CallbackStatus button_callback) { down_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateLeftButtonStatus(Input::CallbackStatus button_callback) { + void UpdateLeftButtonStatus(Common::Input::CallbackStatus button_callback) { left_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateRightButtonStatus(Input::CallbackStatus button_callback) { + void UpdateRightButtonStatus(Common::Input::CallbackStatus button_callback) { right_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateModButtonStatus(Input::CallbackStatus button_callback) { + void UpdateModButtonStatus(Common::Input::CallbackStatus button_callback) { modifier_status = button_callback.button_status.value; UpdateStatus(); } @@ -193,8 +195,8 @@ public: } last_update = now; - Input::CallbackStatus status{ - .type = Input::InputType::Stick, + Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Stick, .stick_status = GetStatus(), }; TriggerOnChange(status); @@ -209,15 +211,15 @@ public: } void SoftUpdate() override { - Input::CallbackStatus status{ - .type = Input::InputType::Stick, + Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Stick, .stick_status = GetStatus(), }; TriggerOnChange(status); } - Input::StickStatus GetStatus() const { - Input::StickStatus status{}; + Common::Input::StickStatus GetStatus() const { + Common::Input::StickStatus status{}; status.x.properties = properties; status.y.properties = properties; if (Settings::values.emulate_analog_keyboard) { @@ -263,19 +265,23 @@ private: bool left_status; bool right_status; bool modifier_status; - const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; + const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; std::chrono::time_point last_update; }; -std::unique_ptr StickFromButton::Create(const Common::ParamPackage& params) { +std::unique_ptr StickFromButton::Create( + const Common::ParamPackage& params) { const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); - auto up = Input::CreateDeviceFromString(params.Get("up", null_engine)); - auto down = Input::CreateDeviceFromString(params.Get("down", null_engine)); - auto left = Input::CreateDeviceFromString(params.Get("left", null_engine)); - auto right = - Input::CreateDeviceFromString(params.Get("right", null_engine)); - auto modifier = - Input::CreateDeviceFromString(params.Get("modifier", null_engine)); + auto up = Common::Input::CreateDeviceFromString( + params.Get("up", null_engine)); + auto down = Common::Input::CreateDeviceFromString( + params.Get("down", null_engine)); + auto left = Common::Input::CreateDeviceFromString( + params.Get("left", null_engine)); + auto right = Common::Input::CreateDeviceFromString( + params.Get("right", null_engine)); + auto modifier = Common::Input::CreateDeviceFromString( + params.Get("modifier", null_engine)); auto modifier_scale = params.Get("modifier_scale", 0.5f); auto modifier_angle = params.Get("modifier_angle", 5.5f); return std::make_unique(std::move(up), std::move(down), std::move(left), diff --git a/src/input_common/helpers/stick_from_buttons.h b/src/input_common/helpers/stick_from_buttons.h index 82dff5ca8..437ace4f7 100644 --- a/src/input_common/helpers/stick_from_buttons.h +++ b/src/input_common/helpers/stick_from_buttons.h @@ -12,7 +12,7 @@ namespace InputCommon { * An analog device factory that takes direction button devices and combines them into a analog * device. */ -class StickFromButton final : public Input::Factory { +class StickFromButton final : public Common::Input::Factory { public: /** * Creates an analog device from direction button devices @@ -24,7 +24,7 @@ public: * - "modifier": a serialized ParamPackage for creating a button device as the modifier * - "modifier_scale": a float for the multiplier the modifier gives to the position */ - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; }; } // namespace InputCommon diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index bb2bad5b1..fee41cae3 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -9,22 +9,22 @@ namespace InputCommon { -class TouchFromButtonDevice final : public Input::InputDevice { +class TouchFromButtonDevice final : public Common::Input::InputDevice { public: - using Button = std::unique_ptr; + using Button = std::unique_ptr; TouchFromButtonDevice(Button button_, u32 touch_id_, float x_, float y_) : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { - Input::InputCallback button_up_callback{ - [this](Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }}; + Common::Input::InputCallback button_up_callback{ + [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }}; button->SetCallback(button_up_callback); button->ForceUpdate(); } - Input::TouchStatus GetStatus(bool pressed) const { - const Input::ButtonStatus button_status{ + Common::Input::TouchStatus GetStatus(bool pressed) const { + const Common::Input::ButtonStatus button_status{ .value = pressed, }; - Input::TouchStatus status{ + Common::Input::TouchStatus status{ .pressed = button_status, .x = {}, .y = {}, @@ -42,9 +42,9 @@ public: return status; } - void UpdateButtonStatus(Input::CallbackStatus button_callback) { - const Input::CallbackStatus status{ - .type = Input::InputType::Touch, + void UpdateButtonStatus(Common::Input::CallbackStatus button_callback) { + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Touch, .touch_status = GetStatus(button_callback.button_status.value), }; TriggerOnChange(status); @@ -55,13 +55,14 @@ private: const u32 touch_id; const float x; const float y; - const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; + const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; }; -std::unique_ptr TouchFromButton::Create(const Common::ParamPackage& params) { +std::unique_ptr TouchFromButton::Create( + const Common::ParamPackage& params) { const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); - auto button = - Input::CreateDeviceFromString(params.Get("button", null_engine)); + auto button = Common::Input::CreateDeviceFromString( + params.Get("button", null_engine)); const auto touch_id = params.Get("touch_id", 0); const float x = params.Get("x", 0.0f) / 1280.0f; const float y = params.Get("y", 0.0f) / 720.0f; diff --git a/src/input_common/helpers/touch_from_buttons.h b/src/input_common/helpers/touch_from_buttons.h index 21b353728..628f18215 100644 --- a/src/input_common/helpers/touch_from_buttons.h +++ b/src/input_common/helpers/touch_from_buttons.h @@ -11,12 +11,12 @@ namespace InputCommon { /** * A touch device factory that takes a list of button devices and combines them into a touch device. */ -class TouchFromButton final : public Input::Factory { +class TouchFromButton final : public Common::Input::Factory { public: /** * Creates a touch device from a list of button devices */ - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; }; } // namespace InputCommon diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index 31ce900d7..ed79d3d93 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -116,22 +116,22 @@ public: // Sets a led pattern for a controller virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Input::LedStatus led_status) { + [[maybe_unused]] const Common::Input::LedStatus led_status) { return; } // Sets rumble to a controller - virtual Input::VibrationError SetRumble( + virtual Common::Input::VibrationError SetRumble( [[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Input::VibrationStatus vibration) { - return Input::VibrationError::NotSupported; + [[maybe_unused]] const Common::Input::VibrationStatus vibration) { + return Common::Input::VibrationError::NotSupported; } // Sets polling mode to a controller - virtual Input::PollingError SetPollingMode( + virtual Common::Input::PollingError SetPollingMode( [[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Input::PollingMode vibration) { - return Input::PollingError::NotSupported; + [[maybe_unused]] const Common::Input::PollingMode vibration) { + return Common::Input::PollingError::NotSupported; } // Returns the engine name diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 6edb8d900..2b3b77938 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -10,13 +10,13 @@ namespace InputCommon { -class DummyInput final : public Input::InputDevice { +class DummyInput final : public Common::Input::InputDevice { public: explicit DummyInput() {} ~DummyInput() {} }; -class InputFromButton final : public Input::InputDevice { +class InputFromButton final : public Common::Input::InputDevice { public: explicit InputFromButton(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_, InputEngine* input_engine_) @@ -37,7 +37,7 @@ public: input_engine->DeleteCallback(callback_key); } - Input::ButtonStatus GetStatus() const { + Common::Input::ButtonStatus GetStatus() const { return { .value = input_engine->GetButton(identifier, button), .inverted = inverted, @@ -46,8 +46,8 @@ public: } void ForceUpdate() { - const Input::CallbackStatus status{ - .type = Input::InputType::Button, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Button, .button_status = GetStatus(), }; @@ -56,8 +56,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Button, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Button, .button_status = GetStatus(), }; @@ -77,7 +77,7 @@ private: InputEngine* input_engine; }; -class InputFromHatButton final : public Input::InputDevice { +class InputFromHatButton final : public Common::Input::InputDevice { public: explicit InputFromHatButton(PadIdentifier identifier_, u32 button_, u8 direction_, bool toggle_, bool inverted_, InputEngine* input_engine_) @@ -98,7 +98,7 @@ public: input_engine->DeleteCallback(callback_key); } - Input::ButtonStatus GetStatus() const { + Common::Input::ButtonStatus GetStatus() const { return { .value = input_engine->GetHatButton(identifier, button, direction), .inverted = inverted, @@ -107,8 +107,8 @@ public: } void ForceUpdate() { - const Input::CallbackStatus status{ - .type = Input::InputType::Button, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Button, .button_status = GetStatus(), }; @@ -117,8 +117,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Button, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Button, .button_status = GetStatus(), }; @@ -139,11 +139,12 @@ private: InputEngine* input_engine; }; -class InputFromStick final : public Input::InputDevice { +class InputFromStick final : public Common::Input::InputDevice { public: explicit InputFromStick(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, - Input::AnalogProperties properties_x_, - Input::AnalogProperties properties_y_, InputEngine* input_engine_) + Common::Input::AnalogProperties properties_x_, + Common::Input::AnalogProperties properties_y_, + InputEngine* input_engine_) : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_), properties_y(properties_y_), input_engine(input_engine_) { UpdateCallback engine_callback{[this]() { OnChange(); }}; @@ -170,8 +171,8 @@ public: input_engine->DeleteCallback(callback_key_y); } - Input::StickStatus GetStatus() const { - Input::StickStatus status; + Common::Input::StickStatus GetStatus() const { + Common::Input::StickStatus status; status.x = { .raw_value = input_engine->GetAxis(identifier, axis_x), .properties = properties_x, @@ -184,8 +185,8 @@ public: } void ForceUpdate() { - const Input::CallbackStatus status{ - .type = Input::InputType::Stick, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Stick, .stick_status = GetStatus(), }; @@ -195,8 +196,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Stick, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Stick, .stick_status = GetStatus(), }; @@ -212,8 +213,8 @@ private: const PadIdentifier identifier; const u32 axis_x; const u32 axis_y; - const Input::AnalogProperties properties_x; - const Input::AnalogProperties properties_y; + const Common::Input::AnalogProperties properties_x; + const Common::Input::AnalogProperties properties_y; int callback_key_x; int callback_key_y; float last_axis_x_value; @@ -221,12 +222,13 @@ private: InputEngine* input_engine; }; -class InputFromTouch final : public Input::InputDevice { +class InputFromTouch final : public Common::Input::InputDevice { public: explicit InputFromTouch(PadIdentifier identifier_, u32 touch_id_, u32 button_, bool toggle_, bool inverted_, u32 axis_x_, u32 axis_y_, - Input::AnalogProperties properties_x_, - Input::AnalogProperties properties_y_, InputEngine* input_engine_) + Common::Input::AnalogProperties properties_x_, + Common::Input::AnalogProperties properties_y_, + InputEngine* input_engine_) : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_), inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_), properties_y(properties_y_), input_engine(input_engine_) { @@ -263,8 +265,8 @@ public: input_engine->DeleteCallback(callback_key_y); } - Input::TouchStatus GetStatus() const { - Input::TouchStatus status; + Common::Input::TouchStatus GetStatus() const { + Common::Input::TouchStatus status; status.id = touch_id; status.pressed = { .value = input_engine->GetButton(identifier, button), @@ -283,8 +285,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Touch, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Touch, .touch_status = GetStatus(), }; @@ -306,8 +308,8 @@ private: const bool inverted; const u32 axis_x; const u32 axis_y; - const Input::AnalogProperties properties_x; - const Input::AnalogProperties properties_y; + const Common::Input::AnalogProperties properties_x; + const Common::Input::AnalogProperties properties_y; int callback_key_button; int callback_key_x; int callback_key_y; @@ -317,10 +319,10 @@ private: InputEngine* input_engine; }; -class InputFromTrigger final : public Input::InputDevice { +class InputFromTrigger final : public Common::Input::InputDevice { public: explicit InputFromTrigger(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_, - u32 axis_, Input::AnalogProperties properties_, + u32 axis_, Common::Input::AnalogProperties properties_, InputEngine* input_engine_) : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), axis(axis_), properties(properties_), input_engine(input_engine_) { @@ -348,8 +350,8 @@ public: input_engine->DeleteCallback(axis_callback_key); } - Input::TriggerStatus GetStatus() const { - const Input::AnalogStatus analog_status{ + Common::Input::TriggerStatus GetStatus() const { + const Common::Input::AnalogStatus analog_status{ .raw_value = input_engine->GetAxis(identifier, axis), .properties = properties, }; @@ -360,8 +362,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Trigger, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Trigger, .trigger_status = GetStatus(), }; @@ -379,7 +381,7 @@ private: const bool toggle; const bool inverted; const u32 axis; - const Input::AnalogProperties properties; + const Common::Input::AnalogProperties properties; int callback_key_button; int axis_callback_key; bool last_button_value; @@ -387,10 +389,11 @@ private: InputEngine* input_engine; }; -class InputFromAnalog final : public Input::InputDevice { +class InputFromAnalog final : public Common::Input::InputDevice { public: explicit InputFromAnalog(PadIdentifier identifier_, u32 axis_, - Input::AnalogProperties properties_, InputEngine* input_engine_) + Common::Input::AnalogProperties properties_, + InputEngine* input_engine_) : identifier(identifier_), axis(axis_), properties(properties_), input_engine(input_engine_) { UpdateCallback engine_callback{[this]() { OnChange(); }}; @@ -408,7 +411,7 @@ public: input_engine->DeleteCallback(callback_key); } - Input::AnalogStatus GetStatus() const { + Common::Input::AnalogStatus GetStatus() const { return { .raw_value = input_engine->GetAxis(identifier, axis), .properties = properties, @@ -416,8 +419,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Analog, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Analog, .analog_status = GetStatus(), }; @@ -430,13 +433,13 @@ public: private: const PadIdentifier identifier; const u32 axis; - const Input::AnalogProperties properties; + const Common::Input::AnalogProperties properties; int callback_key; float last_axis_value; InputEngine* input_engine; }; -class InputFromBattery final : public Input::InputDevice { +class InputFromBattery final : public Common::Input::InputDevice { public: explicit InputFromBattery(PadIdentifier identifier_, InputEngine* input_engine_) : identifier(identifier_), input_engine(input_engine_) { @@ -447,7 +450,7 @@ public: .index = 0, .callback = engine_callback, }; - last_battery_value = Input::BatteryStatus::Charging; + last_battery_value = Common::Input::BatteryStatus::Charging; callback_key = input_engine->SetCallback(input_identifier); } @@ -455,13 +458,13 @@ public: input_engine->DeleteCallback(callback_key); } - Input::BatteryStatus GetStatus() const { - return static_cast(input_engine->GetBattery(identifier)); + Common::Input::BatteryStatus GetStatus() const { + return static_cast(input_engine->GetBattery(identifier)); } void ForceUpdate() { - const Input::CallbackStatus status{ - .type = Input::InputType::Battery, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Battery, .battery_status = GetStatus(), }; @@ -470,8 +473,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Battery, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Battery, .battery_status = GetStatus(), }; @@ -484,11 +487,11 @@ public: private: const PadIdentifier identifier; int callback_key; - Input::BatteryStatus last_battery_value; + Common::Input::BatteryStatus last_battery_value; InputEngine* input_engine; }; -class InputFromMotion final : public Input::InputDevice { +class InputFromMotion final : public Common::Input::InputDevice { public: explicit InputFromMotion(PadIdentifier identifier_, u32 motion_sensor_, InputEngine* input_engine_) @@ -507,10 +510,10 @@ public: input_engine->DeleteCallback(callback_key); } - Input::MotionStatus GetStatus() const { + Common::Input::MotionStatus GetStatus() const { const auto basic_motion = input_engine->GetMotion(identifier, motion_sensor); - Input::MotionStatus status{}; - const Input::AnalogProperties properties = { + Common::Input::MotionStatus status{}; + const Common::Input::AnalogProperties properties = { .deadzone = 0.001f, .range = 1.0f, .offset = 0.0f, @@ -526,8 +529,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Motion, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Motion, .motion_status = GetStatus(), }; @@ -541,12 +544,13 @@ private: InputEngine* input_engine; }; -class InputFromAxisMotion final : public Input::InputDevice { +class InputFromAxisMotion final : public Common::Input::InputDevice { public: explicit InputFromAxisMotion(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, u32 axis_z_, - Input::AnalogProperties properties_x_, - Input::AnalogProperties properties_y_, - Input::AnalogProperties properties_z_, InputEngine* input_engine_) + Common::Input::AnalogProperties properties_x_, + Common::Input::AnalogProperties properties_y_, + Common::Input::AnalogProperties properties_z_, + InputEngine* input_engine_) : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), axis_z(axis_z_), properties_x(properties_x_), properties_y(properties_y_), properties_z(properties_z_), input_engine(input_engine_) { @@ -583,8 +587,8 @@ public: input_engine->DeleteCallback(callback_key_z); } - Input::MotionStatus GetStatus() const { - Input::MotionStatus status{}; + Common::Input::MotionStatus GetStatus() const { + Common::Input::MotionStatus status{}; status.gyro.x = { .raw_value = input_engine->GetAxis(identifier, axis_x), .properties = properties_x, @@ -601,8 +605,8 @@ public: } void ForceUpdate() { - const Input::CallbackStatus status{ - .type = Input::InputType::Motion, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Motion, .motion_status = GetStatus(), }; @@ -613,8 +617,8 @@ public: } void OnChange() { - const Input::CallbackStatus status{ - .type = Input::InputType::Motion, + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Motion, .motion_status = GetStatus(), }; @@ -633,9 +637,9 @@ private: const u32 axis_x; const u32 axis_y; const u32 axis_z; - const Input::AnalogProperties properties_x; - const Input::AnalogProperties properties_y; - const Input::AnalogProperties properties_z; + const Common::Input::AnalogProperties properties_x; + const Common::Input::AnalogProperties properties_y; + const Common::Input::AnalogProperties properties_z; int callback_key_x; int callback_key_y; int callback_key_z; @@ -645,20 +649,21 @@ private: InputEngine* input_engine; }; -class OutputFromIdentifier final : public Input::OutputDevice { +class OutputFromIdentifier final : public Common::Input::OutputDevice { public: explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) : identifier(identifier_), input_engine(input_engine_) {} - virtual void SetLED(Input::LedStatus led_status) { + virtual void SetLED(Common::Input::LedStatus led_status) { input_engine->SetLeds(identifier, led_status); } - virtual Input::VibrationError SetVibration(Input::VibrationStatus vibration_status) { + virtual Common::Input::VibrationError SetVibration( + Common::Input::VibrationStatus vibration_status) { return input_engine->SetRumble(identifier, vibration_status); } - virtual Input::PollingError SetPollingMode(Input::PollingMode polling_mode) { + virtual Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) { return input_engine->SetPollingMode(identifier, polling_mode); } @@ -667,7 +672,7 @@ private: InputEngine* input_engine; }; -std::unique_ptr InputFactory::CreateButtonDevice( +std::unique_ptr InputFactory::CreateButtonDevice( const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, @@ -690,7 +695,7 @@ std::unique_ptr InputFactory::CreateButtonDevice( input_engine.get()); } -std::unique_ptr InputFactory::CreateHatButtonDevice( +std::unique_ptr InputFactory::CreateHatButtonDevice( const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, @@ -709,7 +714,7 @@ std::unique_ptr InputFactory::CreateHatButtonDevice( input_engine.get()); } -std::unique_ptr InputFactory::CreateStickDevice( +std::unique_ptr InputFactory::CreateStickDevice( const Common::ParamPackage& params) { const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f); const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); @@ -721,7 +726,7 @@ std::unique_ptr InputFactory::CreateStickDevice( }; const auto axis_x = static_cast(params.Get("axis_x", 0)); - const Input::AnalogProperties properties_x = { + const Common::Input::AnalogProperties properties_x = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -730,7 +735,7 @@ std::unique_ptr InputFactory::CreateStickDevice( }; const auto axis_y = static_cast(params.Get("axis_y", 1)); - const Input::AnalogProperties properties_y = { + const Common::Input::AnalogProperties properties_y = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -744,7 +749,7 @@ std::unique_ptr InputFactory::CreateStickDevice( input_engine.get()); } -std::unique_ptr InputFactory::CreateAnalogDevice( +std::unique_ptr InputFactory::CreateAnalogDevice( const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, @@ -753,7 +758,7 @@ std::unique_ptr InputFactory::CreateAnalogDevice( }; const auto axis = static_cast(params.Get("axis", 0)); - const Input::AnalogProperties properties = { + const Common::Input::AnalogProperties properties = { .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f), .range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f), .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), @@ -765,7 +770,7 @@ std::unique_ptr InputFactory::CreateAnalogDevice( return std::make_unique(identifier, axis, properties, input_engine.get()); } -std::unique_ptr InputFactory::CreateTriggerDevice( +std::unique_ptr InputFactory::CreateTriggerDevice( const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, @@ -778,7 +783,7 @@ std::unique_ptr InputFactory::CreateTriggerDevice( const auto inverted = params.Get("inverted", false); const auto axis = static_cast(params.Get("axis", 0)); - const Input::AnalogProperties properties = { + const Common::Input::AnalogProperties properties = { .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f), .range = std::clamp(params.Get("range", 1.0f), 0.25f, 2.50f), .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), @@ -792,7 +797,7 @@ std::unique_ptr InputFactory::CreateTriggerDevice( properties, input_engine.get()); } -std::unique_ptr InputFactory::CreateTouchDevice( +std::unique_ptr InputFactory::CreateTouchDevice( const Common::ParamPackage& params) { const auto touch_id = params.Get("touch_id", 0); const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); @@ -809,7 +814,7 @@ std::unique_ptr InputFactory::CreateTouchDevice( const auto inverted = params.Get("inverted", false); const auto axis_x = static_cast(params.Get("axis_x", 0)); - const Input::AnalogProperties properties_x = { + const Common::Input::AnalogProperties properties_x = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -818,7 +823,7 @@ std::unique_ptr InputFactory::CreateTouchDevice( }; const auto axis_y = static_cast(params.Get("axis_y", 1)); - const Input::AnalogProperties properties_y = { + const Common::Input::AnalogProperties properties_y = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -833,7 +838,7 @@ std::unique_ptr InputFactory::CreateTouchDevice( axis_y, properties_x, properties_y, input_engine.get()); } -std::unique_ptr InputFactory::CreateBatteryDevice( +std::unique_ptr InputFactory::CreateBatteryDevice( const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, @@ -845,7 +850,8 @@ std::unique_ptr InputFactory::CreateBatteryDevice( return std::make_unique(identifier, input_engine.get()); } -std::unique_ptr InputFactory::CreateMotionDevice(Common::ParamPackage params) { +std::unique_ptr InputFactory::CreateMotionDevice( + Common::ParamPackage params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, .port = static_cast(params.Get("port", 0)), @@ -864,7 +870,7 @@ std::unique_ptr InputFactory::CreateMotionDevice(Common::Par const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); const auto axis_x = static_cast(params.Get("axis_x", 0)); - const Input::AnalogProperties properties_x = { + const Common::Input::AnalogProperties properties_x = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -873,7 +879,7 @@ std::unique_ptr InputFactory::CreateMotionDevice(Common::Par }; const auto axis_y = static_cast(params.Get("axis_y", 1)); - const Input::AnalogProperties properties_y = { + const Common::Input::AnalogProperties properties_y = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -882,7 +888,7 @@ std::unique_ptr InputFactory::CreateMotionDevice(Common::Par }; const auto axis_z = static_cast(params.Get("axis_z", 1)); - const Input::AnalogProperties properties_z = { + const Common::Input::AnalogProperties properties_z = { .deadzone = deadzone, .range = range, .threshold = threshold, @@ -900,7 +906,8 @@ std::unique_ptr InputFactory::CreateMotionDevice(Common::Par InputFactory::InputFactory(std::shared_ptr input_engine_) : input_engine(std::move(input_engine_)) {} -std::unique_ptr InputFactory::Create(const Common::ParamPackage& params) { +std::unique_ptr InputFactory::Create( + const Common::ParamPackage& params) { if (params.Has("battery")) { return CreateBatteryDevice(params); } @@ -935,7 +942,8 @@ std::unique_ptr InputFactory::Create(const Common::ParamPack OutputFactory::OutputFactory(std::shared_ptr input_engine_) : input_engine(std::move(input_engine_)) {} -std::unique_ptr OutputFactory::Create(const Common::ParamPackage& params) { +std::unique_ptr OutputFactory::Create( + const Common::ParamPackage& params) { const PadIdentifier identifier = { .guid = Common::UUID{params.Get("guid", "")}, .port = static_cast(params.Get("port", 0)), diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h index 1357e104b..573f09fde 100644 --- a/src/input_common/input_poller.h +++ b/src/input_common/input_poller.h @@ -17,7 +17,7 @@ class InputEngine; * An Input factory. It receives input events and forward them to all input devices it created. */ -class OutputFactory final : public Input::Factory { +class OutputFactory final : public Common::Input::Factory { public: explicit OutputFactory(std::shared_ptr input_engine_); @@ -29,13 +29,14 @@ public: * @param - "pad": slot of the connected controller * @return an unique ouput device with the parameters specified */ - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create( + const Common::ParamPackage& params) override; private: std::shared_ptr input_engine; }; -class InputFactory final : public Input::Factory { +class InputFactory final : public Common::Input::Factory { public: explicit InputFactory(std::shared_ptr input_engine_); @@ -64,7 +65,7 @@ public: * @param - "battery": Only used as a placeholder to set the input type * @return an unique input device with the parameters specified */ - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; private: /** @@ -79,7 +80,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateButtonDevice(const Common::ParamPackage& params); + std::unique_ptr CreateButtonDevice( + const Common::ParamPackage& params); /** * Creates a hat button device from the parameters given. @@ -93,7 +95,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateHatButtonDevice(const Common::ParamPackage& params); + std::unique_ptr CreateHatButtonDevice( + const Common::ParamPackage& params); /** * Creates a stick device from the parameters given. @@ -112,7 +115,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateStickDevice(const Common::ParamPackage& params); + std::unique_ptr CreateStickDevice( + const Common::ParamPackage& params); /** * Creates an analog device from the parameters given. @@ -128,7 +132,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateAnalogDevice(const Common::ParamPackage& params); + std::unique_ptr CreateAnalogDevice( + const Common::ParamPackage& params); /** * Creates a trigger device from the parameters given. @@ -148,7 +153,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateTriggerDevice(const Common::ParamPackage& params); + std::unique_ptr CreateTriggerDevice( + const Common::ParamPackage& params); /** * Creates a touch device from the parameters given. @@ -171,7 +177,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateTouchDevice(const Common::ParamPackage& params); + std::unique_ptr CreateTouchDevice( + const Common::ParamPackage& params); /** * Creates a battery device from the parameters given. @@ -181,7 +188,8 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateBatteryDevice(const Common::ParamPackage& params); + std::unique_ptr CreateBatteryDevice( + const Common::ParamPackage& params); /** * Creates a motion device from the parameters given. @@ -202,7 +210,7 @@ private: * @param - "pad": slot of the connected controller * @return an unique input device with the parameters specified */ - std::unique_ptr CreateMotionDevice(Common::ParamPackage params); + std::unique_ptr CreateMotionDevice(Common::ParamPackage params); std::shared_ptr input_engine; }; diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 07d514ad7..df36a337c 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -33,89 +33,97 @@ struct InputSubsystem::Impl { keyboard->SetMappingCallback(mapping_callback); keyboard_factory = std::make_shared(keyboard); keyboard_output_factory = std::make_shared(keyboard); - Input::RegisterFactory(keyboard->GetEngineName(), keyboard_factory); - Input::RegisterFactory(keyboard->GetEngineName(), - keyboard_output_factory); + Common::Input::RegisterFactory(keyboard->GetEngineName(), + keyboard_factory); + Common::Input::RegisterFactory(keyboard->GetEngineName(), + keyboard_output_factory); mouse = std::make_shared("mouse"); mouse->SetMappingCallback(mapping_callback); mouse_factory = std::make_shared(mouse); mouse_output_factory = std::make_shared(mouse); - Input::RegisterFactory(mouse->GetEngineName(), mouse_factory); - Input::RegisterFactory(mouse->GetEngineName(), mouse_output_factory); + Common::Input::RegisterFactory(mouse->GetEngineName(), + mouse_factory); + Common::Input::RegisterFactory(mouse->GetEngineName(), + mouse_output_factory); touch_screen = std::make_shared("touch"); touch_screen_factory = std::make_shared(touch_screen); - Input::RegisterFactory(touch_screen->GetEngineName(), - touch_screen_factory); + Common::Input::RegisterFactory(touch_screen->GetEngineName(), + touch_screen_factory); gcadapter = std::make_shared("gcpad"); gcadapter->SetMappingCallback(mapping_callback); gcadapter_input_factory = std::make_shared(gcadapter); gcadapter_output_factory = std::make_shared(gcadapter); - Input::RegisterFactory(gcadapter->GetEngineName(), - gcadapter_input_factory); - Input::RegisterFactory(gcadapter->GetEngineName(), - gcadapter_output_factory); + Common::Input::RegisterFactory(gcadapter->GetEngineName(), + gcadapter_input_factory); + Common::Input::RegisterFactory(gcadapter->GetEngineName(), + gcadapter_output_factory); udp_client = std::make_shared("cemuhookudp"); udp_client->SetMappingCallback(mapping_callback); udp_client_factory = std::make_shared(udp_client); - Input::RegisterFactory(udp_client->GetEngineName(), udp_client_factory); + Common::Input::RegisterFactory(udp_client->GetEngineName(), + udp_client_factory); tas_input = std::make_shared("tas"); tas_input->SetMappingCallback(mapping_callback); tas_input_factory = std::make_shared(tas_input); tas_output_factory = std::make_shared(tas_input); - Input::RegisterFactory(tas_input->GetEngineName(), tas_input_factory); - Input::RegisterFactory(tas_input->GetEngineName(), tas_output_factory); + Common::Input::RegisterFactory(tas_input->GetEngineName(), + tas_input_factory); + Common::Input::RegisterFactory(tas_input->GetEngineName(), + tas_output_factory); #ifdef HAVE_SDL2 sdl = std::make_shared("sdl"); sdl->SetMappingCallback(mapping_callback); sdl_input_factory = std::make_shared(sdl); sdl_output_factory = std::make_shared(sdl); - Input::RegisterFactory(sdl->GetEngineName(), sdl_input_factory); - Input::RegisterFactory(sdl->GetEngineName(), sdl_output_factory); + Common::Input::RegisterFactory(sdl->GetEngineName(), + sdl_input_factory); + Common::Input::RegisterFactory(sdl->GetEngineName(), + sdl_output_factory); #endif - Input::RegisterFactory("touch_from_button", - std::make_shared()); - Input::RegisterFactory("analog_from_button", - std::make_shared()); + Common::Input::RegisterFactory( + "touch_from_button", std::make_shared()); + Common::Input::RegisterFactory( + "analog_from_button", std::make_shared()); } void Shutdown() { - Input::UnregisterFactory(keyboard->GetEngineName()); - Input::UnregisterFactory(keyboard->GetEngineName()); + Common::Input::UnregisterFactory(keyboard->GetEngineName()); + Common::Input::UnregisterFactory(keyboard->GetEngineName()); keyboard.reset(); - Input::UnregisterFactory(mouse->GetEngineName()); - Input::UnregisterFactory(mouse->GetEngineName()); + Common::Input::UnregisterFactory(mouse->GetEngineName()); + Common::Input::UnregisterFactory(mouse->GetEngineName()); mouse.reset(); - Input::UnregisterFactory(touch_screen->GetEngineName()); + Common::Input::UnregisterFactory(touch_screen->GetEngineName()); touch_screen.reset(); - Input::UnregisterFactory(gcadapter->GetEngineName()); - Input::UnregisterFactory(gcadapter->GetEngineName()); + Common::Input::UnregisterFactory(gcadapter->GetEngineName()); + Common::Input::UnregisterFactory(gcadapter->GetEngineName()); gcadapter.reset(); - Input::UnregisterFactory(udp_client->GetEngineName()); + Common::Input::UnregisterFactory(udp_client->GetEngineName()); udp_client.reset(); - Input::UnregisterFactory(tas_input->GetEngineName()); - Input::UnregisterFactory(tas_input->GetEngineName()); + Common::Input::UnregisterFactory(tas_input->GetEngineName()); + Common::Input::UnregisterFactory(tas_input->GetEngineName()); tas_input.reset(); #ifdef HAVE_SDL2 - Input::UnregisterFactory(sdl->GetEngineName()); - Input::UnregisterFactory(sdl->GetEngineName()); + Common::Input::UnregisterFactory(sdl->GetEngineName()); + Common::Input::UnregisterFactory(sdl->GetEngineName()); sdl.reset(); #endif - Input::UnregisterFactory("touch_from_button"); - Input::UnregisterFactory("analog_from_button"); + Common::Input::UnregisterFactory("touch_from_button"); + Common::Input::UnregisterFactory("analog_from_button"); } [[nodiscard]] std::vector GetInputDevices() const { diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 67e56ed3a..bb20e9339 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -1945,8 +1945,8 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) { } void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed) { + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array qleft_trigger; std::array qright_trigger; std::array qbody_top; @@ -1984,8 +1984,8 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, - Input::TriggerStatus left_trigger, - Input::TriggerStatus right_trigger) { + Common::Input::TriggerStatus left_trigger, + Common::Input::TriggerStatus right_trigger) { std::array qleft_trigger; std::array qright_trigger; @@ -2022,8 +2022,8 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed) { + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array qleft_trigger; std::array qright_trigger; @@ -2048,8 +2048,8 @@ void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF cente } void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed) { + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array qleft_trigger; std::array qright_trigger; constexpr float size = 1.62f; @@ -2076,9 +2076,9 @@ void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, DrawPolygon(p, qright_trigger); } -void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed) { +void PlayerControlPreview::DrawDualTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array qleft_trigger; std::array qright_trigger; constexpr float size = 0.9f; @@ -2113,9 +2113,9 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce DrawSymbol(p, center + QPointF(177, -84), Symbol::R, 1.0f); } -void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed) { +void PlayerControlPreview::DrawDualZTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array qleft_trigger; std::array qright_trigger; constexpr float size = 0.9f; @@ -2149,7 +2149,7 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c } void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed) { + const Common::Input::ButtonStatus& left_pressed) { std::array qleft_trigger; constexpr float size = 1.78f; constexpr float offset = 311.5f; @@ -2166,7 +2166,7 @@ void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed) { + const Common::Input::ButtonStatus& left_pressed) { std::array qleft_trigger; constexpr float size = 1.1115f; constexpr float offset2 = 335; @@ -2184,8 +2184,8 @@ void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, 225 * 16, 44 * 16); } -void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed) { +void PlayerControlPreview::DrawLeftTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed) { std::array qleft_trigger; for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) { @@ -2203,8 +2203,8 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce DrawSymbol(p, center + QPointF(-143, -36), Symbol::L, 1.0f); } -void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center, - const Input::ButtonStatus& left_pressed) { +void PlayerControlPreview::DrawLeftZTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed) { std::array qleft_trigger; for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) { @@ -2223,7 +2223,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c } void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& right_pressed) { + const Common::Input::ButtonStatus& right_pressed) { std::array qright_trigger; constexpr float size = 1.78f; constexpr float offset = 311.5f; @@ -2240,7 +2240,7 @@ void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center, - const Input::ButtonStatus& right_pressed) { + const Common::Input::ButtonStatus& right_pressed) { std::array qright_trigger; constexpr float size = 1.1115f; constexpr float offset2 = 335; @@ -2259,8 +2259,8 @@ void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center, 271 * 16, 44 * 16); } -void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center, - const Input::ButtonStatus& right_pressed) { +void PlayerControlPreview::DrawRightTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& right_pressed) { std::array qright_trigger; for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) { @@ -2278,8 +2278,8 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c DrawSymbol(p, center + QPointF(137, -36), Symbol::R, 1.0f); } -void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center, - const Input::ButtonStatus& right_pressed) { +void PlayerControlPreview::DrawRightZTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& right_pressed) { std::array qright_trigger; for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) { @@ -2298,7 +2298,7 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF } void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { const float radius1 = 13.0f * size; const float radius2 = 9.0f * size; @@ -2317,7 +2317,8 @@ void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float } void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle, - float size, const Input::ButtonStatus& pressed) { + float size, + const Common::Input::ButtonStatus& pressed) { QVector joystick; joystick.reserve(static_cast(left_joystick_sideview.size() / 2)); @@ -2342,7 +2343,7 @@ void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF cente void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, const QPointF offset, float offset_scalar, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { const float radius1 = 24.0f; const float radius2 = 17.0f; @@ -2377,7 +2378,7 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co } void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { // Outer circle p.setPen(colors.outline); p.setBrush(pressed.value ? colors.highlight : colors.button); @@ -2414,8 +2415,8 @@ void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPo } } -void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF center, - const Input::AnalogProperties& properties) { +void PlayerControlPreview::DrawJoystickProperties( + QPainter& p, const QPointF center, const Common::Input::AnalogProperties& properties) { constexpr float size = 45.0f; const float range = size * properties.range; const float deadzone = size * properties.deadzone; @@ -2435,7 +2436,7 @@ void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF cen } void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, - const Input::StickStatus& stick, bool raw) { + const Common::Input::StickStatus& stick, bool raw) { constexpr float size = 45.0f; const float range = size * stick.x.properties.range; @@ -2450,7 +2451,7 @@ void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, - const Input::ButtonStatus& pressed, float width, + const Common::Input::ButtonStatus& pressed, float width, float height, Direction direction, float radius) { p.setBrush(button_color); if (pressed.value) { @@ -2476,13 +2477,15 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, p.drawRoundedRect(rect, radius, radius); } void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed, int button_size) { + const Common::Input::ButtonStatus& pressed, + int button_size) { p.setPen(colors.outline); p.setBrush(pressed.value ? colors.highlight : colors.button); DrawRectangle(p, center, button_size, button_size / 3.0f); } void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed, int button_size) { + const Common::Input::ButtonStatus& pressed, + int button_size) { // Draw outer line p.setPen(colors.outline); p.setBrush(pressed.value ? colors.highlight : colors.button); @@ -2499,7 +2502,7 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { std::array button_x; for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) { @@ -2512,7 +2515,7 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { std::array button_x; for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) { @@ -2525,7 +2528,7 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { std::array button_x; for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) { @@ -2539,7 +2542,8 @@ void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, - const Input::ButtonStatus& pressed, float button_size) { + const Common::Input::ButtonStatus& pressed, + float button_size) { p.setBrush(button_color); if (pressed.value) { p.setBrush(colors.highlight); @@ -2571,7 +2575,7 @@ void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF cen void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, const Direction direction, - const Input::ButtonStatus& pressed, float size) { + const Common::Input::ButtonStatus& pressed, float size) { std::array arrow_button; QPoint offset; @@ -2628,7 +2632,7 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, const Direction direction, - const Input::ButtonStatus& pressed) { + const Common::Input::ButtonStatus& pressed) { std::array qtrigger_button; for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) { @@ -2655,8 +2659,9 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, DrawPolygon(p, qtrigger_button); } -void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery) { - if (battery == Input::BatteryLevel::None) { +void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, + Common::Input::BatteryLevel battery) { + if (battery == Common::Input::BatteryLevel::None) { return; } p.setPen(colors.outline); @@ -2665,29 +2670,29 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::Batte p.drawRect(center.x() + 56, center.y() + 6, 3, 8); p.setBrush(colors.deadzone); switch (battery) { - case Input::BatteryLevel::Charging: + case Common::Input::BatteryLevel::Charging: p.setBrush(colors.indicator2); p.drawText(center + QPoint(2, 14), tr("Charging")); break; - case Input::BatteryLevel::Full: + case Common::Input::BatteryLevel::Full: p.drawRect(center.x() + 42, center.y(), 14, 20); p.drawRect(center.x() + 28, center.y(), 14, 20); p.drawRect(center.x() + 14, center.y(), 14, 20); p.drawRect(center.x(), center.y(), 14, 20); break; - case Input::BatteryLevel::Medium: + case Common::Input::BatteryLevel::Medium: p.drawRect(center.x() + 28, center.y(), 14, 20); p.drawRect(center.x() + 14, center.y(), 14, 20); p.drawRect(center.x(), center.y(), 14, 20); break; - case Input::BatteryLevel::Low: + case Common::Input::BatteryLevel::Low: p.drawRect(center.x() + 14, center.y(), 14, 20); p.drawRect(center.x(), center.y(), 14, 20); break; - case Input::BatteryLevel::Critical: + case Common::Input::BatteryLevel::Critical: p.drawRect(center.x(), center.y(), 14, 20); break; - case Input::BatteryLevel::Empty: + case Common::Input::BatteryLevel::Empty: p.drawRect(center.x(), center.y(), 5, 20); break; default: diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 333c3fc56..430e4f4f4 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -115,66 +115,75 @@ private: void DrawGCBody(QPainter& p, QPointF center); // Draw triggers functions - void DrawProTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed); - void DrawGCTriggers(QPainter& p, QPointF center, Input::TriggerStatus left_trigger, - Input::TriggerStatus right_trigger); - void DrawHandheldTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed); - void DrawDualTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed); + void DrawProTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawGCTriggers(QPainter& p, QPointF center, Common::Input::TriggerStatus left_trigger, + Common::Input::TriggerStatus right_trigger); + void DrawHandheldTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawDualTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); void DrawDualTriggersTopView(QPainter& p, QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed); + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); void DrawDualZTriggersTopView(QPainter& p, QPointF center, - const Input::ButtonStatus& left_pressed, - const Input::ButtonStatus& right_pressed); - void DrawLeftTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed); - void DrawLeftZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed); + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawLeftTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed); + void DrawLeftZTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed); void DrawLeftTriggersTopView(QPainter& p, QPointF center, - const Input::ButtonStatus& left_pressed); + const Common::Input::ButtonStatus& left_pressed); void DrawLeftZTriggersTopView(QPainter& p, QPointF center, - const Input::ButtonStatus& left_pressed); - void DrawRightTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed); - void DrawRightZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed); + const Common::Input::ButtonStatus& left_pressed); + void DrawRightTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& right_pressed); + void DrawRightZTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& right_pressed); void DrawRightTriggersTopView(QPainter& p, QPointF center, - const Input::ButtonStatus& right_pressed); + const Common::Input::ButtonStatus& right_pressed); void DrawRightZTriggersTopView(QPainter& p, QPointF center, - const Input::ButtonStatus& right_pressed); + const Common::Input::ButtonStatus& right_pressed); // Draw joystick functions - void DrawJoystick(QPainter& p, QPointF center, float size, const Input::ButtonStatus& pressed); + void DrawJoystick(QPainter& p, QPointF center, float size, + const Common::Input::ButtonStatus& pressed); void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, - const Input::ButtonStatus& pressed); + const Common::Input::ButtonStatus& pressed); void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right); void DrawJoystickProperties(QPainter& p, QPointF center, - const Input::AnalogProperties& properties); - void DrawJoystickDot(QPainter& p, QPointF center, const Input::StickStatus& stick, bool raw); + const Common::Input::AnalogProperties& properties); + void DrawJoystickDot(QPainter& p, QPointF center, const Common::Input::StickStatus& stick, + bool raw); void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar, - const Input::ButtonStatus& pressed); - void DrawGCJoystick(QPainter& p, QPointF center, const Input::ButtonStatus& pressed); + const Common::Input::ButtonStatus& pressed); + void DrawGCJoystick(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); // Draw button functions - void DrawCircleButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed, + void DrawCircleButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, float button_size); - void DrawRoundButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed, + void DrawRoundButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, float width, float height, Direction direction = Direction::None, float radius = 2); - void DrawMinusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed, + void DrawMinusButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, int button_size); - void DrawPlusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed, + void DrawPlusButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, int button_size); - void DrawGCButtonX(QPainter& p, QPointF center, const Input::ButtonStatus& pressed); - void DrawGCButtonY(QPainter& p, QPointF center, const Input::ButtonStatus& pressed); - void DrawGCButtonZ(QPainter& p, QPointF center, const Input::ButtonStatus& pressed); + void DrawGCButtonX(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); + void DrawGCButtonY(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); + void DrawGCButtonZ(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f); void DrawArrowButton(QPainter& p, QPointF center, Direction direction, - const Input::ButtonStatus& pressed, float size = 1.0f); + const Common::Input::ButtonStatus& pressed, float size = 1.0f); void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, - const Input::ButtonStatus& pressed); + const Common::Input::ButtonStatus& pressed); // Draw battery functions - void DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery); + void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery); // Draw icon functions void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size); -- 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/common/input.h | 4 +- src/core/hid/emulated_console.cpp | 3 +- src/core/hid/emulated_controller.cpp | 11 ++- src/core/hid/input_converter.cpp | 4 +- src/input_common/drivers/tas_input.h | 1 - src/input_common/helpers/touch_from_buttons.cpp | 4 +- src/input_common/input_engine.cpp | 2 +- src/input_common/input_engine.h | 5 +- src/input_common/input_poller.cpp | 89 ++++++++++++---------- src/yuzu/applets/qt_controller.cpp | 2 - src/yuzu/configuration/configure_input_player.cpp | 2 - src/yuzu/configuration/configure_input_player.ui | 25 ------ .../configure_input_player_widget.cpp | 20 ++--- 13 files changed, 77 insertions(+), 95 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 6d3227f5e..16b1e6f1b 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -100,7 +100,7 @@ struct StickStatus { struct TriggerStatus { AnalogStatus analog{}; - bool pressed{}; + ButtonStatus pressed{}; }; struct MotionSensor { @@ -119,7 +119,7 @@ struct TouchStatus { ButtonStatus pressed{}; AnalogStatus x{}; AnalogStatus y{}; - u32 id{}; + int id{}; }; struct BodyColorStatus { 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 diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h index 5f5c3267c..82dc9d616 100644 --- a/src/input_common/drivers/tas_input.h +++ b/src/input_common/drivers/tas_input.h @@ -188,7 +188,6 @@ private: std::string WriteCommandAxis(TasAnalog data) const; size_t script_length{0}; - bool is_old_input_saved{false}; bool is_recording{false}; bool is_running{false}; bool needs_reset{false}; diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index fee41cae3..024343715 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -12,7 +12,7 @@ namespace InputCommon { class TouchFromButtonDevice final : public Common::Input::InputDevice { public: using Button = std::unique_ptr; - TouchFromButtonDevice(Button button_, u32 touch_id_, float x_, float y_) + TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_) : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { Common::Input::InputCallback button_up_callback{ [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }}; @@ -52,7 +52,7 @@ public: private: Button button; - const u32 touch_id; + const int touch_id; const float x; const float y; const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 9cfe0f232..965a2bdf1 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp @@ -315,7 +315,7 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, const PadIdentifier& identifier, EngineInputType type, - std::size_t index) const { + int index) const { if (input_identifier.type != type) { return false; } diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index ed79d3d93..5430c0cf8 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -96,7 +96,7 @@ struct MappingCallback { struct InputIdentifier { PadIdentifier identifier; EngineInputType type; - std::size_t index; + int index; UpdateCallback callback; }; @@ -216,12 +216,11 @@ private: bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, const PadIdentifier& identifier, EngineInputType type, - std::size_t index) const; + int index) const; mutable std::mutex mutex; mutable std::mutex mutex_callback; bool configuring{false}; - bool is_callback_enabled{true}; const std::string input_engine; int last_callback_key = 0; std::unordered_map controller_list; diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 2b3b77938..01c435802 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -18,7 +18,7 @@ public: class InputFromButton final : public Common::Input::InputDevice { public: - explicit InputFromButton(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_, + explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, InputEngine* input_engine_) : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), input_engine(input_engine_) { @@ -69,7 +69,7 @@ public: private: const PadIdentifier identifier; - const u32 button; + const int button; const bool toggle; const bool inverted; int callback_key; @@ -79,7 +79,7 @@ private: class InputFromHatButton final : public Common::Input::InputDevice { public: - explicit InputFromHatButton(PadIdentifier identifier_, u32 button_, u8 direction_, bool toggle_, + explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_, bool inverted_, InputEngine* input_engine_) : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_), inverted(inverted_), input_engine(input_engine_) { @@ -130,7 +130,7 @@ public: private: const PadIdentifier identifier; - const u32 button; + const int button; const u8 direction; const bool toggle; const bool inverted; @@ -141,7 +141,7 @@ private: class InputFromStick final : public Common::Input::InputDevice { public: - explicit InputFromStick(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, + explicit InputFromStick(PadIdentifier identifier_, int axis_x_, int axis_y_, Common::Input::AnalogProperties properties_x_, Common::Input::AnalogProperties properties_y_, InputEngine* input_engine_) @@ -211,8 +211,8 @@ public: private: const PadIdentifier identifier; - const u32 axis_x; - const u32 axis_y; + const int axis_x; + const int axis_y; const Common::Input::AnalogProperties properties_x; const Common::Input::AnalogProperties properties_y; int callback_key_x; @@ -224,8 +224,8 @@ private: class InputFromTouch final : public Common::Input::InputDevice { public: - explicit InputFromTouch(PadIdentifier identifier_, u32 touch_id_, u32 button_, bool toggle_, - bool inverted_, u32 axis_x_, u32 axis_y_, + explicit InputFromTouch(PadIdentifier identifier_, int touch_id_, int button_, bool toggle_, + bool inverted_, int axis_x_, int axis_y_, Common::Input::AnalogProperties properties_x_, Common::Input::AnalogProperties properties_y_, InputEngine* input_engine_) @@ -302,12 +302,12 @@ public: private: const PadIdentifier identifier; - const u32 touch_id; - const u32 button; + const int touch_id; + const int button; const bool toggle; const bool inverted; - const u32 axis_x; - const u32 axis_y; + const int axis_x; + const int axis_y; const Common::Input::AnalogProperties properties_x; const Common::Input::AnalogProperties properties_y; int callback_key_button; @@ -321,8 +321,8 @@ private: class InputFromTrigger final : public Common::Input::InputDevice { public: - explicit InputFromTrigger(PadIdentifier identifier_, u32 button_, bool toggle_, bool inverted_, - u32 axis_, Common::Input::AnalogProperties properties_, + explicit InputFromTrigger(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, + int axis_, Common::Input::AnalogProperties properties_, InputEngine* input_engine_) : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), axis(axis_), properties(properties_), input_engine(input_engine_) { @@ -355,9 +355,14 @@ public: .raw_value = input_engine->GetAxis(identifier, axis), .properties = properties, }; + const Common::Input::ButtonStatus button_status{ + .value = input_engine->GetButton(identifier, button), + .inverted = inverted, + .toggle = toggle, + }; return { .analog = analog_status, - .pressed = input_engine->GetButton(identifier, button), + .pressed = button_status, }; } @@ -368,19 +373,19 @@ public: }; if (status.trigger_status.analog.raw_value != last_axis_value || - status.trigger_status.pressed != last_button_value) { + status.trigger_status.pressed.value != last_button_value) { last_axis_value = status.trigger_status.analog.raw_value; - last_button_value = status.trigger_status.pressed; + last_button_value = status.trigger_status.pressed.value; TriggerOnChange(status); } } private: const PadIdentifier identifier; - const u32 button; + const int button; const bool toggle; const bool inverted; - const u32 axis; + const int axis; const Common::Input::AnalogProperties properties; int callback_key_button; int axis_callback_key; @@ -391,7 +396,7 @@ private: class InputFromAnalog final : public Common::Input::InputDevice { public: - explicit InputFromAnalog(PadIdentifier identifier_, u32 axis_, + explicit InputFromAnalog(PadIdentifier identifier_, int axis_, Common::Input::AnalogProperties properties_, InputEngine* input_engine_) : identifier(identifier_), axis(axis_), properties(properties_), @@ -432,7 +437,7 @@ public: private: const PadIdentifier identifier; - const u32 axis; + const int axis; const Common::Input::AnalogProperties properties; int callback_key; float last_axis_value; @@ -493,7 +498,7 @@ private: class InputFromMotion final : public Common::Input::InputDevice { public: - explicit InputFromMotion(PadIdentifier identifier_, u32 motion_sensor_, + explicit InputFromMotion(PadIdentifier identifier_, int motion_sensor_, InputEngine* input_engine_) : identifier(identifier_), motion_sensor(motion_sensor_), input_engine(input_engine_) { UpdateCallback engine_callback{[this]() { OnChange(); }}; @@ -539,14 +544,14 @@ public: private: const PadIdentifier identifier; - const u32 motion_sensor; + const int motion_sensor; int callback_key; InputEngine* input_engine; }; class InputFromAxisMotion final : public Common::Input::InputDevice { public: - explicit InputFromAxisMotion(PadIdentifier identifier_, u32 axis_x_, u32 axis_y_, u32 axis_z_, + explicit InputFromAxisMotion(PadIdentifier identifier_, int axis_x_, int axis_y_, int axis_z_, Common::Input::AnalogProperties properties_x_, Common::Input::AnalogProperties properties_y_, Common::Input::AnalogProperties properties_z_, @@ -634,9 +639,9 @@ public: private: const PadIdentifier identifier; - const u32 axis_x; - const u32 axis_y; - const u32 axis_z; + const int axis_x; + const int axis_y; + const int axis_z; const Common::Input::AnalogProperties properties_x; const Common::Input::AnalogProperties properties_y; const Common::Input::AnalogProperties properties_z; @@ -680,8 +685,8 @@ std::unique_ptr InputFactory::CreateButtonDevice( .pad = static_cast(params.Get("pad", 0)), }; - const auto button_id = static_cast(params.Get("button", 0)); - const auto keyboard_key = static_cast(params.Get("code", 0)); + const auto button_id = params.Get("button", 0); + const auto keyboard_key = params.Get("code", 0); const auto toggle = params.Get("toggle", false); const auto inverted = params.Get("inverted", false); input_engine->PreSetController(identifier); @@ -703,7 +708,7 @@ std::unique_ptr InputFactory::CreateHatButtonDevice( .pad = static_cast(params.Get("pad", 0)), }; - const auto button_id = static_cast(params.Get("hat", 0)); + const auto button_id = params.Get("hat", 0); const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); const auto toggle = params.Get("toggle", false); const auto inverted = params.Get("inverted", false); @@ -725,7 +730,7 @@ std::unique_ptr InputFactory::CreateStickDevice( .pad = static_cast(params.Get("pad", 0)), }; - const auto axis_x = static_cast(params.Get("axis_x", 0)); + const auto axis_x = params.Get("axis_x", 0); const Common::Input::AnalogProperties properties_x = { .deadzone = deadzone, .range = range, @@ -734,7 +739,7 @@ std::unique_ptr InputFactory::CreateStickDevice( .inverted = params.Get("invert_x", "+") == "-", }; - const auto axis_y = static_cast(params.Get("axis_y", 1)); + const auto axis_y = params.Get("axis_y", 1); const Common::Input::AnalogProperties properties_y = { .deadzone = deadzone, .range = range, @@ -757,7 +762,7 @@ std::unique_ptr InputFactory::CreateAnalogDevice( .pad = static_cast(params.Get("pad", 0)), }; - const auto axis = static_cast(params.Get("axis", 0)); + const auto axis = params.Get("axis", 0); const Common::Input::AnalogProperties properties = { .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f), .range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f), @@ -778,11 +783,11 @@ std::unique_ptr InputFactory::CreateTriggerDevice( .pad = static_cast(params.Get("pad", 0)), }; - const auto button = static_cast(params.Get("button", 0)); + const auto button = params.Get("button", 0); const auto toggle = params.Get("toggle", false); const auto inverted = params.Get("inverted", false); - const auto axis = static_cast(params.Get("axis", 0)); + const auto axis = params.Get("axis", 0); const Common::Input::AnalogProperties properties = { .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f), .range = std::clamp(params.Get("range", 1.0f), 0.25f, 2.50f), @@ -809,11 +814,11 @@ std::unique_ptr InputFactory::CreateTouchDevice( .pad = static_cast(params.Get("pad", 0)), }; - const auto button = static_cast(params.Get("button", 0)); + const auto button = params.Get("button", 0); const auto toggle = params.Get("toggle", false); const auto inverted = params.Get("inverted", false); - const auto axis_x = static_cast(params.Get("axis_x", 0)); + const auto axis_x = params.Get("axis_x", 0); const Common::Input::AnalogProperties properties_x = { .deadzone = deadzone, .range = range, @@ -822,7 +827,7 @@ std::unique_ptr InputFactory::CreateTouchDevice( .inverted = params.Get("invert_x", "+") == "-", }; - const auto axis_y = static_cast(params.Get("axis_y", 1)); + const auto axis_y = params.Get("axis_y", 1); const Common::Input::AnalogProperties properties_y = { .deadzone = deadzone, .range = range, @@ -869,7 +874,7 @@ std::unique_ptr InputFactory::CreateMotionDevice( const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); - const auto axis_x = static_cast(params.Get("axis_x", 0)); + const auto axis_x = params.Get("axis_x", 0); const Common::Input::AnalogProperties properties_x = { .deadzone = deadzone, .range = range, @@ -878,7 +883,7 @@ std::unique_ptr InputFactory::CreateMotionDevice( .inverted = params.Get("invert_x", "+") == "-", }; - const auto axis_y = static_cast(params.Get("axis_y", 1)); + const auto axis_y = params.Get("axis_y", 1); const Common::Input::AnalogProperties properties_y = { .deadzone = deadzone, .range = range, @@ -887,7 +892,7 @@ std::unique_ptr InputFactory::CreateMotionDevice( .inverted = params.Get("invert_y", "+") != "+", }; - const auto axis_z = static_cast(params.Get("axis_z", 1)); + const auto axis_z = params.Get("axis_z", 1); const Common::Input::AnalogProperties properties_z = { .deadzone = deadzone, .range = range, diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 59289c6a5..e9cb578b4 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -26,8 +26,6 @@ namespace { -constexpr std::size_t HANDHELD_INDEX = 8; - void UpdateController(Core::HID::EmulatedController* controller, Core::HID::NpadType controller_type, bool connected) { if (controller->IsConnected()) { diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 9a1b3575e..8d6289d8e 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -38,8 +38,6 @@ const std::array namespace { -constexpr std::size_t HANDHELD_INDEX = 8; - QString GetKeyName(int key_code) { switch (key_code) { case Qt::Key_Shift: diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index 14ca02fd8..958a89229 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui @@ -89,31 +89,6 @@ 21 - - - Pro Controller - - - - - Dual Joycons - - - - - Left Joycon - - - - - Right Joycon - - - - - Handheld - - diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index bb20e9339..99c4f13c3 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -118,7 +118,7 @@ void PlayerControlPreview::ResetInputs() { }); trigger_values.fill({ .analog = {.value = 0, .properties = {0, 1, 0}}, - .pressed = false, + .pressed = {.value = false}, }); update(); } @@ -2001,11 +2001,11 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, // Left trigger p.setPen(colors.outline); - p.setBrush(left_trigger.pressed ? colors.highlight : colors.button); + p.setBrush(left_trigger.pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Right trigger - p.setBrush(right_trigger.pressed ? colors.highlight : colors.button); + p.setBrush(right_trigger.pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); // Draw L text @@ -2587,15 +2587,17 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, case Direction::Up: arrow_button[point] = center + QPointF(up_arrow_x * size, up_arrow_y * size); break; - case Direction::Left: - arrow_button[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size); - break; case Direction::Right: arrow_button[point] = center + QPointF(-up_arrow_y * size, up_arrow_x * size); break; case Direction::Down: arrow_button[point] = center + QPointF(up_arrow_x * size, -up_arrow_y * size); break; + case Direction::Left: + // Compiler doesn't optimize this correctly + arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1] * size, + up_arrow_button[point * 2 + 0] * size); + break; case Direction::None: break; } @@ -2610,15 +2612,15 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, case Direction::Up: offset = QPoint(0, -20 * size); break; - case Direction::Left: - offset = QPoint(-20 * size, 0); - break; case Direction::Right: offset = QPoint(20 * size, 0); break; case Direction::Down: offset = QPoint(0, 20 * size); break; + case Direction::Left: + offset = QPoint(-20 * size, 0); + break; case Direction::None: offset = QPoint(0, 0); break; -- 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/common/input.h | 2 +- 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 + src/input_common/drivers/keyboard.cpp | 6 ++++++ src/input_common/drivers/keyboard.h | 7 ------- src/input_common/drivers/mouse.cpp | 5 +++++ src/input_common/drivers/mouse.h | 5 ----- src/input_common/drivers/touch_screen.cpp | 6 ++++++ src/input_common/drivers/touch_screen.h | 8 +------- src/input_common/input_engine.cpp | 5 +++-- src/yuzu/applets/qt_controller.cpp | 1 + src/yuzu/configuration/configure_input_player_widget.cpp | 5 ++--- src/yuzu/configuration/configure_input_player_widget.h | 1 + src/yuzu/debugger/controller.h | 3 ++- src/yuzu/main.cpp | 1 + 28 files changed, 73 insertions(+), 42 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 16b1e6f1b..12acd8785 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -29,7 +29,7 @@ enum class InputType { Ir, }; -enum class BatteryLevel { +enum class BatteryLevel : u32 { None, Empty, Critical, 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" diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp index 85a781a30..549704e89 100644 --- a/src/input_common/drivers/keyboard.cpp +++ b/src/input_common/drivers/keyboard.cpp @@ -7,6 +7,12 @@ namespace InputCommon { +constexpr PadIdentifier identifier = { + .guid = Common::UUID{Common::INVALID_UUID}, + .port = 0, + .pad = 0, +}; + Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) { PreSetController(identifier); } diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h index 58df15050..46fe78576 100644 --- a/src/input_common/drivers/keyboard.h +++ b/src/input_common/drivers/keyboard.h @@ -32,13 +32,6 @@ public: /// Used for automapping features std::vector GetInputDevices() const override; - -private: - const PadIdentifier identifier = { - .guid = Common::UUID{Common::INVALID_UUID}, - .port = 0, - .pad = 0, - }; }; } // namespace InputCommon diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 1c32b54be..afa92b458 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -14,6 +14,11 @@ namespace InputCommon { constexpr int touch_axis_x = 10; constexpr int touch_axis_y = 11; +constexpr PadIdentifier identifier = { + .guid = Common::UUID{Common::INVALID_UUID}, + .port = 0, + .pad = 0, +}; Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) { PreSetController(identifier); diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index cf0918409..1be362b94 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -62,11 +62,6 @@ private: void UpdateThread(std::stop_token stop_token); void StopPanning(); - const PadIdentifier identifier = { - .guid = Common::UUID{Common::INVALID_UUID}, - .port = 0, - .pad = 0, - }; Common::Vec2 mouse_origin; Common::Vec2 last_mouse_position; Common::Vec2 last_mouse_change; diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp index e13835e9f..377c9ee2b 100644 --- a/src/input_common/drivers/touch_screen.cpp +++ b/src/input_common/drivers/touch_screen.cpp @@ -7,6 +7,12 @@ namespace InputCommon { +constexpr PadIdentifier identifier = { + .guid = Common::UUID{Common::INVALID_UUID}, + .port = 0, + .pad = 0, +}; + TouchScreen::TouchScreen(const std::string input_engine_) : InputEngine(input_engine_) { PreSetController(identifier); } diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h index d297d253c..0f4cd0e7a 100644 --- a/src/input_common/drivers/touch_screen.h +++ b/src/input_common/drivers/touch_screen.h @@ -37,14 +37,8 @@ public: */ void TouchReleased(std::size_t finger); + /// Resets all inputs to their initial value void ReleaseAllTouch(); - -private: - const PadIdentifier identifier = { - .guid = Common::UUID{Common::INVALID_UUID}, - .port = 0, - .pad = 0, - }; }; } // namespace InputCommon diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 965a2bdf1..139d8d2e6 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp @@ -353,11 +353,12 @@ void InputEngine::SetMappingCallback(MappingCallback callback) { void InputEngine::DeleteCallback(int key) { std::lock_guard lock{mutex_callback}; - 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 InputCommon diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index e9cb578b4..9c6377cf0 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -10,6 +10,7 @@ #include "common/string_util.h" #include "core/core.h" #include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/lock.h" #include "core/hle/service/hid/controllers/npad.h" diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 99c4f13c3..7e71a0f58 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -2594,9 +2594,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, arrow_button[point] = center + QPointF(up_arrow_x * size, -up_arrow_y * size); break; case Direction::Left: - // Compiler doesn't optimize this correctly - arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1] * size, - up_arrow_button[point * 2 + 0] * size); + // Compiler doesn't optimize this correctly check why + arrow_button[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size); break; case Direction::None: break; diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 430e4f4f4..acc53a9e3 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -9,6 +9,7 @@ #include #include "common/input.h" #include "common/settings.h" +#include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hid/hid_types.h" diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h index ba4185a4b..d08643baa 100644 --- a/src/yuzu/debugger/controller.h +++ b/src/yuzu/debugger/controller.h @@ -21,7 +21,8 @@ class System; namespace Core::HID { class EmulatedController; -} +enum class ControllerTriggerType; +} // namespace Core::HID class ControllerDialog : public QWidget { Q_OBJECT diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 56db337a4..7c95851b3 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -26,6 +26,7 @@ #include "core/frontend/applets/controller.h" #include "core/frontend/applets/general_frontend.h" #include "core/frontend/applets/software_keyboard.h" +#include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applet_ae.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/common/input.h | 5 ++ 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 +++++ src/input_common/helpers/stick_from_buttons.cpp | 12 ++++ src/input_common/helpers/touch_from_buttons.cpp | 11 +++- 7 files changed, 97 insertions(+), 37 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 12acd8785..8f29026a1 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -110,9 +110,14 @@ struct MotionSensor { }; struct MotionStatus { + // Gyroscope vector measurement in radians/s. MotionSensor gyro{}; + // Acceleration vector measurement in G force MotionSensor accel{}; + // Time since last measurement in microseconds u64 delta_timestamp{}; + // Request to update after reading the value + bool force_update{}; }; struct TouchStatus { 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; }; diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 1d5948f79..77fcd655e 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -36,6 +36,8 @@ public: left->SetCallback(button_left_callback); right->SetCallback(button_right_callback); modifier->SetCallback(button_modifier_callback); + last_x_axis_value = 0.0f; + last_y_axis_value = 0.0f; } bool IsAngleGreater(float old_angle, float new_angle) const { @@ -199,6 +201,8 @@ public: .type = Common::Input::InputType::Stick, .stick_status = GetStatus(), }; + last_x_axis_value = status.stick_status.x.raw_value; + last_y_axis_value = status.stick_status.y.raw_value; TriggerOnChange(status); } @@ -215,6 +219,12 @@ public: .type = Common::Input::InputType::Stick, .stick_status = GetStatus(), }; + if (last_x_axis_value == status.stick_status.x.raw_value && + last_y_axis_value == status.stick_status.y.raw_value) { + return; + } + last_x_axis_value = status.stick_status.x.raw_value; + last_y_axis_value = status.stick_status.y.raw_value; TriggerOnChange(status); } @@ -265,6 +275,8 @@ private: bool left_status; bool right_status; bool modifier_status; + float last_x_axis_value; + float last_y_axis_value; const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; std::chrono::time_point last_update; }; diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index 024343715..35d60bc90 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -16,10 +16,15 @@ public: : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { Common::Input::InputCallback button_up_callback{ [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }}; + last_button_value = false; button->SetCallback(button_up_callback); button->ForceUpdate(); } + void ForceUpdate() override { + button->ForceUpdate(); + } + Common::Input::TouchStatus GetStatus(bool pressed) const { const Common::Input::ButtonStatus button_status{ .value = pressed, @@ -47,11 +52,15 @@ public: .type = Common::Input::InputType::Touch, .touch_status = GetStatus(button_callback.button_status.value), }; - TriggerOnChange(status); + if (last_button_value != button_callback.button_status.value) { + last_button_value = button_callback.button_status.value; + TriggerOnChange(status); + } } private: Button button; + bool last_button_value; const int touch_id; const float x; const float y; -- 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/common/input.h | 4 ++ src/core/hid/emulated_controller.cpp | 68 +++++++++++++++++++++++++++++----- src/core/hid/emulated_controller.h | 6 +-- src/input_common/drivers/tas_input.cpp | 24 +++++------- src/input_common/drivers/tas_input.h | 11 ++---- 5 files changed, 77 insertions(+), 36 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 8f29026a1..f21872b0a 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -11,6 +11,7 @@ #include #include "common/logging/log.h" #include "common/param_package.h" +#include "common/uuid.h" namespace Common::Input { @@ -81,6 +82,7 @@ struct AnalogStatus { }; struct ButtonStatus { + Common::UUID uuid{}; bool value{}; bool inverted{}; bool toggle{}; @@ -90,6 +92,7 @@ struct ButtonStatus { using BatteryStatus = BatteryLevel; struct StickStatus { + Common::UUID uuid{}; AnalogStatus x{}; AnalogStatus y{}; bool left{}; @@ -99,6 +102,7 @@ struct StickStatus { }; struct TriggerStatus { + Common::UUID uuid{}; AnalogStatus analog{}; ButtonStatus pressed{}; }; 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 diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index d2748b240..bb9c236ea 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -71,21 +71,21 @@ Tas::~Tas() { void Tas::LoadTasFiles() { script_length = 0; for (size_t i = 0; i < commands.size(); i++) { - LoadTasFile(i); + LoadTasFile(i, 0); if (commands[i].size() > script_length) { script_length = commands[i].size(); } } } -void Tas::LoadTasFile(size_t player_index) { +void Tas::LoadTasFile(size_t player_index, size_t file_index) { if (!commands[player_index].empty()) { commands[player_index].clear(); } - std::string file = - Common::FS::ReadStringFromFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / - fmt::format("script0-{}.txt", player_index + 1), - Common::FS::FileType::BinaryFile); + std::string file = Common::FS::ReadStringFromFile( + Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / + fmt::format("script{}-{}.txt", file_index, player_index + 1), + Common::FS::FileType::BinaryFile); std::stringstream command_line(file); std::string line; int frame_no = 0; @@ -144,15 +144,8 @@ void Tas::WriteTasFile(std::u8string file_name) { void Tas::RecordInput(u64 buttons, TasAnalog left_axis, TasAnalog right_axis) { last_input = { .buttons = buttons, - .l_axis = FlipAxisY(left_axis), - .r_axis = FlipAxisY(right_axis), - }; -} - -TasAnalog Tas::FlipAxisY(TasAnalog old) { - return { - .x = old.x, - .y = -old.y, + .l_axis = left_axis, + .r_axis = right_axis, }; } @@ -219,6 +212,7 @@ void Tas::UpdateThread() { } } else { is_running = Settings::values.tas_loop.GetValue(); + LoadTasFiles(); current_command = 0; ClearInput(); } diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h index 82dc9d616..bfb37a638 100644 --- a/src/input_common/drivers/tas_input.h +++ b/src/input_common/drivers/tas_input.h @@ -138,21 +138,16 @@ private: void LoadTasFiles(); /** Loads TAS file from the specified player - * @param player_index: player number where data is going to be stored + * @param player_index: player number to save the script + * @param file_index: script number of the file */ - void LoadTasFile(size_t player_index); + void LoadTasFile(size_t player_index, size_t file_index); /** Writes a TAS file from the recorded commands * @param file_name: name of the file to be written */ void WriteTasFile(std::u8string file_name); - /** Inverts the Y axis polarity - * @param old: value of the axis - * @return new value of the axis - */ - TasAnalog FlipAxisY(TasAnalog old); - /** * Parses a string containing the axis values. X and Y have a range from -32767 to 32767 * @param line: string containing axis values with the following format "x;y" -- 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/common/input.h | 34 ++++++++++- src/common/settings.h | 3 - src/core/hid/emulated_console.cpp | 6 +- src/yuzu/configuration/config.cpp | 4 -- src/yuzu/configuration/configure_motion_touch.cpp | 8 +-- src/yuzu/configuration/configure_motion_touch.ui | 70 +++-------------------- src/yuzu_cmd/config.cpp | 3 - src/yuzu_cmd/default_ini.h | 17 +----- 8 files changed, 46 insertions(+), 99 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index f21872b0a..d997853c6 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -15,6 +15,7 @@ namespace Common::Input { +// Type of data that is expected to recieve or send enum class InputType { None, Battery, @@ -30,6 +31,7 @@ enum class InputType { Ir, }; +// Internal battery charge level enum class BatteryLevel : u32 { None, Empty, @@ -41,13 +43,17 @@ enum class BatteryLevel : u32 { }; enum class PollingMode { + // Constant polling of buttons, analogs and motion data Active, + // Only update on button change, digital analogs Pasive, - Camera, - NCF, + // Enable near field communication polling + NFC, + // Enable infrared camera polling IR, }; +// Vibration reply from the controller enum class VibrationError { None, NotSupported, @@ -55,6 +61,7 @@ enum class VibrationError { Unknown, }; +// Polling mode reply from the controller enum class PollingError { None, NotSupported, @@ -67,20 +74,28 @@ enum class VibrationAmplificationType { Exponential, }; +// Analog properties for calibration struct AnalogProperties { + // Anything below this value will be detected as zero float deadzone{}; + // Anyting above this values will be detected as one float range{1.0f}; + // Minimum value to be detected as active float threshold{0.5f}; + // Drift correction applied to the raw data float offset{}; + // Invert direction of the sensor data bool inverted{}; }; +// Single analog sensor data struct AnalogStatus { float value{}; float raw_value{}; AnalogProperties properties{}; }; +// Button data struct ButtonStatus { Common::UUID uuid{}; bool value{}; @@ -89,8 +104,10 @@ struct ButtonStatus { bool locked{}; }; +// Internal battery data using BatteryStatus = BatteryLevel; +// Analog and digital joystick data struct StickStatus { Common::UUID uuid{}; AnalogStatus x{}; @@ -101,18 +118,21 @@ struct StickStatus { bool down{}; }; +// Analog and digital trigger data struct TriggerStatus { Common::UUID uuid{}; AnalogStatus analog{}; ButtonStatus pressed{}; }; +// 3D vector representing motion input struct MotionSensor { AnalogStatus x{}; AnalogStatus y{}; AnalogStatus z{}; }; +// Motion data used to calculate controller orientation struct MotionStatus { // Gyroscope vector measurement in radians/s. MotionSensor gyro{}; @@ -124,6 +144,7 @@ struct MotionStatus { bool force_update{}; }; +// Data of a single point on a touch screen struct TouchStatus { ButtonStatus pressed{}; AnalogStatus x{}; @@ -131,11 +152,13 @@ struct TouchStatus { int id{}; }; +// Physical controller color in RGB format struct BodyColorStatus { u32 body{}; u32 buttons{}; }; +// HD rumble data struct VibrationStatus { f32 low_amplitude{}; f32 low_frequency{}; @@ -144,6 +167,7 @@ struct VibrationStatus { VibrationAmplificationType type; }; +// Physical controller LED pattern struct LedStatus { bool led_1{}; bool led_2{}; @@ -151,6 +175,7 @@ struct LedStatus { bool led_4{}; }; +// Callback data consisting of an input type and the equivalent data status struct CallbackStatus { InputType type{InputType::None}; ButtonStatus button_status{}; @@ -164,6 +189,7 @@ struct CallbackStatus { VibrationStatus vibration_status{}; }; +// Triggered once every input change struct InputCallback { std::function on_change; }; @@ -178,15 +204,17 @@ public: return; } - // Force input device to update data regarless of the current state + // Force input device to update data regardless of the current state virtual void ForceUpdate() { return; } + // Sets the function to be triggered when input changes void SetCallback(InputCallback callback_) { callback = std::move(callback_); } + // Triggers the function set in the callback void TriggerOnChange(CallbackStatus status) { if (callback.on_change) { callback.on_change(status); diff --git a/src/common/settings.h b/src/common/settings.h index 95225fba7..b52d0d1d0 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -559,8 +559,6 @@ struct Values { Setting enable_accurate_vibrations{false, "enable_accurate_vibrations"}; Setting motion_enabled{true, "motion_enabled"}; - BasicSetting motion_device{"engine:motion_emu,update_period:100,sensitivity:0.01", - "motion_device"}; BasicSetting udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; BasicSetting pause_tas_on_load{true, "pause_tas_on_load"}; @@ -583,7 +581,6 @@ struct Values { TouchscreenInput touchscreen; - BasicSetting use_touch_from_button{false, "use_touch_from_button"}; BasicSetting touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", "touch_device"}; BasicSetting touch_from_button_map_index{0, "touch_from_button_map"}; 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]); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7a748d9c8..7669fe474 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -623,9 +623,7 @@ void Config::ReadMotionTouchValues() { } qt_config->endArray(); - ReadBasicSetting(Settings::values.motion_device); ReadBasicSetting(Settings::values.touch_device); - ReadBasicSetting(Settings::values.use_touch_from_button); ReadBasicSetting(Settings::values.touch_from_button_map_index); Settings::values.touch_from_button_map_index = std::clamp( Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); @@ -1131,9 +1129,7 @@ void Config::SaveTouchscreenValues() { } void Config::SaveMotionTouchValues() { - WriteBasicSetting(Settings::values.motion_device); WriteBasicSetting(Settings::values.touch_device); - WriteBasicSetting(Settings::values.use_touch_from_button); WriteBasicSetting(Settings::values.touch_from_button_map_index); WriteBasicSetting(Settings::values.udp_input_servers); diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index 9fd1a919f..8539a5c8b 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp @@ -93,6 +93,7 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, "using-a-controller-or-android-phone-for-motion-or-touch-input'>Learn More")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); SetConfiguration(); UpdateUiDisplay(); ConnectEvents(); @@ -101,17 +102,14 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, ConfigureMotionTouch::~ConfigureMotionTouch() = default; void ConfigureMotionTouch::SetConfiguration() { - const Common::ParamPackage motion_param(Settings::values.motion_device.GetValue()); const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); - ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button.GetValue()); touch_from_button_maps = Settings::values.touch_from_button_maps; for (const auto& touch_map : touch_from_button_maps) { ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name)); } ui->touch_from_button_map->setCurrentIndex( Settings::values.touch_from_button_map_index.GetValue()); - ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f)); min_x = touch_param.Get("min_x", 100); min_y = touch_param.Get("min_y", 50); @@ -139,9 +137,6 @@ void ConfigureMotionTouch::SetConfiguration() { void ConfigureMotionTouch::UpdateUiDisplay() { const QString cemuhook_udp = QStringLiteral("cemuhookudp"); - ui->motion_sensitivity_label->setVisible(true); - ui->motion_sensitivity->setVisible(true); - ui->touch_calibration->setVisible(true); ui->touch_calibration_config->setVisible(true); ui->touch_calibration_label->setVisible(true); @@ -312,7 +307,6 @@ void ConfigureMotionTouch::ApplyConfiguration() { touch_param.Set("max_y", max_y); Settings::values.touch_device = touch_param.Serialize(); - Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked(); Settings::values.touch_from_button_map_index = ui->touch_from_button_map->currentIndex(); Settings::values.touch_from_button_maps = touch_from_button_maps; Settings::values.udp_input_servers = GetUDPServerString(); diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui index 1e35ea946..c75a84ae4 100644 --- a/src/yuzu/configuration/configure_motion_touch.ui +++ b/src/yuzu/configuration/configure_motion_touch.ui @@ -2,14 +2,6 @@ ConfigureMotionTouch - - - 0 - 0 - 500 - 482 - - Configure Motion / Touch @@ -17,48 +9,6 @@ - - - - Mouse Motion - - - - - - - - Sensitivity: - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 4 - - - 0.010000000000000 - - - 10.000000000000000 - - - 0.001000000000000 - - - 0.010000000000000 - - - - - - - - @@ -101,19 +51,13 @@ - - - - - 0 - 0 - - - - Use button mapping: - - - + + + + Touch from button profile: + + + diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 103a12b12..7ca09a635 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -292,8 +292,6 @@ void Config::ReadValues() { Settings::values.mouse_buttons[i] = default_param; } - ReadSetting("ControlsGeneral", Settings::values.motion_device); - ReadSetting("ControlsGeneral", Settings::values.touch_device); ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); @@ -362,7 +360,6 @@ void Config::ReadValues() { Settings::TouchFromButtonMap{"default", {}}); num_touch_from_button_maps = 1; } - ReadSetting("ControlsGeneral", Settings::values.use_touch_from_button); Settings::values.touch_from_button_map_index = std::clamp( Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index ecdc271a8..6d613bf7a 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -84,23 +84,10 @@ enable_accurate_vibrations= # 0: Disabled, 1 (default): Enabled motion_enabled = -# for motion input, the following devices are available: -# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: -# - "update_period": update period in milliseconds (default to 100) -# - "sensitivity": the coefficient converting mouse movement to tilting angle (default to 0.01) -# - "cemuhookudp" reads motion input from a udp server that uses cemuhook's udp protocol -motion_device= - -# for touch input, the following devices are available: -# - "emu_window" (default) for emulating touch input from mouse input to the emulation window. No parameters required -# - "cemuhookudp" reads touch input from a udp server that uses cemuhook's udp protocol -# - "min_x", "min_y", "max_x", "max_y": defines the udp device's touch screen coordinate system +# Defines the udp device's touch screen coordinate system for cemuhookudp devices +# - "min_x", "min_y", "max_x", "max_y" touch_device= -# Whether to enable or disable touch input from button -# 0 (default): Disabled, 1: Enabled -use_touch_from_button= - # for mapping buttons to touch inputs. #touch_from_button_map=1 #touch_from_button_maps_0_name=default -- 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 +-- src/yuzu/applets/qt_controller.cpp | 65 ++++++----- src/yuzu/applets/qt_controller.h | 8 +- src/yuzu/applets/qt_software_keyboard.cpp | 14 +-- src/yuzu/configuration/configure_input_player.cpp | 87 +++++++------- src/yuzu/configuration/configure_input_player.h | 8 +- .../configure_input_player_widget.cpp | 18 +-- .../configuration/configure_input_player_widget.h | 2 +- src/yuzu/main.cpp | 2 +- 15 files changed, 228 insertions(+), 215 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; } diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 9c6377cf0..6a2cdda63 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -28,31 +28,31 @@ namespace { void UpdateController(Core::HID::EmulatedController* controller, - Core::HID::NpadType controller_type, bool connected) { + Core::HID::NpadStyleIndex controller_type, bool connected) { if (controller->IsConnected()) { controller->Disconnect(); } - controller->SetNpadType(controller_type); + controller->SetNpadStyleIndex(controller_type); if (connected) { controller->Connect(); } } // Returns true if the given controller type is compatible with the given parameters. -bool IsControllerCompatible(Core::HID::NpadType controller_type, +bool IsControllerCompatible(Core::HID::NpadStyleIndex controller_type, Core::Frontend::ControllerParameters parameters) { switch (controller_type) { - case Core::HID::NpadType::ProController: + case Core::HID::NpadStyleIndex::ProController: return parameters.allow_pro_controller; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: return parameters.allow_dual_joycons; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: return parameters.allow_left_joycon; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: return parameters.allow_right_joycon; - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: return parameters.enable_single_mode && parameters.allow_handheld; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: return parameters.allow_gamecube_controller; default: return false; @@ -183,7 +183,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( connect(emulated_controllers[i], qOverload(&QComboBox::currentIndexChanged), [this, i](int index) { UpdateDockedState(GetControllerTypeFromIndex(index, i) == - Core::HID::NpadType::Handheld); + Core::HID::NpadStyleIndex::Handheld); }); } } @@ -243,7 +243,7 @@ void QtControllerSelectorDialog::LoadConfiguration() { player_groupboxes[index]->setChecked(connected); connected_controller_checkboxes[index]->setChecked(connected); emulated_controllers[index]->setCurrentIndex( - GetIndexFromControllerType(controller->GetNpadType(), index)); + GetIndexFromControllerType(controller->GetNpadStyleIndex(), index)); } UpdateDockedState(handheld->IsConnected()); @@ -402,32 +402,33 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index emulated_controllers[player_index]->clear(); pairs.emplace_back(emulated_controllers[player_index]->count(), - Core::HID::NpadType::ProController); + Core::HID::NpadStyleIndex::ProController); emulated_controllers[player_index]->addItem(tr("Pro Controller")); pairs.emplace_back(emulated_controllers[player_index]->count(), - Core::HID::NpadType::JoyconDual); + Core::HID::NpadStyleIndex::JoyconDual); emulated_controllers[player_index]->addItem(tr("Dual Joycons")); pairs.emplace_back(emulated_controllers[player_index]->count(), - Core::HID::NpadType::JoyconLeft); + Core::HID::NpadStyleIndex::JoyconLeft); emulated_controllers[player_index]->addItem(tr("Left Joycon")); pairs.emplace_back(emulated_controllers[player_index]->count(), - Core::HID::NpadType::JoyconRight); + Core::HID::NpadStyleIndex::JoyconRight); emulated_controllers[player_index]->addItem(tr("Right Joycon")); if (player_index == 0) { pairs.emplace_back(emulated_controllers[player_index]->count(), - Core::HID::NpadType::Handheld); + Core::HID::NpadStyleIndex::Handheld); emulated_controllers[player_index]->addItem(tr("Handheld")); } - pairs.emplace_back(emulated_controllers[player_index]->count(), Core::HID::NpadType::GameCube); + pairs.emplace_back(emulated_controllers[player_index]->count(), + Core::HID::NpadStyleIndex::GameCube); emulated_controllers[player_index]->addItem(tr("GameCube Controller")); } -Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex( +Core::HID::NpadStyleIndex QtControllerSelectorDialog::GetControllerTypeFromIndex( int index, std::size_t player_index) const { const auto& pairs = index_controller_type_pairs[player_index]; @@ -435,13 +436,13 @@ Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex( [index](const auto& pair) { return pair.first == index; }); if (it == pairs.end()) { - return Core::HID::NpadType::ProController; + return Core::HID::NpadStyleIndex::ProController; } return it->second; } -int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadType type, +int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadStyleIndex type, std::size_t player_index) const { const auto& pairs = index_controller_type_pairs[player_index]; @@ -465,16 +466,16 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) const QString stylesheet = [this, player_index] { switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), player_index)) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::GameCube: return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); "); - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: return QStringLiteral("image: url(:/controller/applet_joycon_left%0); "); - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: return QStringLiteral("image: url(:/controller/applet_joycon_right%0); "); - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: return QStringLiteral("image: url(:/controller/applet_handheld%0); "); default: return QString{}; @@ -507,9 +508,9 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) const auto controller_type = GetControllerTypeFromIndex( emulated_controllers[player_index]->currentIndex(), player_index); const auto player_connected = player_groupboxes[player_index]->isChecked() && - controller_type != Core::HID::NpadType::Handheld; + controller_type != Core::HID::NpadStyleIndex::Handheld; - if (controller->GetNpadType() == controller_type && + if (controller->GetNpadStyleIndex() == controller_type && controller->IsConnected() == player_connected) { // Set vibration devices in the event that the input device has changed. ConfigureVibration::SetVibrationDevices(player_index); @@ -523,10 +524,10 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) // Handheld if (player_index == 0) { - if (controller_type == Core::HID::NpadType::Handheld) { + if (controller_type == Core::HID::NpadStyleIndex::Handheld) { auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - UpdateController(handheld, Core::HID::NpadType::Handheld, + UpdateController(handheld, Core::HID::NpadStyleIndex::Handheld, player_groupboxes[player_index]->isChecked()); } } @@ -537,7 +538,7 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { if (!player_groupboxes[player_index]->isChecked() || GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), - player_index) == Core::HID::NpadType::Handheld) { + player_index) == Core::HID::NpadStyleIndex::Handheld) { led_patterns_boxes[player_index][0]->setChecked(false); led_patterns_boxes[player_index][1]->setChecked(false); led_patterns_boxes[player_index][2]->setChecked(false); @@ -632,7 +633,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); // Disconnect any unsupported players here and disable or hide them if applicable. - UpdateController(controller, controller->GetNpadType(), false); + UpdateController(controller, controller->GetNpadStyleIndex(), false); // Hide the player widgets when max_supported_controllers is less than or equal to 4. if (max_supported_players <= 4) { player_widgets[index]->hide(); diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h index dd981f479..cc343e5ae 100644 --- a/src/yuzu/applets/qt_controller.h +++ b/src/yuzu/applets/qt_controller.h @@ -32,7 +32,7 @@ class System; } namespace Core::HID { -enum class NpadType : u8; +enum class NpadStyleIndex : u8; } class QtControllerSelectorDialog final : public QDialog { @@ -74,10 +74,10 @@ private: void SetEmulatedControllers(std::size_t player_index); // Gets the Controller Type for a given controller combobox index per player. - Core::HID::NpadType GetControllerTypeFromIndex(int index, std::size_t player_index) const; + Core::HID::NpadStyleIndex GetControllerTypeFromIndex(int index, std::size_t player_index) const; // Gets the controller combobox index for a given Controller Type per player. - int GetIndexFromControllerType(Core::HID::NpadType type, std::size_t player_index) const; + int GetIndexFromControllerType(Core::HID::NpadStyleIndex type, std::size_t player_index) const; // Updates the controller icons per player. void UpdateControllerIcon(std::size_t player_index); @@ -139,7 +139,7 @@ private: std::array emulated_controllers; /// Pairs of emulated controller index and Controller Type enum per player. - std::array>, NUM_PLAYERS> + std::array>, NUM_PLAYERS> index_controller_type_pairs; // Labels representing the number of connected controllers diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index 3d91f8034..de7f98c4f 100644 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp @@ -801,7 +801,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); const auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); const auto controller_type = - handheld->IsConnected() ? handheld->GetNpadType() : player_1->GetNpadType(); + handheld->IsConnected() ? handheld->GetNpadStyleIndex() : player_1->GetNpadStyleIndex(); const QString theme = [] { if (QIcon::themeName().contains(QStringLiteral("dark")) || @@ -813,8 +813,8 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { }(); switch (controller_type) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::GameCube: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); ui->icon_controller_shift->setStyleSheet( @@ -822,7 +822,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { ui->icon_controller_num->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); break; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); ui->icon_controller_shift->setStyleSheet( @@ -830,7 +830,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { ui->icon_controller_num->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); break; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") .arg(theme)); @@ -841,7 +841,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") .arg(theme)); break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") .arg(theme)); @@ -852,7 +852,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() { QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") .arg(theme)); break; - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: ui->icon_controller->setStyleSheet( QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); ui->icon_controller_shift->setStyleSheet( diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 8d6289d8e..95a9b8614 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -455,7 +455,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i connect(ui->comboControllerType, qOverload(&QComboBox::currentIndexChanged), [this](int index) { emit HandheldStateChanged(GetControllerTypeFromIndex(index) == - Core::HID::NpadType::Handheld); + Core::HID::NpadStyleIndex::Handheld); }); } @@ -482,7 +482,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); - const Core::HID::NpadType type = + const Core::HID::NpadStyleIndex type = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (player_index == 0) { @@ -492,10 +492,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); bool is_connected = emulated_controller->IsConnected(true); - emulated_controller_p1->SetNpadType(type); - emulated_controller_hanheld->SetNpadType(type); + emulated_controller_p1->SetNpadStyleIndex(type); + emulated_controller_hanheld->SetNpadStyleIndex(type); if (is_connected) { - if (type == Core::HID::NpadType::Handheld) { + if (type == Core::HID::NpadStyleIndex::Handheld) { emulated_controller_p1->Disconnect(); emulated_controller_hanheld->Connect(); emulated_controller = emulated_controller_hanheld; @@ -507,7 +507,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i } ui->controllerFrame->SetController(emulated_controller); } - emulated_controller->SetNpadType(type); + emulated_controller->SetNpadStyleIndex(type); }); connect(ui->comboDevices, qOverload(&QComboBox::activated), this, @@ -607,7 +607,8 @@ void ConfigureInputPlayer::LoadConfiguration() { return; } - const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType(true)); + const int comboBoxIndex = + GetIndexFromControllerType(emulated_controller->GetNpadStyleIndex(true)); ui->comboControllerType->setCurrentIndex(comboBoxIndex); ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true)); } @@ -810,37 +811,37 @@ void ConfigureInputPlayer::SetConnectableControllers() { if (enable_all || npad_style_set.fullkey == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadType::ProController); + Core::HID::NpadStyleIndex::ProController); ui->comboControllerType->addItem(tr("Pro Controller")); } if (enable_all || npad_style_set.joycon_dual == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadType::JoyconDual); + Core::HID::NpadStyleIndex::JoyconDual); ui->comboControllerType->addItem(tr("Dual Joycons")); } if (enable_all || npad_style_set.joycon_left == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadType::JoyconLeft); + Core::HID::NpadStyleIndex::JoyconLeft); ui->comboControllerType->addItem(tr("Left Joycon")); } if (enable_all || npad_style_set.joycon_right == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadType::JoyconRight); + Core::HID::NpadStyleIndex::JoyconRight); ui->comboControllerType->addItem(tr("Right Joycon")); } if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadType::Handheld); + Core::HID::NpadStyleIndex::Handheld); ui->comboControllerType->addItem(tr("Handheld")); } if (enable_all || npad_style_set.gamecube == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadType::GameCube); + Core::HID::NpadStyleIndex::GameCube); ui->comboControllerType->addItem(tr("GameCube Controller")); } }; @@ -853,19 +854,19 @@ void ConfigureInputPlayer::SetConnectableControllers() { add_controllers(false, system.HIDCore().GetSupportedStyleTag()); } -Core::HID::NpadType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { +Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { const auto it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [index](const auto& pair) { return pair.first == index; }); if (it == index_controller_type_pairs.end()) { - return Core::HID::NpadType::ProController; + return Core::HID::NpadStyleIndex::ProController; } return it->second; } -int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadType type) const { +int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadStyleIndex type) const { const auto it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [type](const auto& pair) { return pair.second == type; }); @@ -888,7 +889,7 @@ void ConfigureInputPlayer::UpdateInputDevices() { void ConfigureInputPlayer::UpdateControllerAvailableButtons() { auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (debug) { - layout = Core::HID::NpadType::ProController; + layout = Core::HID::NpadStyleIndex::ProController; } // List of all the widgets that will be hidden by any of the following layouts that need @@ -913,15 +914,15 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { std::vector layout_hidden; switch (layout) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::JoyconDual: - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: layout_hidden = { ui->buttonShoulderButtonsSLSR, ui->horizontalSpacerShoulderButtonsWidget2, }; break; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: layout_hidden = { ui->horizontalSpacerShoulderButtonsWidget2, ui->buttonShoulderButtonsRight, @@ -929,7 +930,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { ui->bottomRight, }; break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: layout_hidden = { ui->horizontalSpacerShoulderButtonsWidget, ui->buttonShoulderButtonsLeft, @@ -937,7 +938,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { ui->bottomLeft, }; break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: layout_hidden = { ui->buttonShoulderButtonsSLSR, ui->horizontalSpacerShoulderButtonsWidget2, @@ -957,7 +958,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { void ConfigureInputPlayer::UpdateControllerEnabledButtons() { auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (debug) { - layout = Core::HID::NpadType::ProController; + layout = Core::HID::NpadStyleIndex::ProController; } // List of all the widgets that will be disabled by any of the following layouts that need @@ -974,13 +975,13 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() { std::vector layout_disable; switch (layout) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::JoyconDual: - case Core::HID::NpadType::Handheld: - case Core::HID::NpadType::JoyconLeft: - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconRight: break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: layout_disable = { ui->buttonHome, ui->buttonLStickPressedGroup, @@ -1007,24 +1008,24 @@ void ConfigureInputPlayer::UpdateMotionButtons() { // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::JoyconLeft: - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::Handheld: // Show "Motion 1" and hide "Motion 2". ui->buttonMotionLeftGroup->show(); ui->buttonMotionRightGroup->hide(); break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: // Show "Motion 2" and hide "Motion 1". ui->buttonMotionLeftGroup->hide(); ui->buttonMotionRightGroup->show(); break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: // Hide both "Motion 1/2". ui->buttonMotionLeftGroup->hide(); ui->buttonMotionRightGroup->hide(); break; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: default: // Show both "Motion 1/2". ui->buttonMotionLeftGroup->show(); @@ -1036,15 +1037,15 @@ void ConfigureInputPlayer::UpdateMotionButtons() { void ConfigureInputPlayer::UpdateControllerButtonNames() { auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (debug) { - layout = Core::HID::NpadType::ProController; + layout = Core::HID::NpadStyleIndex::ProController; } switch (layout) { - case Core::HID::NpadType::ProController: - case Core::HID::NpadType::JoyconDual: - case Core::HID::NpadType::Handheld: - case Core::HID::NpadType::JoyconLeft: - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconRight: ui->buttonMiscButtonsPlusGroup->setTitle(tr("Plus")); ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("ZL")); ui->buttonShoulderButtonsZRGroup->setTitle(tr("ZR")); @@ -1052,7 +1053,7 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() { ui->LStick->setTitle(tr("Left Stick")); ui->RStick->setTitle(tr("Right Stick")); break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: ui->buttonMiscButtonsPlusGroup->setTitle(tr("Start / Pause")); ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("L")); ui->buttonShoulderButtonsZRGroup->setTitle(tr("R")); diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 02d6920f1..7bff4b196 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -51,7 +51,7 @@ class System; namespace Core::HID { class EmulatedController; -enum class NpadType : u8; +enum class NpadStyleIndex : u8; } // namespace Core::HID class ConfigureInputPlayer : public QWidget { @@ -134,10 +134,10 @@ private: void SetConnectableControllers(); /// Gets the Controller Type for a given controller combobox index. - Core::HID::NpadType GetControllerTypeFromIndex(int index) const; + Core::HID::NpadStyleIndex GetControllerTypeFromIndex(int index) const; /// Gets the controller combobox index for a given Controller Type. - int GetIndexFromControllerType(Core::HID::NpadType type) const; + int GetIndexFromControllerType(Core::HID::NpadStyleIndex type) const; /// Update the available input devices. void UpdateInputDevices(); @@ -182,7 +182,7 @@ private: std::unique_ptr poll_timer; /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum. - std::vector> index_controller_type_pairs; + std::vector> index_controller_type_pairs; static constexpr int PLAYER_COUNT = 8; std::array player_connected_checkbox; diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 7e71a0f58..e63c25e70 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -147,7 +147,7 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ needs_redraw = true; break; case Core::HID::ControllerTriggerType::Type: - controller_type = controller->GetNpadType(true); + controller_type = controller->GetNpadStyleIndex(true); needs_redraw = true; break; case Core::HID::ControllerTriggerType::Color: @@ -221,22 +221,22 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) { const QPointF center = rect().center(); switch (controller_type) { - case Core::HID::NpadType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: DrawHandheldController(p, center); break; - case Core::HID::NpadType::JoyconDual: + case Core::HID::NpadStyleIndex::JoyconDual: DrawDualController(p, center); break; - case Core::HID::NpadType::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconLeft: DrawLeftController(p, center); break; - case Core::HID::NpadType::JoyconRight: + case Core::HID::NpadStyleIndex::JoyconRight: DrawRightController(p, center); break; - case Core::HID::NpadType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: DrawGCController(p, center); break; - case Core::HID::NpadType::ProController: + case Core::HID::NpadStyleIndex::ProController: default: DrawProController(p, center); break; @@ -2394,7 +2394,7 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) { using namespace Settings::NativeAnalog; - if (controller_type != Core::HID::NpadType::JoyconLeft) { + if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties); p.setPen(colors.indicator); p.setBrush(colors.indicator); @@ -2404,7 +2404,7 @@ void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPo DrawJoystickDot(p, center_right, stick_values[RStick], false); } - if (controller_type != Core::HID::NpadType::JoyconRight) { + if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties); p.setPen(colors.indicator); p.setBrush(colors.indicator); diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index acc53a9e3..ee217f3c9 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -203,7 +203,7 @@ private: bool is_controller_set{}; bool is_connected{}; bool needs_redraw{}; - Core::HID::NpadType controller_type; + Core::HID::NpadStyleIndex controller_type; bool mapping_active{}; int blink_counter{}; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 7c95851b3..a10522f5f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -841,7 +841,7 @@ void GMainWindow::InitializeWidgets() { tr("Handheld controller can't be used on docked mode. Pro " "controller will be selected.")); handheld->Disconnect(); - player_1->SetNpadType(Core::HID::NpadType::ProController); + player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); player_1->Connect(); } -- 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 ++-- src/yuzu/configuration/configure_input_player_widget.cpp | 4 ++-- src/yuzu/main.cpp | 3 +++ 3 files changed, 7 insertions(+), 4 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; diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index e63c25e70..af65cf64c 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -2394,7 +2394,7 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) { using namespace Settings::NativeAnalog; - if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { + if (center_right != QPointF(0, 0)) { DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties); p.setPen(colors.indicator); p.setBrush(colors.indicator); @@ -2404,7 +2404,7 @@ void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPo DrawJoystickDot(p, center_right, stick_values[RStick], false); } - if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { + if (center_left != QPointF(0, 0)) { DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties); p.setPen(colors.indicator); p.setBrush(colors.indicator); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a10522f5f..baf7b38b4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -230,6 +230,7 @@ GMainWindow::GMainWindow() ConnectWidgetEvents(); system->HIDCore().ReloadInputDevices(); + controller_dialog->refreshConfiguration(); const auto branch_name = std::string(Common::g_scm_branch); const auto description = std::string(Common::g_scm_desc); @@ -843,6 +844,7 @@ void GMainWindow::InitializeWidgets() { handheld->Disconnect(); player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); player_1->Connect(); + controller_dialog->refreshConfiguration(); } Settings::values.use_docked_mode.SetValue(!is_docked); @@ -2744,6 +2746,7 @@ void GMainWindow::OnConfigure() { } UpdateStatusButtons(); + controller_dialog->refreshConfiguration(); } void GMainWindow::OnConfigureTas() { -- 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 ++-- src/yuzu/bootmanager.cpp | 1 - src/yuzu/debugger/controller.cpp | 10 +++++----- src/yuzu/debugger/controller.h | 9 +++------ src/yuzu/main.cpp | 2 +- 29 files changed, 67 insertions(+), 67 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); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 4b3cd9f3e..3c5590a01 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -27,7 +27,6 @@ #include "common/assert.h" #include "common/microprofile.h" -#include "common/param_package.h" #include "common/scm_rev.h" #include "common/scope_exit.h" #include "common/settings.h" diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp index aaca494b8..6b834c42e 100644 --- a/src/yuzu/debugger/controller.cpp +++ b/src/yuzu/debugger/controller.cpp @@ -6,17 +6,17 @@ #include #include #include "common/settings.h" -#include "core/core.h" #include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "input_common/drivers/tas_input.h" #include "input_common/main.h" #include "yuzu/configuration/configure_input_player_widget.h" #include "yuzu/debugger/controller.h" -ControllerDialog::ControllerDialog(Core::System& system_, +ControllerDialog::ControllerDialog(Core::HID::HIDCore& hid_core_, std::shared_ptr input_subsystem_, QWidget* parent) - : QWidget(parent, Qt::Dialog), system{system_}, input_subsystem{input_subsystem_} { + : QWidget(parent, Qt::Dialog), hid_core{hid_core_}, input_subsystem{input_subsystem_} { setObjectName(QStringLiteral("Controller")); setWindowTitle(tr("Controller P1")); resize(500, 350); @@ -41,8 +41,8 @@ ControllerDialog::ControllerDialog(Core::System& system_, void ControllerDialog::refreshConfiguration() { UnloadController(); - auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + auto* player_1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); // Display the correct controller controller = handheld->IsConnected() ? handheld : player_1; diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h index d08643baa..52cea3326 100644 --- a/src/yuzu/debugger/controller.h +++ b/src/yuzu/debugger/controller.h @@ -15,11 +15,8 @@ namespace InputCommon { class InputSubsystem; } -namespace Core { -class System; -} - namespace Core::HID { +class HIDCore; class EmulatedController; enum class ControllerTriggerType; } // namespace Core::HID @@ -28,7 +25,7 @@ class ControllerDialog : public QWidget { Q_OBJECT public: - explicit ControllerDialog(Core::System& system_, + explicit ControllerDialog(Core::HID::HIDCore& hid_core_, std::shared_ptr input_subsystem_, QWidget* parent = nullptr); @@ -55,6 +52,6 @@ private: QAction* toggle_view_action = nullptr; PlayerControlPreview* widget; - Core::System& system; + Core::HID::HIDCore& hid_core; std::shared_ptr input_subsystem; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index baf7b38b4..cd8ea221d 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -928,7 +928,7 @@ void GMainWindow::InitializeDebugWidgets() { waitTreeWidget->hide(); debug_menu->addAction(waitTreeWidget->toggleViewAction()); - controller_dialog = new ControllerDialog(*system, input_subsystem, this); + controller_dialog = new ControllerDialog(system->HIDCore(), input_subsystem, this); controller_dialog->hide(); debug_menu->addAction(controller_dialog->toggleViewAction()); -- 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 ++++++------ src/yuzu/configuration/configure_input_player.cpp | 4 +- .../configure_input_player_widget.cpp | 24 +- 11 files changed, 632 insertions(+), 428 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); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 76f55eb54..0254ea6fe 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -627,7 +627,8 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { return; } - const auto devices = emulated_controller->GetMappedDevices(Core::HID::DeviceIndex::AllDevices); + const auto devices = + emulated_controller->GetMappedDevices(Core::HID::EmulatedDeviceIndex::AllDevices); UpdateInputDevices(); if (devices.empty()) { @@ -846,6 +847,7 @@ void ConfigureInputPlayer::SetConnectableControllers() { if (!is_powered_on) { add_controllers(true); + return; } add_controllers(false, hid_core.GetSupportedStyleTag()); diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index ff40f57f5..6630321cb 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -357,7 +357,8 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) DrawCircle(p, center + QPoint(26, 71), 5); // Draw battery - DrawBattery(p, center + QPoint(-170, -140), battery_values[Core::HID::DeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(-170, -140), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); } void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) { @@ -483,7 +484,8 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); // Draw battery - DrawBattery(p, center + QPoint(110, -140), battery_values[Core::HID::DeviceIndex::RightIndex]); + DrawBattery(p, center + QPoint(110, -140), + battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); } void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { @@ -619,8 +621,10 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); // Draw battery - DrawBattery(p, center + QPoint(-100, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]); - DrawBattery(p, center + QPoint(40, -160), battery_values[Core::HID::DeviceIndex::RightIndex]); + DrawBattery(p, center + QPoint(-100, -160), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(40, -160), + battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); } void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) { @@ -721,8 +725,10 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); // Draw battery - DrawBattery(p, center + QPoint(-200, 110), battery_values[Core::HID::DeviceIndex::LeftIndex]); - DrawBattery(p, center + QPoint(130, 110), battery_values[Core::HID::DeviceIndex::RightIndex]); + DrawBattery(p, center + QPoint(-200, 110), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(130, 110), + battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); } void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { @@ -812,7 +818,8 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); // Draw battery - DrawBattery(p, center + QPoint(-30, -160), battery_values[Core::HID::DeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(-30, -160), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); } void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { @@ -868,7 +875,8 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8); // Draw battery - DrawBattery(p, center + QPoint(-30, -165), battery_values[Core::HID::DeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(-30, -165), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); } constexpr std::array symbol_a = { -- 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/common/settings_input.h | 35 +- 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 + src/input_common/drivers/keyboard.cpp | 53 ++- src/input_common/drivers/keyboard.h | 7 + src/input_common/main.cpp | 9 + src/input_common/main.h | 3 + src/yuzu/bootmanager.cpp | 276 ++++++++++++++- src/yuzu/bootmanager.h | 6 + src/yuzu/configuration/config.cpp | 167 +-------- 13 files changed, 682 insertions(+), 313 deletions(-) (limited to 'src/core') diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 2c0eb31d3..a2982fca4 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h @@ -129,7 +129,6 @@ extern const std::array mapping; namespace NativeKeyboard { enum Keys { None, - Error, A = 4, B, @@ -167,22 +166,22 @@ enum Keys { N8, N9, N0, - Enter, + Return, Escape, Backspace, Tab, Space, Minus, - Equal, - LeftBrace, - RightBrace, - Backslash, + Plus, + OpenBracket, + CloseBracket, + Pipe, Tilde, Semicolon, - Apostrophe, - Grave, + Quote, + Backquote, Comma, - Dot, + Period, Slash, CapsLockKey, @@ -199,7 +198,7 @@ enum Keys { F11, F12, - SystemRequest, + PrintScreen, ScrollLockKey, Pause, Insert, @@ -268,8 +267,18 @@ enum Keys { ScrollLockActive, KPComma, - KPLeftParenthesis, - KPRightParenthesis, + Ro = 0x87, + KatakanaHiragana, + Yen, + Henkan, + Muhenkan, + NumPadCommaPc98, + + HangulEnglish = 0x90, + Hanja, + KatakanaKey, + HiraganaKey, + ZenkakuHankaku, LeftControlKey = 0xE0, LeftShiftKey, @@ -318,6 +327,8 @@ enum Modifiers { CapsLock, ScrollLock, NumLock, + Katakana, + Hiragana, NumKeyboardMods, }; 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)> diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp index 549704e89..328fe1ac1 100644 --- a/src/input_common/drivers/keyboard.cpp +++ b/src/input_common/drivers/keyboard.cpp @@ -3,26 +3,71 @@ // Refer to the license.txt file included #include "common/param_package.h" +#include "common/settings_input.h" #include "input_common/drivers/keyboard.h" namespace InputCommon { -constexpr PadIdentifier identifier = { +constexpr PadIdentifier key_identifier = { .guid = Common::UUID{Common::INVALID_UUID}, .port = 0, .pad = 0, }; +constexpr PadIdentifier modifier_identifier = { + .guid = Common::UUID{Common::INVALID_UUID}, + .port = 0, + .pad = 1, +}; Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) { - PreSetController(identifier); + PreSetController(key_identifier); + PreSetController(modifier_identifier); } void Keyboard::PressKey(int key_code) { - SetButton(identifier, key_code, true); + SetButton(key_identifier, key_code, true); } void Keyboard::ReleaseKey(int key_code) { - SetButton(identifier, key_code, false); + SetButton(key_identifier, key_code, false); +} + +void Keyboard::SetModifiers(int key_modifiers) { + for (int i = 0; i < 32; ++i) { + bool key_value = ((key_modifiers >> i) & 0x1) != 0; + SetButton(modifier_identifier, i, key_value); + // Use the modifier to press the key button equivalent + switch (i) { + case Settings::NativeKeyboard::LeftControl: + SetButton(key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value); + break; + case Settings::NativeKeyboard::LeftShift: + SetButton(key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value); + break; + case Settings::NativeKeyboard::LeftAlt: + SetButton(key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value); + break; + case Settings::NativeKeyboard::LeftMeta: + SetButton(key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value); + break; + case Settings::NativeKeyboard::RightControl: + SetButton(key_identifier, Settings::NativeKeyboard::RightControlKey, key_value); + break; + case Settings::NativeKeyboard::RightShift: + SetButton(key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value); + break; + case Settings::NativeKeyboard::RightAlt: + SetButton(key_identifier, Settings::NativeKeyboard::RightAltKey, key_value); + break; + case Settings::NativeKeyboard::RightMeta: + SetButton(key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value); + break; + default: + // Other modifier keys should be pressed with PressKey since they stay enabled until + // next press + break; + } + } } void Keyboard::ReleaseAllKeys() { diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h index 46fe78576..2ab92fd6c 100644 --- a/src/input_common/drivers/keyboard.h +++ b/src/input_common/drivers/keyboard.h @@ -28,6 +28,13 @@ public: */ void ReleaseKey(int key_code); + /** + * Sets the status of all keyboard modifier keys + * @param key_modifiers the code of the key to release + */ + void SetModifiers(int key_modifiers); + + /// Sets all keys to the non pressed state void ReleaseAllKeys(); /// Used for automapping features diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index df36a337c..ae2518f53 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -402,6 +402,15 @@ std::string GenerateKeyboardParam(int key_code) { return param.Serialize(); } +std::string GenerateModdifierKeyboardParam(int key_code) { + Common::ParamPackage param; + param.Set("engine", "keyboard"); + param.Set("code", key_code); + param.Set("toggle", false); + param.Set("pad", 1); + return param.Serialize(); +} + std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, int key_modifier, float modifier_scale) { Common::ParamPackage circle_pad_param{ diff --git a/src/input_common/main.h b/src/input_common/main.h index a4a24d076..9ea395465 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h @@ -134,6 +134,9 @@ private: /// Generates a serialized param package for creating a keyboard button device. std::string GenerateKeyboardParam(int key_code); +/// Generates a serialized param package for creating a moddifier keyboard button device. +std::string GenerateModdifierKeyboardParam(int key_code); + /// Generates a serialized param package for creating an analog device taking input from keyboard. std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, int key_modifier, float modifier_scale); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 3c5590a01..61513a5b4 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -392,15 +392,287 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { QWidget::closeEvent(event); } +int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { + switch (qt_key) { + case Qt::Key_A: + return Settings::NativeKeyboard::A; + case Qt::Key_B: + return Settings::NativeKeyboard::B; + case Qt::Key_C: + return Settings::NativeKeyboard::C; + case Qt::Key_D: + return Settings::NativeKeyboard::D; + case Qt::Key_E: + return Settings::NativeKeyboard::E; + case Qt::Key_F: + return Settings::NativeKeyboard::F; + case Qt::Key_G: + return Settings::NativeKeyboard::G; + case Qt::Key_H: + return Settings::NativeKeyboard::H; + case Qt::Key_I: + return Settings::NativeKeyboard::I; + case Qt::Key_J: + return Settings::NativeKeyboard::J; + case Qt::Key_K: + return Settings::NativeKeyboard::K; + case Qt::Key_L: + return Settings::NativeKeyboard::L; + case Qt::Key_M: + return Settings::NativeKeyboard::M; + case Qt::Key_N: + return Settings::NativeKeyboard::N; + case Qt::Key_O: + return Settings::NativeKeyboard::O; + case Qt::Key_P: + return Settings::NativeKeyboard::P; + case Qt::Key_Q: + return Settings::NativeKeyboard::Q; + case Qt::Key_R: + return Settings::NativeKeyboard::R; + case Qt::Key_S: + return Settings::NativeKeyboard::S; + case Qt::Key_T: + return Settings::NativeKeyboard::T; + case Qt::Key_U: + return Settings::NativeKeyboard::U; + case Qt::Key_V: + return Settings::NativeKeyboard::V; + case Qt::Key_W: + return Settings::NativeKeyboard::W; + case Qt::Key_X: + return Settings::NativeKeyboard::X; + case Qt::Key_Y: + return Settings::NativeKeyboard::Y; + case Qt::Key_Z: + return Settings::NativeKeyboard::Z; + case Qt::Key_1: + return Settings::NativeKeyboard::N1; + case Qt::Key_2: + return Settings::NativeKeyboard::N2; + case Qt::Key_3: + return Settings::NativeKeyboard::N3; + case Qt::Key_4: + return Settings::NativeKeyboard::N4; + case Qt::Key_5: + return Settings::NativeKeyboard::N5; + case Qt::Key_6: + return Settings::NativeKeyboard::N6; + case Qt::Key_7: + return Settings::NativeKeyboard::N7; + case Qt::Key_8: + return Settings::NativeKeyboard::N8; + case Qt::Key_9: + return Settings::NativeKeyboard::N9; + case Qt::Key_0: + return Settings::NativeKeyboard::N0; + case Qt::Key_Return: + return Settings::NativeKeyboard::Return; + case Qt::Key_Escape: + return Settings::NativeKeyboard::Escape; + case Qt::Key_Backspace: + return Settings::NativeKeyboard::Backspace; + case Qt::Key_Tab: + return Settings::NativeKeyboard::Tab; + case Qt::Key_Space: + return Settings::NativeKeyboard::Space; + case Qt::Key_Minus: + return Settings::NativeKeyboard::Minus; + case Qt::Key_Plus: + case Qt::Key_questiondown: + return Settings::NativeKeyboard::Plus; + case Qt::Key_BracketLeft: + case Qt::Key_BraceLeft: + return Settings::NativeKeyboard::OpenBracket; + case Qt::Key_BracketRight: + case Qt::Key_BraceRight: + return Settings::NativeKeyboard::CloseBracket; + case Qt::Key_Bar: + return Settings::NativeKeyboard::Pipe; + case Qt::Key_Dead_Tilde: + return Settings::NativeKeyboard::Tilde; + case Qt::Key_Ntilde: + case Qt::Key_Semicolon: + return Settings::NativeKeyboard::Semicolon; + case Qt::Key_Apostrophe: + return Settings::NativeKeyboard::Quote; + case Qt::Key_Dead_Grave: + return Settings::NativeKeyboard::Backquote; + case Qt::Key_Comma: + return Settings::NativeKeyboard::Comma; + case Qt::Key_Period: + return Settings::NativeKeyboard::Period; + case Qt::Key_Slash: + return Settings::NativeKeyboard::Slash; + case Qt::Key_CapsLock: + return Settings::NativeKeyboard::CapsLock; + case Qt::Key_F1: + return Settings::NativeKeyboard::F1; + case Qt::Key_F2: + return Settings::NativeKeyboard::F2; + case Qt::Key_F3: + return Settings::NativeKeyboard::F3; + case Qt::Key_F4: + return Settings::NativeKeyboard::F4; + case Qt::Key_F5: + return Settings::NativeKeyboard::F5; + case Qt::Key_F6: + return Settings::NativeKeyboard::F6; + case Qt::Key_F7: + return Settings::NativeKeyboard::F7; + case Qt::Key_F8: + return Settings::NativeKeyboard::F8; + case Qt::Key_F9: + return Settings::NativeKeyboard::F9; + case Qt::Key_F10: + return Settings::NativeKeyboard::F10; + case Qt::Key_F11: + return Settings::NativeKeyboard::F11; + case Qt::Key_F12: + return Settings::NativeKeyboard::F12; + case Qt::Key_Print: + return Settings::NativeKeyboard::PrintScreen; + case Qt::Key_ScrollLock: + return Settings::NativeKeyboard::ScrollLock; + case Qt::Key_Pause: + return Settings::NativeKeyboard::Pause; + case Qt::Key_Insert: + return Settings::NativeKeyboard::Insert; + case Qt::Key_Home: + return Settings::NativeKeyboard::Home; + case Qt::Key_PageUp: + return Settings::NativeKeyboard::PageUp; + case Qt::Key_Delete: + return Settings::NativeKeyboard::Delete; + case Qt::Key_End: + return Settings::NativeKeyboard::End; + case Qt::Key_PageDown: + return Settings::NativeKeyboard::PageDown; + case Qt::Key_Right: + return Settings::NativeKeyboard::Right; + case Qt::Key_Left: + return Settings::NativeKeyboard::Left; + case Qt::Key_Down: + return Settings::NativeKeyboard::Down; + case Qt::Key_Up: + return Settings::NativeKeyboard::Up; + case Qt::Key_NumLock: + return Settings::NativeKeyboard::NumLock; + // Numpad keys are missing here + case Qt::Key_F13: + return Settings::NativeKeyboard::F13; + case Qt::Key_F14: + return Settings::NativeKeyboard::F14; + case Qt::Key_F15: + return Settings::NativeKeyboard::F15; + case Qt::Key_F16: + return Settings::NativeKeyboard::F16; + case Qt::Key_F17: + return Settings::NativeKeyboard::F17; + case Qt::Key_F18: + return Settings::NativeKeyboard::F18; + case Qt::Key_F19: + return Settings::NativeKeyboard::F19; + case Qt::Key_F20: + return Settings::NativeKeyboard::F20; + case Qt::Key_F21: + return Settings::NativeKeyboard::F21; + case Qt::Key_F22: + return Settings::NativeKeyboard::F22; + case Qt::Key_F23: + return Settings::NativeKeyboard::F23; + case Qt::Key_F24: + return Settings::NativeKeyboard::F24; + // case Qt::: + // return Settings::NativeKeyboard::KPComma; + // case Qt::: + // return Settings::NativeKeyboard::Ro; + case Qt::Key_Hiragana_Katakana: + return Settings::NativeKeyboard::KatakanaHiragana; + case Qt::Key_yen: + return Settings::NativeKeyboard::Yen; + case Qt::Key_Henkan: + return Settings::NativeKeyboard::Henkan; + case Qt::Key_Muhenkan: + return Settings::NativeKeyboard::Muhenkan; + // case Qt::: + // return Settings::NativeKeyboard::NumPadCommaPc98; + case Qt::Key_Hangul: + return Settings::NativeKeyboard::HangulEnglish; + case Qt::Key_Hangul_Hanja: + return Settings::NativeKeyboard::Hanja; + case Qt::Key_Katakana: + return Settings::NativeKeyboard::KatakanaKey; + case Qt::Key_Hiragana: + return Settings::NativeKeyboard::HiraganaKey; + case Qt::Key_Zenkaku_Hankaku: + return Settings::NativeKeyboard::ZenkakuHankaku; + // Modifier keys are handled by the modifier property + default: + return 0; + } +} + +int GRenderWindow::QtModifierToSwitchModdifier(quint32 qt_moddifiers) { + int moddifier = 0; + // The values are obtained through testing, Qt doesn't seem to provide a proper enum + if ((qt_moddifiers & 0x1) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftShift; + } + if ((qt_moddifiers & 0x2) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftControl; + } + if ((qt_moddifiers & 0x4) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftAlt; + } + if ((qt_moddifiers & 0x08) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftMeta; + } + if ((qt_moddifiers & 0x10) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightShift; + } + if ((qt_moddifiers & 0x20) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightControl; + } + if ((qt_moddifiers & 0x40) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightAlt; + } + if ((qt_moddifiers & 0x80) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightMeta; + } + if ((qt_moddifiers & 0x100) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::CapsLock; + } + if ((qt_moddifiers & 0x200) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::NumLock; + } + // Verify the last two keys + if ((qt_moddifiers & 0x400) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::Katakana; + } + if ((qt_moddifiers & 0x800) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::Hiragana; + } + return moddifier; +} + void GRenderWindow::keyPressEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { - input_subsystem->GetKeyboard()->PressKey(event->key()); + const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); + // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key + // buttons + const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); + input_subsystem->GetKeyboard()->SetModifiers(moddifier); + input_subsystem->GetKeyboard()->PressKey(key); } } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { - input_subsystem->GetKeyboard()->ReleaseKey(event->key()); + const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); + const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); + input_subsystem->GetKeyboard()->SetModifiers(moddifier); + input_subsystem->GetKeyboard()->ReleaseKey(key); } } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 95594f81c..c42d139be 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -158,6 +158,12 @@ public: void resizeEvent(QResizeEvent* event) override; + /// Converts a Qt keybard key into NativeKeyboard key + static int QtKeyToSwitchKey(Qt::Key qt_keys); + + /// Converts a Qt modifier keys into NativeKeyboard modifier keys + static int QtModifierToSwitchModdifier(quint32 qt_moddifiers); + void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7669fe474..ccf274895 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -65,157 +65,6 @@ const std::array Config::defa Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, }; -const std::array Config::default_keyboard_keys = { - 0, - 0, - 0, - 0, - Qt::Key_A, - Qt::Key_B, - Qt::Key_C, - Qt::Key_D, - Qt::Key_E, - Qt::Key_F, - Qt::Key_G, - Qt::Key_H, - Qt::Key_I, - Qt::Key_J, - Qt::Key_K, - Qt::Key_L, - Qt::Key_M, - Qt::Key_N, - Qt::Key_O, - Qt::Key_P, - Qt::Key_Q, - Qt::Key_R, - Qt::Key_S, - Qt::Key_T, - Qt::Key_U, - Qt::Key_V, - Qt::Key_W, - Qt::Key_X, - Qt::Key_Y, - Qt::Key_Z, - Qt::Key_1, - Qt::Key_2, - Qt::Key_3, - Qt::Key_4, - Qt::Key_5, - Qt::Key_6, - Qt::Key_7, - Qt::Key_8, - Qt::Key_9, - Qt::Key_0, - Qt::Key_Enter, - Qt::Key_Escape, - Qt::Key_Backspace, - Qt::Key_Tab, - Qt::Key_Space, - Qt::Key_Minus, - Qt::Key_Equal, - Qt::Key_BracketLeft, - Qt::Key_BracketRight, - Qt::Key_Backslash, - Qt::Key_Dead_Tilde, - Qt::Key_Semicolon, - Qt::Key_Apostrophe, - Qt::Key_Dead_Grave, - Qt::Key_Comma, - Qt::Key_Period, - Qt::Key_Slash, - Qt::Key_CapsLock, - - Qt::Key_F1, - Qt::Key_F2, - Qt::Key_F3, - Qt::Key_F4, - Qt::Key_F5, - Qt::Key_F6, - Qt::Key_F7, - Qt::Key_F8, - Qt::Key_F9, - Qt::Key_F10, - Qt::Key_F11, - Qt::Key_F12, - - Qt::Key_SysReq, - Qt::Key_ScrollLock, - Qt::Key_Pause, - Qt::Key_Insert, - Qt::Key_Home, - Qt::Key_PageUp, - Qt::Key_Delete, - Qt::Key_End, - Qt::Key_PageDown, - Qt::Key_Right, - Qt::Key_Left, - Qt::Key_Down, - Qt::Key_Up, - - Qt::Key_NumLock, - Qt::Key_Slash, - Qt::Key_Asterisk, - Qt::Key_Minus, - Qt::Key_Plus, - Qt::Key_Enter, - Qt::Key_1, - Qt::Key_2, - Qt::Key_3, - Qt::Key_4, - Qt::Key_5, - Qt::Key_6, - Qt::Key_7, - Qt::Key_8, - Qt::Key_9, - Qt::Key_0, - Qt::Key_Period, - - 0, - 0, - Qt::Key_PowerOff, - Qt::Key_Equal, - - Qt::Key_F13, - Qt::Key_F14, - Qt::Key_F15, - Qt::Key_F16, - Qt::Key_F17, - Qt::Key_F18, - Qt::Key_F19, - Qt::Key_F20, - Qt::Key_F21, - Qt::Key_F22, - Qt::Key_F23, - Qt::Key_F24, - - Qt::Key_Open, - Qt::Key_Help, - Qt::Key_Menu, - 0, - Qt::Key_Stop, - Qt::Key_AudioRepeat, - Qt::Key_Undo, - Qt::Key_Cut, - Qt::Key_Copy, - Qt::Key_Paste, - Qt::Key_Find, - Qt::Key_VolumeMute, - Qt::Key_VolumeUp, - Qt::Key_VolumeDown, - Qt::Key_CapsLock, - Qt::Key_NumLock, - Qt::Key_ScrollLock, - Qt::Key_Comma, - - Qt::Key_ParenLeft, - Qt::Key_ParenRight, -}; - -const std::array Config::default_keyboard_mods = { - Qt::Key_Control, Qt::Key_Shift, Qt::Key_Alt, Qt::Key_ApplicationLeft, - Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, -}; - // This shouldn't have anything except static initializers (no functions). So // QKeySequence(...).toString() is NOT ALLOWED HERE. // This must be in alphabetical order according to action name as it must have the same order as @@ -496,14 +345,14 @@ void Config::ReadDebugValues() { void Config::ReadKeyboardValues() { ReadBasicSetting(Settings::values.keyboard_enabled); - std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), - Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_keys.begin() + - Settings::NativeKeyboard::LeftControlKey, - InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); + for (std::size_t i = 0; i < Settings::values.keyboard_keys.size(); ++i) { + Settings::values.keyboard_keys[i] = InputCommon::GenerateKeyboardParam(static_cast(i)); + } + + for (std::size_t i = 0; i < Settings::values.keyboard_mods.size(); ++i) { + Settings::values.keyboard_mods[i] = + InputCommon::GenerateModdifierKeyboardParam(static_cast(i)); + } } void Config::ReadMouseValues() { -- 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/common/settings.h | 2 -- src/core/hid/emulated_devices.cpp | 28 +++++++++++++++---- src/input_common/drivers/keyboard.cpp | 52 ++++++++++++++++++++++++++--------- src/input_common/drivers/keyboard.h | 14 +++++++++- src/input_common/input_mapping.cpp | 25 +++++++++++++++++ src/input_common/input_mapping.h | 7 +++++ src/input_common/main.cpp | 9 ------ src/input_common/main.h | 3 -- src/yuzu/bootmanager.cpp | 14 ++++++---- src/yuzu/configuration/config.cpp | 9 ------ 10 files changed, 115 insertions(+), 48 deletions(-) (limited to 'src/core') diff --git a/src/common/settings.h b/src/common/settings.h index b52d0d1d0..ee9e0b5a1 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -572,8 +572,6 @@ struct Values { BasicSetting emulate_analog_keyboard{false, "emulate_analog_keyboard"}; BasicSetting keyboard_enabled{false, "keyboard_enabled"}; - KeyboardKeysRaw keyboard_keys; - KeyboardModsRaw keyboard_mods; BasicSetting debug_pad_enabled{false, "debug_pad_enabled"}; ButtonsRaw debug_pad_buttons; 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]) { diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp index 328fe1ac1..23b0c0ccf 100644 --- a/src/input_common/drivers/keyboard.cpp +++ b/src/input_common/drivers/keyboard.cpp @@ -13,15 +13,26 @@ constexpr PadIdentifier key_identifier = { .port = 0, .pad = 0, }; -constexpr PadIdentifier modifier_identifier = { +constexpr PadIdentifier keyboard_key_identifier = { .guid = Common::UUID{Common::INVALID_UUID}, - .port = 0, + .port = 1, + .pad = 0, +}; +constexpr PadIdentifier keyboard_modifier_identifier = { + .guid = Common::UUID{Common::INVALID_UUID}, + .port = 1, .pad = 1, }; Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) { + // Keyboard is broken into 3 diferent sets: + // key: Unfiltered intended for controllers. + // keyboard_key: Allows only Settings::NativeKeyboard::Keys intended for keyboard emulation. + // keyboard_modifier: Allows only Settings::NativeKeyboard::Modifiers intended for keyboard + // emulation. PreSetController(key_identifier); - PreSetController(modifier_identifier); + PreSetController(keyboard_key_identifier); + PreSetController(keyboard_modifier_identifier); } void Keyboard::PressKey(int key_code) { @@ -32,35 +43,50 @@ void Keyboard::ReleaseKey(int key_code) { SetButton(key_identifier, key_code, false); } -void Keyboard::SetModifiers(int key_modifiers) { +void Keyboard::PressKeyboardKey(int key_index) { + if (key_index == Settings::NativeKeyboard::None) { + return; + } + SetButton(keyboard_key_identifier, key_index, true); +} + +void Keyboard::ReleaseKeyboardKey(int key_index) { + if (key_index == Settings::NativeKeyboard::None) { + return; + } + SetButton(keyboard_key_identifier, key_index, false); +} + +void Keyboard::SetKeyboardModifiers(int key_modifiers) { for (int i = 0; i < 32; ++i) { bool key_value = ((key_modifiers >> i) & 0x1) != 0; - SetButton(modifier_identifier, i, key_value); + SetButton(keyboard_modifier_identifier, i, key_value); // Use the modifier to press the key button equivalent switch (i) { case Settings::NativeKeyboard::LeftControl: - SetButton(key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value); break; case Settings::NativeKeyboard::LeftShift: - SetButton(key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value); break; case Settings::NativeKeyboard::LeftAlt: - SetButton(key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value); break; case Settings::NativeKeyboard::LeftMeta: - SetButton(key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value); break; case Settings::NativeKeyboard::RightControl: - SetButton(key_identifier, Settings::NativeKeyboard::RightControlKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightControlKey, + key_value); break; case Settings::NativeKeyboard::RightShift: - SetButton(key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value); break; case Settings::NativeKeyboard::RightAlt: - SetButton(key_identifier, Settings::NativeKeyboard::RightAltKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightAltKey, key_value); break; case Settings::NativeKeyboard::RightMeta: - SetButton(key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value); + SetButton(keyboard_key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value); break; default: // Other modifier keys should be pressed with PressKey since they stay enabled until diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h index 2ab92fd6c..ad123b136 100644 --- a/src/input_common/drivers/keyboard.h +++ b/src/input_common/drivers/keyboard.h @@ -28,11 +28,23 @@ public: */ void ReleaseKey(int key_code); + /** + * Sets the status of the keyboard key to pressed + * @param key_index index of the key to press + */ + void PressKeyboardKey(int key_index); + + /** + * Sets the status of the keyboard key to released + * @param key_index index of the key to release + */ + void ReleaseKeyboardKey(int key_index); + /** * Sets the status of all keyboard modifier keys * @param key_modifiers the code of the key to release */ - void SetModifiers(int key_modifiers); + void SetKeyboardModifiers(int key_modifiers); /// Sets all keys to the non pressed state void ReleaseAllKeys(); diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp index 0ffc71028..0eeeff372 100644 --- a/src/input_common/input_mapping.cpp +++ b/src/input_common/input_mapping.cpp @@ -28,6 +28,10 @@ void MappingFactory::RegisterInput(const MappingData& data) { if (!is_enabled) { return; } + if (!IsDriverValid(data)) { + return; + } + switch (input_type) { case Polling::InputType::Button: RegisterButton(data); @@ -168,4 +172,25 @@ void MappingFactory::RegisterMotion(const MappingData& data) { input_queue.Push(new_input); } +bool MappingFactory::IsDriverValid(const MappingData& data) const { + // Only port 0 can be mapped on the keyboard + if (data.engine == "keyboard" && data.pad.port != 0) { + return false; + } + // The following drivers don't need to be mapped + if (data.engine == "tas") { + return false; + } + if (data.engine == "touch") { + return false; + } + if (data.engine == "touch_from_button") { + return false; + } + if (data.engine == "analog_from_button") { + return false; + } + return true; +} + } // namespace InputCommon diff --git a/src/input_common/input_mapping.h b/src/input_common/input_mapping.h index 2622dba70..44eb8ad9a 100644 --- a/src/input_common/input_mapping.h +++ b/src/input_common/input_mapping.h @@ -66,6 +66,13 @@ private: */ void RegisterMotion(const MappingData& data); + /** + * Returns true if driver can be mapped + * @param "data": An struct containing all the information needed to create a proper + * ParamPackage + */ + bool IsDriverValid(const MappingData& data) const; + Common::SPSCQueue input_queue; Polling::InputType input_type{Polling::InputType::None}; bool is_enabled{}; diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index ae2518f53..df36a337c 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -402,15 +402,6 @@ std::string GenerateKeyboardParam(int key_code) { return param.Serialize(); } -std::string GenerateModdifierKeyboardParam(int key_code) { - Common::ParamPackage param; - param.Set("engine", "keyboard"); - param.Set("code", key_code); - param.Set("toggle", false); - param.Set("pad", 1); - return param.Serialize(); -} - std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, int key_modifier, float modifier_scale) { Common::ParamPackage circle_pad_param{ diff --git a/src/input_common/main.h b/src/input_common/main.h index 9ea395465..a4a24d076 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h @@ -134,9 +134,6 @@ private: /// Generates a serialized param package for creating a keyboard button device. std::string GenerateKeyboardParam(int key_code); -/// Generates a serialized param package for creating a moddifier keyboard button device. -std::string GenerateModdifierKeyboardParam(int key_code); - /// Generates a serialized param package for creating an analog device taking input from keyboard. std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, int key_modifier, float modifier_scale); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 61513a5b4..9f4d1aac3 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -609,7 +609,7 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { return Settings::NativeKeyboard::ZenkakuHankaku; // Modifier keys are handled by the modifier property default: - return 0; + return Settings::NativeKeyboard::None; } } @@ -662,8 +662,10 @@ void GRenderWindow::keyPressEvent(QKeyEvent* event) { // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key // buttons const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); - input_subsystem->GetKeyboard()->SetModifiers(moddifier); - input_subsystem->GetKeyboard()->PressKey(key); + input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier); + input_subsystem->GetKeyboard()->PressKeyboardKey(key); + // This is used for gamepads + input_subsystem->GetKeyboard()->PressKey(event->key()); } } @@ -671,8 +673,10 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); - input_subsystem->GetKeyboard()->SetModifiers(moddifier); - input_subsystem->GetKeyboard()->ReleaseKey(key); + input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier); + input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key); + // This is used for gamepads + input_subsystem->GetKeyboard()->ReleaseKey(event->key()); } } diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index ccf274895..5865359fe 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -344,15 +344,6 @@ void Config::ReadDebugValues() { void Config::ReadKeyboardValues() { ReadBasicSetting(Settings::values.keyboard_enabled); - - for (std::size_t i = 0; i < Settings::values.keyboard_keys.size(); ++i) { - Settings::values.keyboard_keys[i] = InputCommon::GenerateKeyboardParam(static_cast(i)); - } - - for (std::size_t i = 0; i < Settings::values.keyboard_mods.size(); ++i) { - Settings::values.keyboard_mods[i] = - InputCommon::GenerateModdifierKeyboardParam(static_cast(i)); - } } void Config::ReadMouseValues() { -- 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/common/settings.h | 1 - src/common/settings_input.h | 15 +- 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 +- src/input_common/drivers/mouse.cpp | 31 +- src/input_common/drivers/mouse.h | 7 + src/yuzu/CMakeLists.txt | 3 - src/yuzu/bootmanager.cpp | 6 + src/yuzu/bootmanager.h | 1 + src/yuzu/configuration/config.cpp | 30 -- src/yuzu/configuration/configure_input.cpp | 4 - .../configuration/configure_input_advanced.cpp | 2 - src/yuzu/configuration/configure_input_advanced.ui | 204 ++++++------- .../configuration/configure_mouse_advanced.cpp | 247 --------------- src/yuzu/configuration/configure_mouse_advanced.h | 72 ----- src/yuzu/configuration/configure_mouse_advanced.ui | 335 --------------------- src/yuzu_cmd/config.cpp | 174 ----------- 21 files changed, 323 insertions(+), 1039 deletions(-) delete mode 100644 src/yuzu/configuration/configure_mouse_advanced.cpp delete mode 100644 src/yuzu/configuration/configure_mouse_advanced.h delete mode 100644 src/yuzu/configuration/configure_mouse_advanced.ui (limited to 'src/core') diff --git a/src/common/settings.h b/src/common/settings.h index ee9e0b5a1..d7410fa9b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -568,7 +568,6 @@ struct Values { BasicSetting mouse_panning{false, "mouse_panning"}; BasicRangedSetting mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; BasicSetting mouse_enabled{false, "mouse_enabled"}; - MouseButtonsRaw mouse_buttons; BasicSetting emulate_analog_keyboard{false, "emulate_analog_keyboard"}; BasicSetting keyboard_enabled{false, "keyboard_enabled"}; diff --git a/src/common/settings_input.h b/src/common/settings_input.h index a2982fca4..9a8804488 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h @@ -126,6 +126,17 @@ constexpr int NUM_MOUSE_HID = NumMouseButtons; extern const std::array mapping; } // namespace NativeMouseButton +namespace NativeMouseWheel { +enum Values { + X, + Y, + + NumMouseWheels, +}; + +extern const std::array mapping; +} // namespace NativeMouseWheel + namespace NativeKeyboard { enum Keys { None, @@ -348,10 +359,6 @@ using ButtonsRaw = std::array; using MotionsRaw = std::array; using VibrationsRaw = std::array; -using MouseButtonsRaw = std::array; -using KeyboardKeysRaw = std::array; -using KeyboardModsRaw = std::array; - constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; 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; } diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index afa92b458..478737db2 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -12,6 +12,10 @@ #include "input_common/drivers/mouse.h" namespace InputCommon { +constexpr int mouse_axis_x = 0; +constexpr int mouse_axis_y = 1; +constexpr int wheel_axis_x = 2; +constexpr int wheel_axis_y = 3; constexpr int touch_axis_x = 10; constexpr int touch_axis_y = 11; constexpr PadIdentifier identifier = { @@ -22,6 +26,12 @@ constexpr PadIdentifier identifier = { Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) { PreSetController(identifier); + PreSetAxis(identifier, mouse_axis_x); + PreSetAxis(identifier, mouse_axis_y); + PreSetAxis(identifier, wheel_axis_x); + PreSetAxis(identifier, wheel_axis_y); + PreSetAxis(identifier, touch_axis_x); + PreSetAxis(identifier, touch_axis_x); update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); } @@ -34,14 +44,18 @@ void Mouse::UpdateThread(std::stop_token stop_token) { last_mouse_change *= 0.96f; const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.022f; - SetAxis(identifier, 0, last_mouse_change.x * sensitivity); - SetAxis(identifier, 1, -last_mouse_change.y * sensitivity); + SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity); + SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); } if (mouse_panning_timout++ > 20) { StopPanning(); } std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); + + // Reset wheel position + SetAxis(identifier, wheel_axis_x, 0); + SetAxis(identifier, wheel_axis_y, 0); } } @@ -89,8 +103,8 @@ void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int if (button_pressed) { const auto mouse_move = Common::MakeVec(x, y) - mouse_origin; const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f; - SetAxis(identifier, 0, static_cast(mouse_move.x) * sensitivity); - SetAxis(identifier, 1, static_cast(-mouse_move.y) * sensitivity); + SetAxis(identifier, mouse_axis_x, static_cast(mouse_move.x) * sensitivity); + SetAxis(identifier, mouse_axis_y, static_cast(-mouse_move.y) * sensitivity); } } @@ -108,12 +122,17 @@ void Mouse::ReleaseButton(MouseButton button) { SetButton(identifier, static_cast(button), false); if (!Settings::values.mouse_panning) { - SetAxis(identifier, 0, 0); - SetAxis(identifier, 1, 0); + SetAxis(identifier, mouse_axis_x, 0); + SetAxis(identifier, mouse_axis_y, 0); } button_pressed = false; } +void Mouse::MouseWheelChange(int x, int y) { + SetAxis(identifier, wheel_axis_x, static_cast(x)); + SetAxis(identifier, wheel_axis_y, static_cast(y)); +} + void Mouse::ReleaseAllButtons() { ResetButtonState(); button_pressed = false; diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 1be362b94..429502af9 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -52,6 +52,13 @@ public: */ void ReleaseButton(MouseButton button); + /** + * Sets the status of the mouse wheel + * @param x delta movement in the x direction + * @param y delta movement in the y direction + */ + void MouseWheelChange(int x, int y); + void ReleaseAllButtons(); std::vector GetInputDevices() const override; diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index d62fd566f..a44815e71 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -90,9 +90,6 @@ add_executable(yuzu configuration/configure_motion_touch.cpp configuration/configure_motion_touch.h configuration/configure_motion_touch.ui - configuration/configure_mouse_advanced.cpp - configuration/configure_mouse_advanced.h - configuration/configure_mouse_advanced.ui configuration/configure_per_game.cpp configuration/configure_per_game.h configuration/configure_per_game.ui diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 9f4d1aac3..1015e51b5 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -746,6 +746,12 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { input_subsystem->GetMouse()->ReleaseButton(button); } +void GRenderWindow::wheelEvent(QWheelEvent* event) { + const int x = event->delta(); + const int y = 0; + input_subsystem->GetMouse()->MouseWheelChange(x, y); +} + void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { QList touch_points = event->touchPoints(); for (const auto& touch_point : touch_points) { diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index c42d139be..d6b2ab5f3 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -173,6 +173,7 @@ public: void mousePressEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; + void wheelEvent(QWheelEvent* event) override; bool event(QEvent* event) override; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 5865359fe..ae1684dd4 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -60,11 +60,6 @@ const std::array Config::default_stick_mod = { 0, }; -const std::array Config::default_mouse_buttons = - { - Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, -}; - // This shouldn't have anything except static initializers (no functions). So // QKeySequence(...).toString() is NOT ALLOWED HERE. // This must be in alphabetical order according to action name as it must have the same order as @@ -348,22 +343,6 @@ void Config::ReadKeyboardValues() { void Config::ReadMouseValues() { ReadBasicSetting(Settings::values.mouse_enabled); - - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - const std::string default_param = - InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - auto& mouse_buttons = Settings::values.mouse_buttons[i]; - - mouse_buttons = qt_config - ->value(QStringLiteral("mouse_") + - QString::fromUtf8(Settings::NativeMouseButton::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (mouse_buttons.empty()) { - mouse_buttons = default_param; - } - } } void Config::ReadTouchscreenValues() { @@ -947,15 +926,6 @@ void Config::SaveDebugValues() { void Config::SaveMouseValues() { WriteBasicSetting(Settings::values.mouse_enabled); - - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - const std::string default_param = - InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - WriteSetting(QStringLiteral("mouse_") + - QString::fromStdString(Settings::NativeMouseButton::mapping[i]), - QString::fromStdString(Settings::values.mouse_buttons[i]), - QString::fromStdString(default_param)); - } } void Config::SaveTouchscreenValues() { diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 99450bc7d..d53179dbb 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -24,7 +24,6 @@ #include "yuzu/configuration/configure_input_advanced.h" #include "yuzu/configuration/configure_input_player.h" #include "yuzu/configuration/configure_motion_touch.h" -#include "yuzu/configuration/configure_mouse_advanced.h" #include "yuzu/configuration/configure_touchscreen_advanced.h" #include "yuzu/configuration/configure_vibration.h" #include "yuzu/configuration/input_profiles.h" @@ -157,9 +156,6 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, CallConfigureDialog( *this, input_subsystem, profiles.get(), hid_core, is_powered_on); }); - connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { - CallConfigureDialog(*this, input_subsystem); - }); connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog, [this] { CallConfigureDialog(*this); }); connect(advanced, &ConfigureInputAdvanced::CallMotionTouchConfigDialog, diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index b30f09013..cf8aad4ab 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -82,7 +82,6 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) connect(ui->debug_configure, &QPushButton::clicked, this, [this] { CallDebugControllerDialog(); }); - connect(ui->mouse_advanced, &QPushButton::clicked, this, [this] { CallMouseConfigDialog(); }); connect(ui->touchscreen_advanced, &QPushButton::clicked, this, [this] { CallTouchscreenConfigDialog(); }); connect(ui->buttonMotionTouch, &QPushButton::clicked, this, @@ -178,7 +177,6 @@ void ConfigureInputAdvanced::RetranslateUI() { } void ConfigureInputAdvanced::UpdateUIEnabled() { - ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked()); ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); } diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 9095206a0..75487a5d0 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2528,11 +2528,11 @@ 0 - + - Other + Emulated Devices - + @@ -2547,7 +2547,7 @@ - + 0 @@ -2555,53 +2555,18 @@ - Emulate Analog with Keyboard Input + Mouse - - - - 0 - 23 - - + - Enable mouse panning + Touchscreen - - - - Mouse sensitivity - - - Qt::AlignCenter - - - % - - - 1 - - - 100 - - - 100 - - - - - - - Advanced - - - - + Qt::Horizontal @@ -2617,80 +2582,117 @@ - - - - Advanced - - - - - - - Touchscreen - - - + + + + Advanced + + + - - - - 0 - 23 - - - - Mouse - - - - - - - Motion / Touch - - - - - - - Configure - - - - Debug Controller - + Configure - - - - Requires restarting yuzu - - - - 0 - 23 - - - - Enable XInput 8 player support (disables web applet) - - - + + + + Other + + + + + + + 0 + 23 + + + + Emulate Analog with Keyboard Input + + + + + + + Requires restarting yuzu + + + + 0 + 23 + + + + Enable XInput 8 player support (disables web applet) + + + + + + + + 0 + 23 + + + + Enable mouse panning + + + + + + + Mouse sensitivity + + + Qt::AlignCenter + + + % + + + 1 + + + 100 + + + 100 + + + + + + + Motion / Touch + + + + + + + Configure + + + + + + diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp deleted file mode 100644 index 1e7a3751d..000000000 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include - -#include -#include -#include - -#include "common/assert.h" -#include "common/param_package.h" -#include "input_common/drivers/keyboard.h" -#include "input_common/drivers/mouse.h" -#include "input_common/main.h" -#include "ui_configure_mouse_advanced.h" -#include "yuzu/bootmanager.h" -#include "yuzu/configuration/config.h" -#include "yuzu/configuration/configure_mouse_advanced.h" - -static QString GetKeyName(int key_code) { - switch (key_code) { - case Qt::LeftButton: - return QObject::tr("Click 0"); - case Qt::RightButton: - return QObject::tr("Click 1"); - case Qt::MiddleButton: - return QObject::tr("Click 2"); - case Qt::BackButton: - return QObject::tr("Click 3"); - case Qt::ForwardButton: - return QObject::tr("Click 4"); - case Qt::Key_Shift: - return QObject::tr("Shift"); - case Qt::Key_Control: - return QObject::tr("Ctrl"); - case Qt::Key_Alt: - return QObject::tr("Alt"); - case Qt::Key_Meta: - return {}; - default: - return QKeySequence(key_code).toString(); - } -} - -static QString ButtonToText(const Common::ParamPackage& param) { - if (!param.Has("engine")) { - return QObject::tr("[not set]"); - } - - if (param.Get("engine", "") == "keyboard") { - return GetKeyName(param.Get("code", 0)); - } - - if (param.Get("engine", "") == "sdl") { - if (param.Has("hat")) { - const QString hat_str = QString::fromStdString(param.Get("hat", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("Hat %1 %2").arg(hat_str, direction_str); - } - - if (param.Has("axis")) { - const QString axis_str = QString::fromStdString(param.Get("axis", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("Axis %1%2").arg(axis_str, direction_str); - } - - if (param.Has("button")) { - const QString button_str = QString::fromStdString(param.Get("button", "")); - - return QObject::tr("Button %1").arg(button_str); - } - return {}; - } - - return QObject::tr("[unknown]"); -} - -ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent, - InputCommon::InputSubsystem* input_subsystem_) - : QDialog(parent), - ui(std::make_unique()), input_subsystem{input_subsystem_}, - timeout_timer(std::make_unique()), poll_timer(std::make_unique()) { - ui->setupUi(this); - setFocusPolicy(Qt::ClickFocus); - - button_map = { - ui->left_button, ui->right_button, ui->middle_button, ui->forward_button, ui->back_button, - }; - - for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { - auto* const button = button_map[button_id]; - if (button == nullptr) { - continue; - } - - button->setContextMenuPolicy(Qt::CustomContextMenu); - connect(button, &QPushButton::clicked, [=, this] { - HandleClick( - button_map[button_id], - [=, this](const Common::ParamPackage& params) { - buttons_param[button_id] = params; - }, - InputCommon::Polling::InputType::Button); - }); - connect(button, &QPushButton::customContextMenuRequested, - [=, this](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - buttons_param[button_id].Clear(); - button_map[button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Restore Default"), [&] { - buttons_param[button_id] = - Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_mouse_buttons[button_id])}; - button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); - }); - context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); - }); - } - - connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); }); - - timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - - connect(poll_timer.get(), &QTimer::timeout, [this] { - const auto& params = input_subsystem->GetNextInput(); - if (params.Has("engine")) { - SetPollingResult(params, false); - return; - } - }); - - LoadConfiguration(); - resize(0, 0); -} - -ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default; - -void ConfigureMouseAdvanced::ApplyConfiguration() { - std::transform(buttons_param.begin(), buttons_param.end(), - Settings::values.mouse_buttons.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); -} - -void ConfigureMouseAdvanced::LoadConfiguration() { - std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), - buttons_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - UpdateButtonLabels(); -} - -void ConfigureMouseAdvanced::changeEvent(QEvent* event) { - if (event->type() == QEvent::LanguageChange) { - RetranslateUI(); - } - - QDialog::changeEvent(event); -} - -void ConfigureMouseAdvanced::RetranslateUI() { - ui->retranslateUi(this); -} - -void ConfigureMouseAdvanced::RestoreDefaults() { - for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { - buttons_param[button_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])}; - } - - UpdateButtonLabels(); -} - -void ConfigureMouseAdvanced::ClearAll() { - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - const auto* const button = button_map[i]; - if (button != nullptr && button->isEnabled()) { - buttons_param[i].Clear(); - } - } - - UpdateButtonLabels(); -} - -void ConfigureMouseAdvanced::UpdateButtonLabels() { - for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) { - button_map[button]->setText(ButtonToText(buttons_param[button])); - } -} - -void ConfigureMouseAdvanced::HandleClick( - QPushButton* button, std::function new_input_setter, - InputCommon::Polling::InputType type) { - button->setText(tr("[press key]")); - button->setFocus(); - - input_setter = new_input_setter; - - input_subsystem->BeginMapping(type); - - QWidget::grabMouse(); - QWidget::grabKeyboard(); - - timeout_timer->start(2500); // Cancel after 2.5 seconds - poll_timer->start(50); // Check for new inputs every 50ms -} - -void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { - timeout_timer->stop(); - poll_timer->stop(); - input_subsystem->StopMapping(); - - QWidget::releaseMouse(); - QWidget::releaseKeyboard(); - - if (!abort) { - (*input_setter)(params); - } - - UpdateButtonLabels(); - input_setter = std::nullopt; -} - -void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) { - if (!input_setter || !event) { - return; - } - - const auto button = GRenderWindow::QtButtonToMouseButton(event->button()); - input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button); -} - -void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) { - return; - } - - if (event->key() != Qt::Key_Escape) { - input_subsystem->GetKeyboard()->PressKey(event->key()); - } -} diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h deleted file mode 100644 index 5fa534eaf..000000000 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -class QCheckBox; -class QPushButton; -class QTimer; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Ui { -class ConfigureMouseAdvanced; -} - -class ConfigureMouseAdvanced : public QDialog { - Q_OBJECT - -public: - explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_); - ~ConfigureMouseAdvanced() override; - - void ApplyConfiguration(); - -private: - void changeEvent(QEvent* event) override; - void RetranslateUI(); - - /// Load configuration settings. - void LoadConfiguration(); - /// Restore all buttons to their default values. - void RestoreDefaults(); - /// Clear all input configuration - void ClearAll(); - - /// Update UI to reflect current configuration. - void UpdateButtonLabels(); - - /// Called when the button was pressed. - void HandleClick(QPushButton* button, - std::function new_input_setter, - InputCommon::Polling::InputType type); - - /// Finish polling and configure input using the input_setter - void SetPollingResult(const Common::ParamPackage& params, bool abort); - - /// Handle mouse button press events. - void mousePressEvent(QMouseEvent* event) override; - - /// Handle key press events. - void keyPressEvent(QKeyEvent* event) override; - - std::unique_ptr ui; - - InputCommon::InputSubsystem* input_subsystem; - - /// This will be the the setting function when an input is awaiting configuration. - std::optional> input_setter; - - std::array button_map; - std::array buttons_param; - - std::unique_ptr timeout_timer; - std::unique_ptr poll_timer; -}; diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui deleted file mode 100644 index 5b99e1c37..000000000 --- a/src/yuzu/configuration/configure_mouse_advanced.ui +++ /dev/null @@ -1,335 +0,0 @@ - - - ConfigureMouseAdvanced - - - - 0 - 0 - 310 - 193 - - - - Configure Mouse - - - QPushButton { - min-width: 60px; -} - - - - - - Mouse Buttons - - - - - - - - - - Forward: - - - - - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - - - - - - - - - - - - - - - 54 - 0 - - - - Back: - - - - - - - - - - 68 - 0 - - - - - - - - - - - - - - - - - Left: - - - - - - - - - - 68 - 0 - - - - - - - - - - - - - - - - - Middle: - - - - - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 0 - 20 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 0 - 20 - - - - - - - - - - - - Right: - - - - - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - - - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - Clear - - - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - Defaults - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - ConfigureMouseAdvanced - accept() - - - buttonBox - rejected() - ConfigureMouseAdvanced - reject() - - - diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 7ca09a635..8e9c7d211 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -83,163 +83,6 @@ static const std::array, Settings::NativeAnalog::NumAnalogs> }, }}; -static const std::array default_mouse_buttons = { - SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_APOSTROPHE, - SDL_SCANCODE_MINUS, SDL_SCANCODE_EQUALS, -}; - -static const std::array keyboard_keys = { - 0, - 0, - 0, - 0, - SDL_SCANCODE_A, - SDL_SCANCODE_B, - SDL_SCANCODE_C, - SDL_SCANCODE_D, - SDL_SCANCODE_E, - SDL_SCANCODE_F, - SDL_SCANCODE_G, - SDL_SCANCODE_H, - SDL_SCANCODE_I, - SDL_SCANCODE_J, - SDL_SCANCODE_K, - SDL_SCANCODE_L, - SDL_SCANCODE_M, - SDL_SCANCODE_N, - SDL_SCANCODE_O, - SDL_SCANCODE_P, - SDL_SCANCODE_Q, - SDL_SCANCODE_R, - SDL_SCANCODE_S, - SDL_SCANCODE_T, - SDL_SCANCODE_U, - SDL_SCANCODE_V, - SDL_SCANCODE_W, - SDL_SCANCODE_X, - SDL_SCANCODE_Y, - SDL_SCANCODE_Z, - SDL_SCANCODE_1, - SDL_SCANCODE_2, - SDL_SCANCODE_3, - SDL_SCANCODE_4, - SDL_SCANCODE_5, - SDL_SCANCODE_6, - SDL_SCANCODE_7, - SDL_SCANCODE_8, - SDL_SCANCODE_9, - SDL_SCANCODE_0, - SDL_SCANCODE_RETURN, - SDL_SCANCODE_ESCAPE, - SDL_SCANCODE_BACKSPACE, - SDL_SCANCODE_TAB, - SDL_SCANCODE_SPACE, - SDL_SCANCODE_MINUS, - SDL_SCANCODE_EQUALS, - SDL_SCANCODE_LEFTBRACKET, - SDL_SCANCODE_RIGHTBRACKET, - SDL_SCANCODE_BACKSLASH, - 0, - SDL_SCANCODE_SEMICOLON, - SDL_SCANCODE_APOSTROPHE, - SDL_SCANCODE_GRAVE, - SDL_SCANCODE_COMMA, - SDL_SCANCODE_PERIOD, - SDL_SCANCODE_SLASH, - SDL_SCANCODE_CAPSLOCK, - - SDL_SCANCODE_F1, - SDL_SCANCODE_F2, - SDL_SCANCODE_F3, - SDL_SCANCODE_F4, - SDL_SCANCODE_F5, - SDL_SCANCODE_F6, - SDL_SCANCODE_F7, - SDL_SCANCODE_F8, - SDL_SCANCODE_F9, - SDL_SCANCODE_F10, - SDL_SCANCODE_F11, - SDL_SCANCODE_F12, - - 0, - SDL_SCANCODE_SCROLLLOCK, - SDL_SCANCODE_PAUSE, - SDL_SCANCODE_INSERT, - SDL_SCANCODE_HOME, - SDL_SCANCODE_PAGEUP, - SDL_SCANCODE_DELETE, - SDL_SCANCODE_END, - SDL_SCANCODE_PAGEDOWN, - SDL_SCANCODE_RIGHT, - SDL_SCANCODE_LEFT, - SDL_SCANCODE_DOWN, - SDL_SCANCODE_UP, - - SDL_SCANCODE_NUMLOCKCLEAR, - SDL_SCANCODE_KP_DIVIDE, - SDL_SCANCODE_KP_MULTIPLY, - SDL_SCANCODE_KP_MINUS, - SDL_SCANCODE_KP_PLUS, - SDL_SCANCODE_KP_ENTER, - SDL_SCANCODE_KP_1, - SDL_SCANCODE_KP_2, - SDL_SCANCODE_KP_3, - SDL_SCANCODE_KP_4, - SDL_SCANCODE_KP_5, - SDL_SCANCODE_KP_6, - SDL_SCANCODE_KP_7, - SDL_SCANCODE_KP_8, - SDL_SCANCODE_KP_9, - SDL_SCANCODE_KP_0, - SDL_SCANCODE_KP_PERIOD, - - 0, - 0, - SDL_SCANCODE_POWER, - SDL_SCANCODE_KP_EQUALS, - - SDL_SCANCODE_F13, - SDL_SCANCODE_F14, - SDL_SCANCODE_F15, - SDL_SCANCODE_F16, - SDL_SCANCODE_F17, - SDL_SCANCODE_F18, - SDL_SCANCODE_F19, - SDL_SCANCODE_F20, - SDL_SCANCODE_F21, - SDL_SCANCODE_F22, - SDL_SCANCODE_F23, - SDL_SCANCODE_F24, - - 0, - SDL_SCANCODE_HELP, - SDL_SCANCODE_MENU, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - SDL_SCANCODE_KP_COMMA, - SDL_SCANCODE_KP_LEFTPAREN, - SDL_SCANCODE_KP_RIGHTPAREN, - 0, - 0, - 0, - 0, -}; - -static const std::array keyboard_mods{ - SDL_SCANCODE_LCTRL, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_LALT, SDL_SCANCODE_LGUI, - SDL_SCANCODE_RCTRL, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_RALT, SDL_SCANCODE_RGUI, -}; - template <> void Config::ReadSetting(const std::string& group, Settings::BasicSetting& setting) { setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); @@ -283,14 +126,6 @@ void Config::ReadValues() { } ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - Settings::values.mouse_buttons[i] = sdl2_config->Get( - "ControlsGeneral", std::string("mouse_") + Settings::NativeMouseButton::mapping[i], - default_param); - if (Settings::values.mouse_buttons[i].empty()) - Settings::values.mouse_buttons[i] = default_param; - } ReadSetting("ControlsGeneral", Settings::values.touch_device); @@ -365,15 +200,6 @@ void Config::ReadValues() { ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); - std::transform(keyboard_keys.begin(), keyboard_keys.end(), - Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); - std::transform(keyboard_mods.begin(), keyboard_mods.end(), - Settings::values.keyboard_keys.begin() + - Settings::NativeKeyboard::LeftControlKey, - InputCommon::GenerateKeyboardParam); - std::transform(keyboard_mods.begin(), keyboard_mods.end(), - Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); - // Data Storage ReadSetting("Data Storage", Settings::values.use_virtual_sd); FS::SetYuzuPath(FS::YuzuPath::NANDDir, -- 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 +-- src/input_common/drivers/mouse.cpp | 21 ++++++++----- src/input_common/drivers/mouse.h | 1 + src/yuzu/bootmanager.cpp | 4 +-- .../configuration/configure_input_advanced.cpp | 2 ++ 14 files changed, 79 insertions(+), 48 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)> diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 478737db2..05fd7f9c0 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -39,7 +39,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) { Common::SetCurrentThreadName("yuzu:input:Mouse"); constexpr int update_time = 10; while (!stop_token.stop_requested()) { - if (Settings::values.mouse_panning) { + if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { // Slow movement by 4% last_mouse_change *= 0.96f; const float sensitivity = @@ -52,14 +52,17 @@ void Mouse::UpdateThread(std::stop_token stop_token) { StopPanning(); } std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); - - // Reset wheel position - SetAxis(identifier, wheel_axis_x, 0); - SetAxis(identifier, wheel_axis_y, 0); } } void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) { + // If native mouse is enabled just set the screen coordinates + if (Settings::values.mouse_enabled) { + SetAxis(identifier, mouse_axis_x, touch_x); + SetAxis(identifier, mouse_axis_y, touch_y); + return; + } + SetAxis(identifier, touch_axis_x, touch_x); SetAxis(identifier, touch_axis_y, touch_y); @@ -121,7 +124,7 @@ void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton butt void Mouse::ReleaseButton(MouseButton button) { SetButton(identifier, static_cast(button), false); - if (!Settings::values.mouse_panning) { + if (!Settings::values.mouse_panning && !Settings::values.mouse_enabled) { SetAxis(identifier, mouse_axis_x, 0); SetAxis(identifier, mouse_axis_y, 0); } @@ -129,8 +132,10 @@ void Mouse::ReleaseButton(MouseButton button) { } void Mouse::MouseWheelChange(int x, int y) { - SetAxis(identifier, wheel_axis_x, static_cast(x)); - SetAxis(identifier, wheel_axis_y, static_cast(y)); + wheel_position.x += x; + wheel_position.y += y; + SetAxis(identifier, wheel_axis_x, static_cast(wheel_position.x)); + SetAxis(identifier, wheel_axis_y, static_cast(wheel_position.y)); } void Mouse::ReleaseAllButtons() { diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 429502af9..f7e6db0b5 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -72,6 +72,7 @@ private: Common::Vec2 mouse_origin; Common::Vec2 last_mouse_position; Common::Vec2 last_mouse_change; + Common::Vec2 wheel_position; bool button_pressed; int mouse_panning_timout{}; std::jthread update_thread; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 1015e51b5..2313a4189 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -729,7 +729,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { const int center_y = height() / 2; input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y); - if (Settings::values.mouse_panning) { + if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { QCursor::setPos(mapToGlobal({center_x, center_y})); } @@ -1044,7 +1044,7 @@ void GRenderWindow::showEvent(QShowEvent* event) { bool GRenderWindow::eventFilter(QObject* object, QEvent* event) { if (event->type() == QEvent::HoverMove) { - if (Settings::values.mouse_panning) { + if (Settings::values.mouse_panning || Settings::values.mouse_enabled) { auto* hover_event = static_cast(event); mouseMoveEvent(hover_event); return false; diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index cf8aad4ab..e6127f9e6 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -179,4 +179,6 @@ void ConfigureInputAdvanced::RetranslateUI() { void ConfigureInputAdvanced::UpdateUIEnabled() { ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); + ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked()); + ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked()); } -- 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 ++- src/input_common/drivers/gc_adapter.cpp | 16 +------ src/input_common/drivers/gc_adapter.h | 2 +- src/input_common/drivers/mouse.cpp | 2 +- src/input_common/drivers/mouse.h | 2 +- src/input_common/drivers/sdl_driver.cpp | 2 +- src/input_common/drivers/sdl_driver.h | 2 +- src/input_common/drivers/tas_input.cpp | 2 +- src/input_common/drivers/tas_input.h | 2 +- src/input_common/drivers/touch_screen.cpp | 2 +- src/input_common/drivers/touch_screen.h | 2 +- src/input_common/input_engine.cpp | 4 +- src/input_common/input_engine.h | 2 +- src/yuzu/bootmanager.cpp | 66 +++++++++++++-------------- src/yuzu/bootmanager.h | 2 +- 17 files changed, 54 insertions(+), 66 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) { diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 2550f8cba..a1b9b6d98 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -69,7 +69,7 @@ private: libusb_device_handle* handle{}; }; -GCAdapter::GCAdapter(const std::string input_engine_) : InputEngine(input_engine_) { +GCAdapter::GCAdapter(const std::string& input_engine_) : InputEngine(input_engine_) { if (usb_adapter_handle) { return; } @@ -486,42 +486,30 @@ std::string GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const switch (button) { case PadButton::ButtonLeft: return "left"; - break; case PadButton::ButtonRight: return "right"; - break; case PadButton::ButtonDown: return "down"; - break; case PadButton::ButtonUp: return "up"; - break; case PadButton::TriggerZ: return "Z"; - break; case PadButton::TriggerR: return "R"; - break; case PadButton::TriggerL: return "L"; - break; case PadButton::ButtonA: return "A"; - break; case PadButton::ButtonB: return "B"; - break; case PadButton::ButtonX: return "X"; - break; case PadButton::ButtonY: return "Y"; - break; case PadButton::ButtonStart: return "start"; - break; default: - return "Unkown GC"; + return "Unknown GC"; } } diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index fba90352e..3e4747040 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -24,7 +24,7 @@ class LibUSBDeviceHandle; class GCAdapter : public InputCommon::InputEngine { public: - explicit GCAdapter(const std::string input_engine_); + explicit GCAdapter(const std::string& input_engine_); ~GCAdapter(); Common::Input::VibrationError SetRumble( diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 05fd7f9c0..9a9a1987d 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -24,7 +24,7 @@ constexpr PadIdentifier identifier = { .pad = 0, }; -Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) { +Mouse::Mouse(const std::string& input_engine_) : InputEngine(input_engine_) { PreSetController(identifier); PreSetAxis(identifier, mouse_axis_x); PreSetAxis(identifier, mouse_axis_y); diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index f7e6db0b5..11dd76e14 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -29,7 +29,7 @@ enum class MouseButton { */ class Mouse final : public InputCommon::InputEngine { public: - explicit Mouse(const std::string input_engine_); + explicit Mouse(const std::string& input_engine_); /** * Signals that mouse has moved. diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 1e3741e0f..0b24f1858 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -929,7 +929,7 @@ std::string SDLDriver::GetHatButtonName(u8 direction_value) const { } } -u8 SDLDriver::GetHatButtonId(const std::string direction_name) const { +u8 SDLDriver::GetHatButtonId(const std::string& direction_name) const { Uint8 direction; if (direction_name == "up") { direction = SDL_HAT_UP; diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index b879df8ab..3faaca984 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -56,7 +56,7 @@ public: std::string GetUIName(const Common::ParamPackage& params) const override; std::string GetHatButtonName(u8 direction_value) const override; - u8 GetHatButtonId(const std::string direction_name) const override; + u8 GetHatButtonId(const std::string& direction_name) const override; Common::Input::VibrationError SetRumble( const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override; diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index bb9c236ea..0e01fb0d9 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -47,7 +47,7 @@ constexpr std::array, 20> text_to_tas_but {"KEY_ZR", TasButton::TRIGGER_ZR}, }; -Tas::Tas(const std::string input_engine_) : InputCommon::InputEngine(input_engine_) { +Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engine_) { for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) { PadIdentifier identifier{ .guid = Common::UUID{}, diff --git a/src/input_common/drivers/tas_input.h b/src/input_common/drivers/tas_input.h index bfb37a638..c95a130fc 100644 --- a/src/input_common/drivers/tas_input.h +++ b/src/input_common/drivers/tas_input.h @@ -83,7 +83,7 @@ enum class TasState { class Tas final : public InputCommon::InputEngine { public: - explicit Tas(const std::string input_engine_); + explicit Tas(const std::string& input_engine_); ~Tas(); /** diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp index 377c9ee2b..45b3086f6 100644 --- a/src/input_common/drivers/touch_screen.cpp +++ b/src/input_common/drivers/touch_screen.cpp @@ -13,7 +13,7 @@ constexpr PadIdentifier identifier = { .pad = 0, }; -TouchScreen::TouchScreen(const std::string input_engine_) : InputEngine(input_engine_) { +TouchScreen::TouchScreen(const std::string& input_engine_) : InputEngine(input_engine_) { PreSetController(identifier); } diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h index 0f4cd0e7a..25c11e8bf 100644 --- a/src/input_common/drivers/touch_screen.h +++ b/src/input_common/drivers/touch_screen.h @@ -14,7 +14,7 @@ namespace InputCommon { */ class TouchScreen final : public InputCommon::InputEngine { public: - explicit TouchScreen(const std::string input_engine_); + explicit TouchScreen(const std::string& input_engine_); /** * Signals that mouse has moved. diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 139d8d2e6..2b2105376 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp @@ -300,8 +300,8 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot if (!configuring || !mapping_callback.on_data) { return; } - if (std::abs(value.gyro_x) < 1.0f && std::abs(value.gyro_y) < 1.0f && - std::abs(value.gyro_z) < 1.0f) { + if (std::abs(value.gyro_x) < 0.6f && std::abs(value.gyro_y) < 0.6f && + std::abs(value.gyro_z) < 0.6f) { return; } mapping_callback.on_data(MappingData{ diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index 5430c0cf8..c621686e5 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -166,7 +166,7 @@ public: }; /// Retrieves the index number of the given hat button direction - virtual u8 GetHatButtonId([[maybe_unused]] const std::string direction_name) const { + virtual u8 GetHatButtonId([[maybe_unused]] const std::string& direction_name) const { return 0; }; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 2313a4189..7390fc5bd 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -613,56 +613,56 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { } } -int GRenderWindow::QtModifierToSwitchModdifier(quint32 qt_moddifiers) { - int moddifier = 0; +int GRenderWindow::QtModifierToSwitchModifier(quint32 qt_modifiers) { + int modifier = 0; // The values are obtained through testing, Qt doesn't seem to provide a proper enum - if ((qt_moddifiers & 0x1) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::LeftShift; + if ((qt_modifiers & 0x1) != 0) { + modifier |= 1 << Settings::NativeKeyboard::LeftShift; } - if ((qt_moddifiers & 0x2) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::LeftControl; + if ((qt_modifiers & 0x2) != 0) { + modifier |= 1 << Settings::NativeKeyboard::LeftControl; } - if ((qt_moddifiers & 0x4) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::LeftAlt; + if ((qt_modifiers & 0x4) != 0) { + modifier |= 1 << Settings::NativeKeyboard::LeftAlt; } - if ((qt_moddifiers & 0x08) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::LeftMeta; + if ((qt_modifiers & 0x08) != 0) { + modifier |= 1 << Settings::NativeKeyboard::LeftMeta; } - if ((qt_moddifiers & 0x10) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::RightShift; + if ((qt_modifiers & 0x10) != 0) { + modifier |= 1 << Settings::NativeKeyboard::RightShift; } - if ((qt_moddifiers & 0x20) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::RightControl; + if ((qt_modifiers & 0x20) != 0) { + modifier |= 1 << Settings::NativeKeyboard::RightControl; } - if ((qt_moddifiers & 0x40) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::RightAlt; + if ((qt_modifiers & 0x40) != 0) { + modifier |= 1 << Settings::NativeKeyboard::RightAlt; } - if ((qt_moddifiers & 0x80) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::RightMeta; + if ((qt_modifiers & 0x80) != 0) { + modifier |= 1 << Settings::NativeKeyboard::RightMeta; } - if ((qt_moddifiers & 0x100) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::CapsLock; + if ((qt_modifiers & 0x100) != 0) { + modifier |= 1 << Settings::NativeKeyboard::CapsLock; } - if ((qt_moddifiers & 0x200) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::NumLock; + if ((qt_modifiers & 0x200) != 0) { + modifier |= 1 << Settings::NativeKeyboard::NumLock; } // Verify the last two keys - if ((qt_moddifiers & 0x400) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::Katakana; + if ((qt_modifiers & 0x400) != 0) { + modifier |= 1 << Settings::NativeKeyboard::Katakana; } - if ((qt_moddifiers & 0x800) != 0) { - moddifier |= 1 << Settings::NativeKeyboard::Hiragana; + if ((qt_modifiers & 0x800) != 0) { + modifier |= 1 << Settings::NativeKeyboard::Hiragana; } - return moddifier; + return modifier; } void GRenderWindow::keyPressEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { - const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); + const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers()); // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key // buttons const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); - input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier); + input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier); input_subsystem->GetKeyboard()->PressKeyboardKey(key); // This is used for gamepads input_subsystem->GetKeyboard()->PressKey(event->key()); @@ -671,9 +671,9 @@ void GRenderWindow::keyPressEvent(QKeyEvent* event) { void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { - const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); + const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers()); const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); - input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier); + input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier); input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key); // This is used for gamepads input_subsystem->GetKeyboard()->ReleaseKey(event->key()); @@ -747,8 +747,8 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { } void GRenderWindow::wheelEvent(QWheelEvent* event) { - const int x = event->delta(); - const int y = 0; + const int x = event->angleDelta().x(); + const int y = event->angleDelta().y(); input_subsystem->GetMouse()->MouseWheelChange(x, y); } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index d6b2ab5f3..81e3c4eb0 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -162,7 +162,7 @@ public: static int QtKeyToSwitchKey(Qt::Key qt_keys); /// Converts a Qt modifier keys into NativeKeyboard modifier keys - static int QtModifierToSwitchModdifier(quint32 qt_moddifiers); + static int QtModifierToSwitchModifier(quint32 qt_modifiers); void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; -- 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 +- src/yuzu/bootmanager.cpp | 93 +++++++++++++++++++++++++++++------------------- src/yuzu/bootmanager.h | 2 +- 3 files changed, 58 insertions(+), 39 deletions(-) (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; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 7390fc5bd..5e19f8cb1 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -613,69 +613,88 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { } } -int GRenderWindow::QtModifierToSwitchModifier(quint32 qt_modifiers) { +int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) { int modifier = 0; - // The values are obtained through testing, Qt doesn't seem to provide a proper enum - if ((qt_modifiers & 0x1) != 0) { + + if ((qt_modifiers & Qt::KeyboardModifier::ShiftModifier) != 0) { modifier |= 1 << Settings::NativeKeyboard::LeftShift; } - if ((qt_modifiers & 0x2) != 0) { + if ((qt_modifiers & Qt::KeyboardModifier::ControlModifier) != 0) { modifier |= 1 << Settings::NativeKeyboard::LeftControl; } - if ((qt_modifiers & 0x4) != 0) { + if ((qt_modifiers & Qt::KeyboardModifier::AltModifier) != 0) { modifier |= 1 << Settings::NativeKeyboard::LeftAlt; } - if ((qt_modifiers & 0x08) != 0) { + if ((qt_modifiers & Qt::KeyboardModifier::MetaModifier) != 0) { modifier |= 1 << Settings::NativeKeyboard::LeftMeta; } - if ((qt_modifiers & 0x10) != 0) { - modifier |= 1 << Settings::NativeKeyboard::RightShift; - } - if ((qt_modifiers & 0x20) != 0) { - modifier |= 1 << Settings::NativeKeyboard::RightControl; - } - if ((qt_modifiers & 0x40) != 0) { - modifier |= 1 << Settings::NativeKeyboard::RightAlt; - } - if ((qt_modifiers & 0x80) != 0) { - modifier |= 1 << Settings::NativeKeyboard::RightMeta; - } - if ((qt_modifiers & 0x100) != 0) { - modifier |= 1 << Settings::NativeKeyboard::CapsLock; - } - if ((qt_modifiers & 0x200) != 0) { - modifier |= 1 << Settings::NativeKeyboard::NumLock; - } - // Verify the last two keys - if ((qt_modifiers & 0x400) != 0) { - modifier |= 1 << Settings::NativeKeyboard::Katakana; - } - if ((qt_modifiers & 0x800) != 0) { - modifier |= 1 << Settings::NativeKeyboard::Hiragana; - } + + // TODO: These keys can't be obtained with Qt::KeyboardModifier + + // if ((qt_modifiers & 0x10) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::RightShift; + // } + // if ((qt_modifiers & 0x20) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::RightControl; + // } + // if ((qt_modifiers & 0x40) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::RightAlt; + // } + // if ((qt_modifiers & 0x80) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::RightMeta; + // } + // if ((qt_modifiers & 0x100) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::CapsLock; + // } + // if ((qt_modifiers & 0x200) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::NumLock; + // } + // if ((qt_modifiers & ???) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::ScrollLock; + // } + // if ((qt_modifiers & ???) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::Katakana; + // } + // if ((qt_modifiers & ???) != 0) { + // modifier |= 1 << Settings::NativeKeyboard::Hiragana; + // } return modifier; } void GRenderWindow::keyPressEvent(QKeyEvent* event) { + /** + * This feature can be enhanced with the following functions, but they do not provide + * cross-platform behavior. + * + * event->nativeVirtualKey() can distinguish between keys on the numpad. + * event->nativeModifiers() can distinguish between left and right keys and numlock, + * capslock, scroll lock. + */ if (!event->isAutoRepeat()) { - const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers()); - // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key - // buttons + const auto modifier = QtModifierToSwitchModifier(event->modifiers()); const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier); input_subsystem->GetKeyboard()->PressKeyboardKey(key); - // This is used for gamepads + // This is used for gamepads that can have any key mapped input_subsystem->GetKeyboard()->PressKey(event->key()); } } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { + /** + * This feature can be enhanced with the following functions, but they do not provide + * cross-platform behavior. + * + * event->nativeVirtualKey() can distinguish between keys on the numpad. + * event->nativeModifiers() can distinguish between left and right buttons and numlock, + * capslock, scroll lock. + */ if (!event->isAutoRepeat()) { - const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers()); + const auto modifier = QtModifierToSwitchModifier(event->modifiers()); const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier); input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key); - // This is used for gamepads + // This is used for gamepads that can have any key mapped input_subsystem->GetKeyboard()->ReleaseKey(event->key()); } } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 81e3c4eb0..c8a2c59b4 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -162,7 +162,7 @@ public: static int QtKeyToSwitchKey(Qt::Key qt_keys); /// Converts a Qt modifier keys into NativeKeyboard modifier keys - static int QtModifierToSwitchModifier(quint32 qt_modifiers); + static int QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers); void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; -- 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/common/input.h | 14 ++ src/common/settings.h | 1 + src/core/hid/emulated_console.cpp | 6 +- src/input_common/drivers/udp_client.cpp | 206 ++++++++++++++++++++- src/input_common/drivers/udp_client.h | 56 ++++++ src/input_common/helpers/udp_protocol.h | 75 +++++--- src/input_common/input_mapping.cpp | 6 + src/input_common/main.cpp | 26 ++- src/yuzu/configuration/config.cpp | 2 + .../configuration/configure_input_advanced.cpp | 2 + src/yuzu/configuration/configure_input_advanced.ui | 19 +- src/yuzu/configuration/configure_input_player.cpp | 24 +++ 12 files changed, 397 insertions(+), 40 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index cc0cbd9b8..eaee0bdea 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -195,6 +195,20 @@ enum class ButtonNames { ButtonX, ButtonY, ButtonStart, + + // DS4 button names + L1, + L2, + L3, + R1, + R2, + R3, + Circle, + Cross, + Square, + Triangle, + Share, + Options, }; // Callback data consisting of an input type and the equivalent data status diff --git a/src/common/settings.h b/src/common/settings.h index d7410fa9b..e4e049f67 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -560,6 +560,7 @@ struct Values { Setting motion_enabled{true, "motion_enabled"}; BasicSetting udp_input_servers{"127.0.0.1:26760", "udp_input_servers"}; + BasicSetting enable_udp_controller{false, "enable_udp_controller"}; BasicSetting pause_tas_on_load{true, "pause_tas_on_load"}; BasicSetting tas_enable{false, "tas_enable"}; 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()); diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 7cab707da..fdee0f2d5 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -103,7 +103,7 @@ private: // Send a request for getting pad data for the pad const Request::PadData pad_data{ - Request::PadData::Flags::AllPorts, + Request::RegisterFlags::AllPads, 0, EMPTY_MAC_ADDRESS, }; @@ -247,7 +247,12 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) { for (std::size_t id = 0; id < data.touch.size(); ++id) { const auto touch_pad = data.touch[id]; - const int touch_id = static_cast(client * 2 + id); + const auto touch_axis_x_id = + static_cast(id == 0 ? PadAxes::Touch1X : PadAxes::Touch2X); + const auto touch_axis_y_id = + static_cast(id == 0 ? PadAxes::Touch1Y : PadAxes::Touch2Y); + const auto touch_button_id = + static_cast(id == 0 ? PadButton::Touch1 : PadButton::touch2); // TODO: Use custom calibration per device const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); @@ -264,14 +269,35 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) { static_cast(max_y - min_y); if (touch_pad.is_active) { - SetAxis(identifier, touch_id * 2, x); - SetAxis(identifier, touch_id * 2 + 1, y); - SetButton(identifier, touch_id, true); + SetAxis(identifier, touch_axis_x_id, x); + SetAxis(identifier, touch_axis_y_id, y); + SetButton(identifier, touch_button_id, true); continue; } - SetAxis(identifier, touch_id * 2, 0); - SetAxis(identifier, touch_id * 2 + 1, 0); - SetButton(identifier, touch_id, false); + SetAxis(identifier, touch_axis_x_id, 0); + SetAxis(identifier, touch_axis_y_id, 0); + SetButton(identifier, touch_button_id, false); + } + + SetAxis(identifier, static_cast(PadAxes::LeftStickX), + (data.left_stick_x - 127.0f) / 127.0f); + SetAxis(identifier, static_cast(PadAxes::LeftStickY), + (data.left_stick_y - 127.0f) / 127.0f); + SetAxis(identifier, static_cast(PadAxes::RightStickX), + (data.right_stick_x - 127.0f) / 127.0f); + SetAxis(identifier, static_cast(PadAxes::RightStickY), + (data.right_stick_y - 127.0f) / 127.0f); + + static constexpr std::array buttons{ + PadButton::Share, PadButton::L3, PadButton::R3, PadButton::Options, + PadButton::Up, PadButton::Right, PadButton::Down, PadButton::Left, + PadButton::L2, PadButton::R2, PadButton::L1, PadButton::R1, + PadButton::Triangle, PadButton::Circle, PadButton::Cross, PadButton::Square}; + + for (std::size_t i = 0; i < buttons.size(); ++i) { + const bool button_status = (data.digital_button & (1U << i)) != 0; + const int button = static_cast(buttons[i]); + SetButton(identifier, button, button_status); } } @@ -317,6 +343,170 @@ void UDPClient::Reset() { } } +std::vector UDPClient::GetInputDevices() const { + std::vector devices; + if (!Settings::values.enable_udp_controller) { + return devices; + } + for (std::size_t client = 0; client < clients.size(); client++) { + if (clients[client].active != 1) { + continue; + } + for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) { + const std::size_t pad_index = client * PADS_PER_CLIENT + index; + if (!pads[pad_index].connected) { + continue; + } + const auto pad_identifier = GetPadIdentifier(pad_index); + Common::ParamPackage identifier{}; + identifier.Set("engine", GetEngineName()); + identifier.Set("display", fmt::format("UDP Controller {}", pad_identifier.pad)); + identifier.Set("guid", pad_identifier.guid.Format()); + identifier.Set("port", static_cast(pad_identifier.port)); + identifier.Set("pad", static_cast(pad_identifier.pad)); + devices.emplace_back(identifier); + } + } + return devices; +} + +ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) { + // This list excludes any button that can't be really mapped + static constexpr std::array, 18> + switch_to_dsu_button = { + std::pair{Settings::NativeButton::A, PadButton::Circle}, + {Settings::NativeButton::B, PadButton::Cross}, + {Settings::NativeButton::X, PadButton::Triangle}, + {Settings::NativeButton::Y, PadButton::Square}, + {Settings::NativeButton::Plus, PadButton::Options}, + {Settings::NativeButton::Minus, PadButton::Share}, + {Settings::NativeButton::DLeft, PadButton::Left}, + {Settings::NativeButton::DUp, PadButton::Up}, + {Settings::NativeButton::DRight, PadButton::Right}, + {Settings::NativeButton::DDown, PadButton::Down}, + {Settings::NativeButton::L, PadButton::L1}, + {Settings::NativeButton::R, PadButton::R1}, + {Settings::NativeButton::ZL, PadButton::L2}, + {Settings::NativeButton::ZR, PadButton::R2}, + {Settings::NativeButton::SL, PadButton::L2}, + {Settings::NativeButton::SR, PadButton::R2}, + {Settings::NativeButton::LStick, PadButton::L3}, + {Settings::NativeButton::RStick, PadButton::R3}, + }; + if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) { + return {}; + } + + ButtonMapping mapping{}; + for (const auto& [switch_button, dsu_button] : switch_to_dsu_button) { + Common::ParamPackage button_params{}; + button_params.Set("engine", GetEngineName()); + button_params.Set("guid", params.Get("guid", "")); + button_params.Set("port", params.Get("port", 0)); + button_params.Set("pad", params.Get("pad", 0)); + button_params.Set("button", static_cast(dsu_button)); + mapping.insert_or_assign(switch_button, std::move(button_params)); + } + + return mapping; +} + +AnalogMapping UDPClient::GetAnalogMappingForDevice(const Common::ParamPackage& params) { + if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) { + return {}; + } + + AnalogMapping mapping = {}; + Common::ParamPackage left_analog_params; + left_analog_params.Set("engine", GetEngineName()); + left_analog_params.Set("guid", params.Get("guid", "")); + left_analog_params.Set("port", params.Get("port", 0)); + left_analog_params.Set("pad", params.Get("pad", 0)); + left_analog_params.Set("axis_x", static_cast(PadAxes::LeftStickX)); + left_analog_params.Set("axis_y", static_cast(PadAxes::LeftStickY)); + mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params)); + Common::ParamPackage right_analog_params; + right_analog_params.Set("engine", GetEngineName()); + right_analog_params.Set("guid", params.Get("guid", "")); + right_analog_params.Set("port", params.Get("port", 0)); + right_analog_params.Set("pad", params.Get("pad", 0)); + right_analog_params.Set("axis_x", static_cast(PadAxes::RightStickX)); + right_analog_params.Set("axis_y", static_cast(PadAxes::RightStickY)); + mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params)); + return mapping; +} + +MotionMapping UDPClient::GetMotionMappingForDevice(const Common::ParamPackage& params) { + if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) { + return {}; + } + + MotionMapping mapping = {}; + Common::ParamPackage motion_params; + motion_params.Set("engine", GetEngineName()); + motion_params.Set("guid", params.Get("guid", "")); + motion_params.Set("port", params.Get("port", 0)); + motion_params.Set("pad", params.Get("pad", 0)); + motion_params.Set("motion", 0); + mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, std::move(motion_params)); + mapping.insert_or_assign(Settings::NativeMotion::MotionRight, std::move(motion_params)); + return mapping; +} + +Common::Input::ButtonNames UDPClient::GetUIButtonName(const Common::ParamPackage& params) const { + PadButton button = static_cast(params.Get("button", 0)); + switch (button) { + case PadButton::Left: + return Common::Input::ButtonNames::ButtonLeft; + case PadButton::Right: + return Common::Input::ButtonNames::ButtonRight; + case PadButton::Down: + return Common::Input::ButtonNames::ButtonDown; + case PadButton::Up: + return Common::Input::ButtonNames::ButtonUp; + case PadButton::L1: + return Common::Input::ButtonNames::L1; + case PadButton::L2: + return Common::Input::ButtonNames::L2; + case PadButton::L3: + return Common::Input::ButtonNames::L3; + case PadButton::R1: + return Common::Input::ButtonNames::R1; + case PadButton::R2: + return Common::Input::ButtonNames::R2; + case PadButton::R3: + return Common::Input::ButtonNames::R3; + case PadButton::Circle: + return Common::Input::ButtonNames::Circle; + case PadButton::Cross: + return Common::Input::ButtonNames::Cross; + case PadButton::Square: + return Common::Input::ButtonNames::Square; + case PadButton::Triangle: + return Common::Input::ButtonNames::Triangle; + case PadButton::Share: + return Common::Input::ButtonNames::Share; + case PadButton::Options: + return Common::Input::ButtonNames::Options; + default: + return Common::Input::ButtonNames::Undefined; + } +} + +Common::Input::ButtonNames UDPClient::GetUIName(const Common::ParamPackage& params) const { + if (params.Has("button")) { + return GetUIButtonName(params); + } + if (params.Has("axis")) { + return Common::Input::ButtonNames::Value; + } + if (params.Has("motion")) { + return Common::Input::ButtonNames::Engine; + } + + return Common::Input::ButtonNames::Invalid; +} + void TestCommunication(const std::string& host, u16 port, const std::function& success_callback, const std::function& failure_callback) { diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h index 1f02adba5..5d483f26b 100644 --- a/src/input_common/drivers/udp_client.h +++ b/src/input_common/drivers/udp_client.h @@ -56,7 +56,61 @@ public: void ReloadSockets(); + /// Used for automapping features + std::vector GetInputDevices() const override; + ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; + AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; + MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; + Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; + private: + enum class PadButton { + Undefined = 0x0000, + Share = 0x0001, + L3 = 0x0002, + R3 = 0x0004, + Options = 0x0008, + Up = 0x0010, + Right = 0x0020, + Down = 0x0040, + Left = 0x0080, + L2 = 0x0100, + R2 = 0x0200, + L1 = 0x0400, + R1 = 0x0800, + Triangle = 0x1000, + Circle = 0x2000, + Cross = 0x4000, + Square = 0x8000, + Touch1 = 0x10000, + touch2 = 0x20000, + }; + + enum class PadAxes : u8 { + LeftStickX, + LeftStickY, + RightStickX, + RightStickY, + AnalogLeft, + AnalogDown, + AnalogRight, + AnalogUp, + AnalogSquare, + AnalogCross, + AnalogCircle, + AnalogTriangle, + AnalogR1, + AnalogL1, + AnalogR2, + AnalogL3, + AnalogR3, + Touch1X, + Touch1Y, + Touch2X, + Touch2Y, + Undefined, + }; + struct PadData { std::size_t pad_index{}; bool connected{}; @@ -90,6 +144,8 @@ private: const PadIdentifier GetPadIdentifier(std::size_t pad_index) const; const Common::UUID GetHostUUID(const std::string host) const; + Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; + // Allocate clients for 8 udp servers static constexpr std::size_t MAX_UDP_CLIENTS = 8; static constexpr std::size_t PADS_PER_CLIENT = 4; diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h index 1bdc9209e..bcba12c58 100644 --- a/src/input_common/helpers/udp_protocol.h +++ b/src/input_common/helpers/udp_protocol.h @@ -56,6 +56,12 @@ constexpr Type GetMessageType(); namespace Request { +enum RegisterFlags : u8 { + AllPads, + PadID, + PadMACAdddress, +}; + struct Version {}; /** * Requests the server to send information about what controllers are plugged into the ports @@ -77,13 +83,8 @@ static_assert(std::is_trivially_copyable_v, * timeout seems to be 5 seconds. */ struct PadData { - enum class Flags : u8 { - AllPorts, - Id, - Mac, - }; /// Determines which method will be used as a look up for the controller - Flags flags{}; + RegisterFlags flags{}; /// Index of the port of the controller to retrieve data about u8 port_id{}; /// Mac address of the controller to retrieve data about @@ -113,6 +114,36 @@ Message Create(const T data, const u32 client_id = 0) { namespace Response { +enum class ConnectionType : u8 { + None, + Usb, + Bluetooth, +}; + +enum class State : u8 { + Disconnected, + Reserved, + Connected, +}; + +enum class Model : u8 { + None, + PartialGyro, + FullGyro, + Generic, +}; + +enum class Battery : u8 { + None = 0x00, + Dying = 0x01, + Low = 0x02, + Medium = 0x03, + High = 0x04, + Full = 0x05, + Charging = 0xEE, + Charged = 0xEF, +}; + struct Version { u16_le version{}; }; @@ -122,11 +153,11 @@ static_assert(std::is_trivially_copyable_v, struct PortInfo { u8 id{}; - u8 state{}; - u8 model{}; - u8 connection_type{}; + State state{}; + Model model{}; + ConnectionType connection_type{}; MacAddress mac; - u8 battery{}; + Battery battery{}; u8 is_pad_active{}; }; static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size"); @@ -177,18 +208,18 @@ struct PadData { u8 right_stick_y{}; struct AnalogButton { - u8 button_8{}; - u8 button_7{}; - u8 button_6{}; - u8 button_5{}; - u8 button_12{}; - u8 button_11{}; - u8 button_10{}; - u8 button_9{}; - u8 button_16{}; - u8 button_15{}; - u8 button_14{}; - u8 button_13{}; + u8 button_dpad_left_analog{}; + u8 button_dpad_down_analog{}; + u8 button_dpad_right_analog{}; + u8 button_dpad_up_analog{}; + u8 button_square_analog{}; + u8 button_cross_analog{}; + u8 button_circle_analog{}; + u8 button_triangle_analog{}; + u8 button_r1_analog{}; + u8 button_l1_analog{}; + u8 trigger_r2{}; + u8 trigger_l2{}; } analog_button; std::array touch; diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp index c5218f2cb..6e0024b2d 100644 --- a/src/input_common/input_mapping.cpp +++ b/src/input_common/input_mapping.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included #include "common/common_types.h" +#include "common/settings.h" #include "input_common/input_engine.h" #include "input_common/input_mapping.h" @@ -182,6 +183,11 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const { if (data.engine == "keyboard" && data.pad.port != 0) { return false; } + // To prevent mapping with two devices we disable any UDP except motion + if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" && + data.type != EngineInputType::Motion) { + return false; + } // The following drivers don't need to be mapped if (data.engine == "tas") { return false; diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 39e4935dc..940744c5f 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -63,9 +63,12 @@ struct InputSubsystem::Impl { udp_client = std::make_shared("cemuhookudp"); udp_client->SetMappingCallback(mapping_callback); - udp_client_factory = std::make_shared(udp_client); + udp_client_input_factory = std::make_shared(udp_client); + udp_client_output_factory = std::make_shared(udp_client); Common::Input::RegisterFactory(udp_client->GetEngineName(), - udp_client_factory); + udp_client_input_factory); + Common::Input::RegisterFactory(udp_client->GetEngineName(), + udp_client_output_factory); tas_input = std::make_shared("tas"); tas_input->SetMappingCallback(mapping_callback); @@ -110,6 +113,7 @@ struct InputSubsystem::Impl { gcadapter.reset(); Common::Input::UnregisterFactory(udp_client->GetEngineName()); + Common::Input::UnregisterFactory(udp_client->GetEngineName()); udp_client.reset(); Common::Input::UnregisterFactory(tas_input->GetEngineName()); @@ -137,6 +141,8 @@ struct InputSubsystem::Impl { devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end()); auto gcadapter_devices = gcadapter->GetInputDevices(); devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end()); + auto udp_devices = udp_client->GetInputDevices(); + devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); #ifdef HAVE_SDL2 auto sdl_devices = sdl->GetInputDevices(); devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end()); @@ -157,6 +163,9 @@ struct InputSubsystem::Impl { if (engine == gcadapter->GetEngineName()) { return gcadapter->GetAnalogMappingForDevice(params); } + if (engine == udp_client->GetEngineName()) { + return udp_client->GetAnalogMappingForDevice(params); + } if (engine == tas_input->GetEngineName()) { return tas_input->GetAnalogMappingForDevice(params); } @@ -177,6 +186,9 @@ struct InputSubsystem::Impl { if (engine == gcadapter->GetEngineName()) { return gcadapter->GetButtonMappingForDevice(params); } + if (engine == udp_client->GetEngineName()) { + return udp_client->GetButtonMappingForDevice(params); + } if (engine == tas_input->GetEngineName()) { return tas_input->GetButtonMappingForDevice(params); } @@ -194,8 +206,8 @@ struct InputSubsystem::Impl { return {}; } const std::string engine = params.Get("engine", ""); - if (engine == gcadapter->GetEngineName()) { - return gcadapter->GetMotionMappingForDevice(params); + if (engine == udp_client->GetEngineName()) { + return udp_client->GetMotionMappingForDevice(params); } #ifdef HAVE_SDL2 if (engine == sdl->GetEngineName()) { @@ -238,6 +250,9 @@ struct InputSubsystem::Impl { if (engine == gcadapter->GetEngineName()) { return true; } + if (engine == udp_client->GetEngineName()) { + return true; + } if (engine == tas_input->GetEngineName()) { return true; } @@ -286,12 +301,13 @@ struct InputSubsystem::Impl { std::shared_ptr mouse_factory; std::shared_ptr gcadapter_input_factory; std::shared_ptr touch_screen_factory; - std::shared_ptr udp_client_factory; + std::shared_ptr udp_client_input_factory; std::shared_ptr tas_input_factory; std::shared_ptr keyboard_output_factory; std::shared_ptr mouse_output_factory; std::shared_ptr gcadapter_output_factory; + std::shared_ptr udp_client_output_factory; std::shared_ptr tas_output_factory; #ifdef HAVE_SDL2 diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index ae1684dd4..38fd6e93b 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -447,6 +447,7 @@ void Config::ReadMotionTouchValues() { Settings::values.touch_from_button_map_index = std::clamp( Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); ReadBasicSetting(Settings::values.udp_input_servers); + ReadBasicSetting(Settings::values.enable_udp_controller); } void Config::ReadCoreValues() { @@ -942,6 +943,7 @@ void Config::SaveMotionTouchValues() { WriteBasicSetting(Settings::values.touch_device); WriteBasicSetting(Settings::values.touch_from_button_map_index); WriteBasicSetting(Settings::values.udp_input_servers); + WriteBasicSetting(Settings::values.enable_udp_controller); qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index e6127f9e6..65c8e59ac 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -130,6 +130,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() { static_cast(ui->mouse_panning_sensitivity->value()); Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); Settings::values.enable_raw_input = ui->enable_raw_input->isChecked(); + Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked(); } void ConfigureInputAdvanced::LoadConfiguration() { @@ -160,6 +161,7 @@ void ConfigureInputAdvanced::LoadConfiguration() { ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue()); ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue()); + ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue()); UpdateUIEnabled(); } diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 75487a5d0..df0e4d602 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2642,6 +2642,19 @@ + + + + 0 + 23 + + + + Enable UDP controllers (not needed for motion) + + + + @@ -2654,7 +2667,7 @@ - + Mouse sensitivity @@ -2676,14 +2689,14 @@ - + Motion / Touch - + Configure diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 6219a09a8..ec071d6ec 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -78,6 +78,30 @@ QString GetButtonName(Common::Input::ButtonNames button_name) { return QObject::tr("Y"); case Common::Input::ButtonNames::ButtonStart: return QObject::tr("Start"); + case Common::Input::ButtonNames::L1: + return QObject::tr("L1"); + case Common::Input::ButtonNames::L2: + return QObject::tr("L2"); + case Common::Input::ButtonNames::L3: + return QObject::tr("L3"); + case Common::Input::ButtonNames::R1: + return QObject::tr("R1"); + case Common::Input::ButtonNames::R2: + return QObject::tr("R2"); + case Common::Input::ButtonNames::R3: + return QObject::tr("R3"); + case Common::Input::ButtonNames::Circle: + return QObject::tr("Circle"); + case Common::Input::ButtonNames::Cross: + return QObject::tr("Cross"); + case Common::Input::ButtonNames::Square: + return QObject::tr("Square"); + case Common::Input::ButtonNames::Triangle: + return QObject::tr("Triangle"); + case Common::Input::ButtonNames::Share: + return QObject::tr("Share"); + case Common::Input::ButtonNames::Options: + return QObject::tr("Options"); default: return QObject::tr("[undefined]"); } -- 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/common/settings_input.h | 2 - src/core/hid/emulated_controller.cpp | 5 +- src/yuzu/applets/qt_controller.cpp | 4 -- src/yuzu/configuration/config.cpp | 17 ------ src/yuzu/configuration/configure_vibration.cpp | 74 -------------------------- src/yuzu/configuration/configure_vibration.h | 3 -- src/yuzu/main.cpp | 2 - 7 files changed, 3 insertions(+), 104 deletions(-) (limited to 'src/core') diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 9a8804488..9e3df7376 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h @@ -357,7 +357,6 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; using AnalogsRaw = std::array; using ButtonsRaw = std::array; using MotionsRaw = std::array; -using VibrationsRaw = std::array; constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; @@ -378,7 +377,6 @@ struct PlayerInput { ControllerType controller_type; ButtonsRaw buttons; AnalogsRaw analogs; - VibrationsRaw vibrations; MotionsRaw motions; bool vibration_enabled; 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]; diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index eaa0f39f2..589e0577a 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -517,16 +517,12 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) if (controller->GetNpadStyleIndex(true) == controller_type && controller->IsConnected(true) == player_connected) { - // Set vibration devices in the event that the input device has changed. - ConfigureVibration::SetVibrationDevices(player_index); return; } // Disconnect the controller first. UpdateController(controller, controller_type, false); - ConfigureVibration::SetVibrationDevices(player_index); - // Handheld if (player_index == 0) { if (controller_type == Core::HID::NpadStyleIndex::Handheld) { diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 38fd6e93b..2c70d0548 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -273,18 +273,6 @@ void Config::ReadPlayerValue(std::size_t player_index) { } } - for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { - auto& player_vibrations = player.vibrations[i]; - - player_vibrations = - qt_config - ->value(QStringLiteral("%1").arg(player_prefix) + - QString::fromUtf8(Settings::NativeVibration::mapping[i]), - QString{}) - .toString() - .toStdString(); - } - for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); auto& player_motions = player.motions[i]; @@ -891,11 +879,6 @@ void Config::SavePlayerValue(std::size_t player_index) { QString::fromStdString(player.analogs[i]), QString::fromStdString(default_param)); } - for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { - WriteSetting(QStringLiteral("%1").arg(player_prefix) + - QString::fromStdString(Settings::NativeVibration::mapping[i]), - QString::fromStdString(player.vibrations[i]), QString{}); - } for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); WriteSetting(QStringLiteral("%1").arg(player_prefix) + diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index f1ce7205d..adce04b27 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -59,80 +59,6 @@ void ConfigureVibration::ApplyConfiguration() { ui->checkBoxAccurateVibration->isChecked()); } -void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { - using namespace Settings::NativeButton; - static constexpr std::array, 2> buttons{{ - {DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons - {A, B, X, Y, R, ZR}, // Right Buttons - }}; - - auto& player = Settings::values.players.GetValue()[player_index]; - - for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) { - std::unordered_map params_count; - - for (const auto button_index : buttons[device_idx]) { - const auto& player_button = player.buttons[button_index]; - - if (params_count.find(player_button) != params_count.end()) { - ++params_count[player_button]; - continue; - } - - params_count.insert_or_assign(player_button, 1); - } - - const auto it = std::max_element( - params_count.begin(), params_count.end(), - [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); - - auto& vibration_param_str = player.vibrations[device_idx]; - vibration_param_str.clear(); - - if (it->first.empty()) { - continue; - } - - const auto param = Common::ParamPackage(it->first); - - const auto engine = param.Get("engine", ""); - const auto guid = param.Get("guid", ""); - const auto port = param.Get("port", 0); - - if (engine.empty() || engine == "keyboard" || engine == "mouse" || engine == "tas") { - continue; - } - - vibration_param_str += fmt::format("engine:{}", engine); - - if (port != 0) { - vibration_param_str += fmt::format(",port:{}", port); - } - if (!guid.empty()) { - vibration_param_str += fmt::format(",guid:{}", guid); - } - } - - if (player.vibrations[0] != player.vibrations[1]) { - return; - } - - if (!player.vibrations[0].empty() && - player.controller_type != Settings::ControllerType::RightJoycon) { - player.vibrations[1].clear(); - } else if (!player.vibrations[1].empty() && - player.controller_type == Settings::ControllerType::RightJoycon) { - player.vibrations[0].clear(); - } -} - -void ConfigureVibration::SetAllVibrationDevices() { - // Set vibration devices for all player indices including handheld - for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) { - SetVibrationDevices(player_idx); - } -} - void ConfigureVibration::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { RetranslateUI(); diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h index 07411a86f..37bbc2653 100644 --- a/src/yuzu/configuration/configure_vibration.h +++ b/src/yuzu/configuration/configure_vibration.h @@ -24,9 +24,6 @@ public: void ApplyConfiguration(); - static void SetVibrationDevices(std::size_t player_index); - static void SetAllVibrationDevices(); - private: void changeEvent(QEvent* event) override; void RetranslateUI(); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 09ea21f5e..552db6387 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1380,8 +1380,6 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t Config per_game_config(*system, config_file_name, Config::ConfigType::PerGameConfig); } - ConfigureVibration::SetAllVibrationDevices(); - // Disable fps limit toggle when booting a new title Settings::values.disable_fps_limit.SetValue(false); -- 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/common/settings.h | 1 + src/common/settings_input.h | 5 ++++ src/core/hid/emulated_controller.cpp | 20 +++++++++++++ src/core/hle/service/hid/controllers/npad.cpp | 4 +++ src/yuzu/configuration/config.cpp | 2 ++ src/yuzu/configuration/configure_debug.cpp | 2 ++ src/yuzu/configuration/configure_debug.ui | 7 +++++ src/yuzu/configuration/configure_input_player.cpp | 34 +++++++++++++++++++++++ 8 files changed, 75 insertions(+) (limited to 'src/core') diff --git a/src/common/settings.h b/src/common/settings.h index e4e049f67..313f1fa7f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -604,6 +604,7 @@ struct Values { BasicSetting extended_logging{false, "extended_logging"}; BasicSetting use_debug_asserts{false, "use_debug_asserts"}; BasicSetting use_auto_stub{false, "use_auto_stub"}; + BasicSetting enable_all_controllers{false, "enable_all_controllers"}; // Miscellaneous BasicSetting log_filter{"*:Info", "log_filter"}; diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 9e3df7376..4ff37e186 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h @@ -370,6 +370,11 @@ enum class ControllerType { RightJoycon, Handheld, GameCube, + Pokeball, + NES, + SNES, + N64, + SegaGenesis, }; struct PlayerInput { 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); } diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 2c70d0548..463d500c2 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -508,6 +508,7 @@ void Config::ReadDebuggingValues() { ReadBasicSetting(Settings::values.extended_logging); ReadBasicSetting(Settings::values.use_debug_asserts); ReadBasicSetting(Settings::values.use_auto_stub); + ReadBasicSetting(Settings::values.enable_all_controllers); qt_config->endGroup(); } @@ -1051,6 +1052,7 @@ void Config::SaveDebuggingValues() { WriteBasicSetting(Settings::values.quest_flag); WriteBasicSetting(Settings::values.use_debug_asserts); WriteBasicSetting(Settings::values.disable_macro_jit); + WriteBasicSetting(Settings::values.enable_all_controllers); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 07bfa0360..633fc295b 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -42,6 +42,7 @@ void ConfigureDebug::SetConfiguration() { ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue()); ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue()); ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue()); + ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue()); ui->enable_graphics_debugging->setEnabled(runtime_lock); ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); ui->enable_shader_feedback->setEnabled(runtime_lock); @@ -67,6 +68,7 @@ void ConfigureDebug::ApplyConfiguration() { Settings::values.quest_flag = ui->quest_flag->isChecked(); Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); + Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked(); Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked(); Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index b884a56b0..0f3b51c8d 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -198,6 +198,13 @@ + + + + Enable all Controller Types + + + diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index ec071d6ec..16284d5a6 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -947,6 +947,40 @@ void ConfigureInputPlayer::SetConnectableControllers() { Core::HID::NpadStyleIndex::GameCube); ui->comboControllerType->addItem(tr("GameCube Controller")); } + + // Disable all unsupported controllers + if (!Settings::values.enable_all_controllers) { + return; + } + if (enable_all || npad_style_set.palma == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::Pokeball); + ui->comboControllerType->addItem(tr("Poke Ball Plus")); + } + + if (enable_all || npad_style_set.lark == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::NES); + ui->comboControllerType->addItem(tr("NES Controller")); + } + + if (enable_all || npad_style_set.lucia == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::SNES); + ui->comboControllerType->addItem(tr("SNES Controller")); + } + + if (enable_all || npad_style_set.lagoon == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::N64); + ui->comboControllerType->addItem(tr("N64 Controller")); + } + + if (enable_all || npad_style_set.lager == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::SegaGenesis); + ui->comboControllerType->addItem(tr("Sega Genesis")); + } }; if (!is_powered_on) { -- 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 +- src/yuzu/configuration/configure_input_player.cpp | 32 +++++++++++------------ 2 files changed, 17 insertions(+), 17 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 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); } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 16284d5a6..34099bc83 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -246,15 +246,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); emulated_controller_p1->SaveCurrentConfig(); emulated_controller_p1->EnableConfiguration(); - emulated_controller_hanheld->SaveCurrentConfig(); - emulated_controller_hanheld->EnableConfiguration(); - if (emulated_controller_hanheld->IsConnected(true)) { + emulated_controller_handheld->SaveCurrentConfig(); + emulated_controller_handheld->EnableConfiguration(); + if (emulated_controller_handheld->IsConnected(true)) { emulated_controller_p1->Disconnect(); - emulated_controller = emulated_controller_hanheld; + emulated_controller = emulated_controller_handheld; } else { emulated_controller = emulated_controller_p1; } @@ -590,19 +590,19 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); bool is_connected = emulated_controller->IsConnected(true); emulated_controller_p1->SetNpadStyleIndex(type); - emulated_controller_hanheld->SetNpadStyleIndex(type); + emulated_controller_handheld->SetNpadStyleIndex(type); if (is_connected) { if (type == Core::HID::NpadStyleIndex::Handheld) { emulated_controller_p1->Disconnect(); - emulated_controller_hanheld->Connect(); - emulated_controller = emulated_controller_hanheld; + emulated_controller_handheld->Connect(); + emulated_controller = emulated_controller_handheld; } else { - emulated_controller_hanheld->Disconnect(); + emulated_controller_handheld->Disconnect(); emulated_controller_p1->Connect(); emulated_controller = emulated_controller_p1; } @@ -650,10 +650,10 @@ ConfigureInputPlayer::~ConfigureInputPlayer() { if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); emulated_controller_p1->DisableConfiguration(); - emulated_controller_hanheld->DisableConfiguration(); + emulated_controller_handheld->DisableConfiguration(); } else { emulated_controller->DisableConfiguration(); } @@ -663,14 +663,14 @@ void ConfigureInputPlayer::ApplyConfiguration() { if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); emulated_controller_p1->DisableConfiguration(); emulated_controller_p1->SaveCurrentConfig(); emulated_controller_p1->EnableConfiguration(); - emulated_controller_hanheld->DisableConfiguration(); - emulated_controller_hanheld->SaveCurrentConfig(); - emulated_controller_hanheld->EnableConfiguration(); + emulated_controller_handheld->DisableConfiguration(); + emulated_controller_handheld->SaveCurrentConfig(); + emulated_controller_handheld->EnableConfiguration(); return; } emulated_controller->DisableConfiguration(); -- 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 --- .../hle/service/nvdrv/devices/nvhost_nvdec.cpp | 11 ++++-- .../service/nvdrv/devices/nvhost_nvdec_common.cpp | 5 ++- .../service/nvdrv/devices/nvhost_nvdec_common.h | 3 +- src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 11 ++++-- src/video_core/gpu.cpp | 43 +++++++--------------- src/video_core/gpu.h | 4 +- 6 files changed, 36 insertions(+), 41 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 diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index ab7c21a49..27a47954d 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -185,16 +185,6 @@ struct GPU::Impl { return *dma_pusher; } - /// Returns a reference to the GPU CDMA pusher. - [[nodiscard]] Tegra::CDmaPusher& CDmaPusher() { - return *cdma_pusher; - } - - /// Returns a const reference to the GPU CDMA pusher. - [[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const { - return *cdma_pusher; - } - /// Returns a reference to the underlying renderer. [[nodiscard]] VideoCore::RendererBase& Renderer() { return *renderer; @@ -338,25 +328,26 @@ struct GPU::Impl { } /// Push GPU command buffer entries to be processed - void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { + void PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries) { if (!use_nvdec) { return; } - if (!cdma_pusher) { - cdma_pusher = std::make_unique(gpu); + if (cdma_pushers.find(id) == cdma_pushers.end()) { + cdma_pushers[id] = std::make_unique(gpu); } // SubmitCommandBuffer would make the nvdec operations async, this is not currently working // TODO(ameerj): RE proper async nvdec operation // gpu_thread.SubmitCommandBuffer(std::move(entries)); - - cdma_pusher->ProcessEntries(std::move(entries)); + cdma_pushers[id]->ProcessEntries(std::move(entries)); } /// Frees the CDMAPusher instance to free up resources - void ClearCdmaInstance() { - cdma_pusher.reset(); + void ClearCdmaInstance(u32 id) { + if (cdma_pushers.find(id) != cdma_pushers.end()) { + cdma_pushers.erase(id); + } } /// Swap buffers (render frame) @@ -659,7 +650,7 @@ struct GPU::Impl { Core::System& system; std::unique_ptr memory_manager; std::unique_ptr dma_pusher; - std::unique_ptr cdma_pusher; + std::map> cdma_pushers; std::unique_ptr renderer; VideoCore::RasterizerInterface* rasterizer = nullptr; const bool use_nvdec; @@ -811,14 +802,6 @@ const Tegra::DmaPusher& GPU::DmaPusher() const { return impl->DmaPusher(); } -Tegra::CDmaPusher& GPU::CDmaPusher() { - return impl->CDmaPusher(); -} - -const Tegra::CDmaPusher& GPU::CDmaPusher() const { - return impl->CDmaPusher(); -} - VideoCore::RendererBase& GPU::Renderer() { return impl->Renderer(); } @@ -887,12 +870,12 @@ void GPU::PushGPUEntries(Tegra::CommandList&& entries) { impl->PushGPUEntries(std::move(entries)); } -void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { - impl->PushCommandBuffer(entries); +void GPU::PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries) { + impl->PushCommandBuffer(id, entries); } -void GPU::ClearCdmaInstance() { - impl->ClearCdmaInstance(); +void GPU::ClearCdmaInstance(u32 id) { + impl->ClearCdmaInstance(id); } void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index c89a5d693..500411176 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -242,10 +242,10 @@ public: void PushGPUEntries(Tegra::CommandList&& entries); /// Push GPU command buffer entries to be processed - void PushCommandBuffer(Tegra::ChCommandHeaderList& entries); + void PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries); /// Frees the CDMAPusher instance to free up resources - void ClearCdmaInstance(); + void ClearCdmaInstance(u32 id); /// Swap buffers (render frame) void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); -- 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/common/x64/native_clock.cpp | 6 +++--- src/core/hle/service/audio/hwopus.cpp | 4 ++-- src/core/perf_stats.h | 4 ++-- src/video_core/shader_notify.cpp | 2 +- src/video_core/shader_notify.h | 2 +- src/yuzu/loading_screen.cpp | 4 ++-- src/yuzu/loading_screen.h | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 87de40624..28f834443 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -19,16 +19,16 @@ u64 EstimateRDTSCFrequency() { // get current time _mm_mfence(); const u64 tscStart = __rdtsc(); - const auto startTime = std::chrono::high_resolution_clock::now(); + const auto startTime = std::chrono::steady_clock::now(); // wait roughly 3 seconds while (true) { auto milli = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - startTime); + std::chrono::steady_clock::now() - startTime); if (milli.count() >= 3000) break; std::this_thread::sleep_for(milli_10); } - const auto endTime = std::chrono::high_resolution_clock::now(); + const auto endTime = std::chrono::steady_clock::now(); _mm_mfence(); const u64 tscEnd = __rdtsc(); // calculate difference 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); diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp index dc6995b46..bcaf5f575 100644 --- a/src/video_core/shader_notify.cpp +++ b/src/video_core/shader_notify.cpp @@ -18,7 +18,7 @@ int ShaderNotify::ShadersBuilding() noexcept { const int now_complete = num_complete.load(std::memory_order::relaxed); const int now_building = num_building.load(std::memory_order::relaxed); if (now_complete == now_building) { - const auto now = std::chrono::high_resolution_clock::now(); + const auto now = std::chrono::steady_clock::now(); if (completed && num_complete == num_when_completed) { if (now - complete_time > TIME_TO_STOP_REPORTING) { report_base = now_complete; diff --git a/src/video_core/shader_notify.h b/src/video_core/shader_notify.h index ad363bfb5..4d8d52071 100644 --- a/src/video_core/shader_notify.h +++ b/src/video_core/shader_notify.h @@ -28,6 +28,6 @@ private: bool completed{}; int num_when_completed{}; - std::chrono::high_resolution_clock::time_point complete_time; + std::chrono::steady_clock::time_point complete_time; }; } // namespace VideoCore diff --git a/src/yuzu/loading_screen.cpp b/src/yuzu/loading_screen.cpp index ae842306c..b001b8c23 100644 --- a/src/yuzu/loading_screen.cpp +++ b/src/yuzu/loading_screen.cpp @@ -136,7 +136,7 @@ void LoadingScreen::OnLoadComplete() { void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { using namespace std::chrono; - const auto now = high_resolution_clock::now(); + const auto now = steady_clock::now(); // reset the timer if the stage changes if (stage != previous_stage) { ui->progress_bar->setStyleSheet(QString::fromUtf8(progressbar_style[stage])); @@ -160,7 +160,7 @@ void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size // If theres a drastic slowdown in the rate, then display an estimate if (now - previous_time > milliseconds{50} || slow_shader_compile_start) { if (!slow_shader_compile_start) { - slow_shader_start = high_resolution_clock::now(); + slow_shader_start = steady_clock::now(); slow_shader_compile_start = true; slow_shader_first_value = value; } diff --git a/src/yuzu/loading_screen.h b/src/yuzu/loading_screen.h index 801d08e1a..29155a77c 100644 --- a/src/yuzu/loading_screen.h +++ b/src/yuzu/loading_screen.h @@ -84,8 +84,8 @@ private: // shaders, it will start quickly but end slow if new shaders were added since previous launch. // These variables are used to detect the change in speed so we can generate an ETA bool slow_shader_compile_start = false; - std::chrono::high_resolution_clock::time_point slow_shader_start; - std::chrono::high_resolution_clock::time_point previous_time; + std::chrono::steady_clock::time_point slow_shader_start; + std::chrono::steady_clock::time_point previous_time; std::size_t slow_shader_first_value = 0; }; -- 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 +++ src/video_core/gpu.cpp | 9 +++++---- 5 files changed, 27 insertions(+), 17 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 diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 27a47954d..8788f5148 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -333,8 +333,8 @@ struct GPU::Impl { return; } - if (cdma_pushers.find(id) == cdma_pushers.end()) { - cdma_pushers[id] = std::make_unique(gpu); + if (!cdma_pushers.contains(id)) { + cdma_pushers.insert_or_assign(id, std::make_unique(gpu)); } // SubmitCommandBuffer would make the nvdec operations async, this is not currently working @@ -345,8 +345,9 @@ struct GPU::Impl { /// Frees the CDMAPusher instance to free up resources void ClearCdmaInstance(u32 id) { - if (cdma_pushers.find(id) != cdma_pushers.end()) { - cdma_pushers.erase(id); + const auto iter = cdma_pushers.find(id); + if (iter != cdma_pushers.end()) { + cdma_pushers.erase(iter); } } -- 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 +++-- src/yuzu/configuration/configure_input_player.cpp | 131 ++++++++++------------ src/yuzu/main.cpp | 3 + 8 files changed, 147 insertions(+), 88 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; } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 34099bc83..8a8be8e40 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -907,88 +907,79 @@ void ConfigureInputPlayer::UpdateUI() { } void ConfigureInputPlayer::SetConnectableControllers() { - const auto add_controllers = [this](bool enable_all, - Core::HID::NpadStyleTag npad_style_set = {}) { - index_controller_type_pairs.clear(); - ui->comboControllerType->clear(); - - if (enable_all || npad_style_set.fullkey == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::ProController); - ui->comboControllerType->addItem(tr("Pro Controller")); - } - - if (enable_all || npad_style_set.joycon_dual == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::JoyconDual); - ui->comboControllerType->addItem(tr("Dual Joycons")); - } + Core::HID::NpadStyleTag npad_style_set = hid_core.GetSupportedStyleTag(); + index_controller_type_pairs.clear(); + ui->comboControllerType->clear(); - if (enable_all || npad_style_set.joycon_left == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::JoyconLeft); - ui->comboControllerType->addItem(tr("Left Joycon")); - } + if (npad_style_set.fullkey == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::ProController); + ui->comboControllerType->addItem(tr("Pro Controller")); + } - if (enable_all || npad_style_set.joycon_right == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::JoyconRight); - ui->comboControllerType->addItem(tr("Right Joycon")); - } + if (npad_style_set.joycon_dual == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::JoyconDual); + ui->comboControllerType->addItem(tr("Dual Joycons")); + } - if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::Handheld); - ui->comboControllerType->addItem(tr("Handheld")); - } + if (npad_style_set.joycon_left == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::JoyconLeft); + ui->comboControllerType->addItem(tr("Left Joycon")); + } - if (enable_all || npad_style_set.gamecube == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::GameCube); - ui->comboControllerType->addItem(tr("GameCube Controller")); - } + if (npad_style_set.joycon_right == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::JoyconRight); + ui->comboControllerType->addItem(tr("Right Joycon")); + } - // Disable all unsupported controllers - if (!Settings::values.enable_all_controllers) { - return; - } - if (enable_all || npad_style_set.palma == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::Pokeball); - ui->comboControllerType->addItem(tr("Poke Ball Plus")); - } + if (player_index == 0 && npad_style_set.handheld == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::Handheld); + ui->comboControllerType->addItem(tr("Handheld")); + } - if (enable_all || npad_style_set.lark == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::NES); - ui->comboControllerType->addItem(tr("NES Controller")); - } + if (npad_style_set.gamecube == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::GameCube); + ui->comboControllerType->addItem(tr("GameCube Controller")); + } - if (enable_all || npad_style_set.lucia == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::SNES); - ui->comboControllerType->addItem(tr("SNES Controller")); - } + // Disable all unsupported controllers + if (!Settings::values.enable_all_controllers) { + return; + } + if (npad_style_set.palma == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::Pokeball); + ui->comboControllerType->addItem(tr("Poke Ball Plus")); + } - if (enable_all || npad_style_set.lagoon == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::N64); - ui->comboControllerType->addItem(tr("N64 Controller")); - } + if (npad_style_set.lark == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::NES); + ui->comboControllerType->addItem(tr("NES Controller")); + } - if (enable_all || npad_style_set.lager == 1) { - index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Core::HID::NpadStyleIndex::SegaGenesis); - ui->comboControllerType->addItem(tr("Sega Genesis")); - } - }; + if (npad_style_set.lucia == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::SNES); + ui->comboControllerType->addItem(tr("SNES Controller")); + } - if (!is_powered_on) { - add_controllers(true); - return; + if (npad_style_set.lagoon == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::N64); + ui->comboControllerType->addItem(tr("N64 Controller")); } - add_controllers(false, hid_core.GetSupportedStyleTag()); + if (npad_style_set.lager == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Core::HID::NpadStyleIndex::SegaGenesis); + ui->comboControllerType->addItem(tr("Sega Genesis")); + } } Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f266fd963..5a9dec8f3 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1516,6 +1516,9 @@ void GMainWindow::ShutdownGame() { input_subsystem->GetTas()->Stop(); OnTasStateChanged(); + // Enable all controllers + system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); + render_window->removeEventFilter(render_window); render_window->setAttribute(Qt::WA_Hover, false); -- 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/audio_core/delay_line.cpp | 4 ++++ src/audio_core/delay_line.h | 4 ++++ src/common/host_memory.cpp | 4 ++++ src/core/hle/service/nvdrv/nvdata.h | 4 ++++ src/shader_recompiler/environment.h | 4 ++++ 5 files changed, 20 insertions(+) (limited to 'src/core') diff --git a/src/audio_core/delay_line.cpp b/src/audio_core/delay_line.cpp index f4e4dd8d2..2793ed8db 100644 --- a/src/audio_core/delay_line.cpp +++ b/src/audio_core/delay_line.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 #include "audio_core/delay_line.h" diff --git a/src/audio_core/delay_line.h b/src/audio_core/delay_line.h index cafddd432..84f11bc52 100644 --- a/src/audio_core/delay_line.h +++ b/src/audio_core/delay_line.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 "common/common_types.h" diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index b44a44949..28949fe5e 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_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. + #ifdef _WIN32 #include 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 diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 8369d0d84..b4df73e8a 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.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 -- 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/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + 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 +++++++++++++++++++++ 6 files changed, 77 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/common/logging/filter.cpp b/src/common/logging/filter.cpp index 42744c994..b898a652c 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -114,6 +114,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Service, NGCT) \ SUB(Service, NIFM) \ SUB(Service, NIM) \ + SUB(Service, NOTIF) \ SUB(Service, NPNS) \ SUB(Service, NS) \ SUB(Service, NVDRV) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index 2d21fc483..9ed0c7ad6 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -82,6 +82,7 @@ enum class Class : u8 { Service_NGCT, ///< The NGCT (No Good Content for Terra) service Service_NIFM, ///< The NIFM (Network interface) service Service_NIM, ///< The NIM service + Service_NOTIF, ///< The NOTIF (Notification) service Service_NPNS, ///< The NPNS service Service_NS, ///< The NS services Service_NVDRV, ///< The NVDRV (Nvidia driver) service 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/common/input.h | 4 +- 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 ++- src/input_common/helpers/stick_from_buttons.cpp | 75 +++++++++++-------- src/input_common/helpers/touch_from_buttons.cpp | 11 +-- 9 files changed, 171 insertions(+), 129 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 848ad7b81..f775a4c01 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -227,7 +227,7 @@ struct CallbackStatus { // Triggered once every input change struct InputCallback { - std::function on_change; + std::function on_change; }; /// An abstract class template for an input device (a button, an analog input, etc.). @@ -247,7 +247,7 @@ public: } // Triggers the function set in the callback - void TriggerOnChange(CallbackStatus status) { + void TriggerOnChange(const CallbackStatus& status) { if (callback.on_change) { callback.on_change(status); } 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 diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 77fcd655e..e23394f5f 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -19,23 +19,36 @@ public: : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_), modifier_angle(modifier_angle_) { - Common::Input::InputCallback button_up_callback{ - [this](Common::Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }}; - Common::Input::InputCallback button_down_callback{ - [this](Common::Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }}; - Common::Input::InputCallback button_left_callback{ - [this](Common::Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }}; - Common::Input::InputCallback button_right_callback{ - [this](Common::Input::CallbackStatus callback_) { - UpdateRightButtonStatus(callback_); - }}; - Common::Input::InputCallback button_modifier_callback{ - [this](Common::Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }}; - up->SetCallback(button_up_callback); - down->SetCallback(button_down_callback); - left->SetCallback(button_left_callback); - right->SetCallback(button_right_callback); - modifier->SetCallback(button_modifier_callback); + up->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback_) { + UpdateUpButtonStatus(callback_); + }, + }); + down->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback_) { + UpdateDownButtonStatus(callback_); + }, + }); + left->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback_) { + UpdateLeftButtonStatus(callback_); + }, + }); + right->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback_) { + UpdateRightButtonStatus(callback_); + }, + }); + modifier->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback_) { + UpdateModButtonStatus(callback_); + }, + }); last_x_axis_value = 0.0f; last_y_axis_value = 0.0f; } @@ -133,27 +146,27 @@ public: } } - void UpdateUpButtonStatus(Common::Input::CallbackStatus button_callback) { + void UpdateUpButtonStatus(const Common::Input::CallbackStatus& button_callback) { up_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateDownButtonStatus(Common::Input::CallbackStatus button_callback) { + void UpdateDownButtonStatus(const Common::Input::CallbackStatus& button_callback) { down_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateLeftButtonStatus(Common::Input::CallbackStatus button_callback) { + void UpdateLeftButtonStatus(const Common::Input::CallbackStatus& button_callback) { left_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateRightButtonStatus(Common::Input::CallbackStatus button_callback) { + void UpdateRightButtonStatus(const Common::Input::CallbackStatus& button_callback) { right_status = button_callback.button_status.value; UpdateStatus(); } - void UpdateModButtonStatus(Common::Input::CallbackStatus button_callback) { + void UpdateModButtonStatus(const Common::Input::CallbackStatus& button_callback) { modifier_status = button_callback.button_status.value; UpdateStatus(); } @@ -265,18 +278,18 @@ private: Button left; Button right; Button modifier; - float modifier_scale; - float modifier_angle; + float modifier_scale{}; + float modifier_angle{}; float angle{}; float goal_angle{}; float amplitude{}; - bool up_status; - bool down_status; - bool left_status; - bool right_status; - bool modifier_status; - float last_x_axis_value; - float last_y_axis_value; + bool up_status{}; + bool down_status{}; + bool left_status{}; + bool right_status{}; + bool modifier_status{}; + float last_x_axis_value{}; + float last_y_axis_value{}; const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; std::chrono::time_point last_update; }; diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index 35d60bc90..ece1e3b32 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -14,10 +14,13 @@ public: using Button = std::unique_ptr; TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_) : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { - Common::Input::InputCallback button_up_callback{ - [this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }}; last_button_value = false; - button->SetCallback(button_up_callback); + button->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback_) { + UpdateButtonStatus(callback_); + }, + }); button->ForceUpdate(); } @@ -47,7 +50,7 @@ public: return status; } - void UpdateButtonStatus(Common::Input::CallbackStatus button_callback) { + void UpdateButtonStatus(const Common::Input::CallbackStatus& button_callback) { const Common::Input::CallbackStatus status{ .type = Common::Input::InputType::Touch, .touch_status = GetStatus(button_callback.button_status.value), -- 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