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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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 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/hle') 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/hle') 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 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/hle') 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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/hle') 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 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/hle') 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 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/hle') 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 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/hle') 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 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/hle') 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 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/hle') 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 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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/hle') 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/hle') 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 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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 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/hle') 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/hle') 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/hle') 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 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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/hle') 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