From 1c4bbc8cde506665de1d1a7b36312c36a1e67a2b Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 22 Aug 2020 22:46:12 +0200 Subject: [PATCH 1/2] XInput: Do not use XINPUT_CAPS_FFB_SUPPORTED There are several reasons for this: 1. XINPUT_CAPS_FFB_SUPPORTED flag was introduced in Windows 8, and therefore only supported by XInput 1.4 2. Despite the name, this flag does NOT indicate whether normal rumble is supported. This flag is reserved for more complex force feedback, and according to MSDN it may have went unused on Windows. This fixes a future (the method is not used yet) bug where XInputControllerInterface::GetControllerRumbleMotorCount would erroreously report no rumble support. --- .../xinput_controller_interface.cpp | 18 ++---------------- .../xinput_controller_interface.h | 3 --- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/frontend-common/xinput_controller_interface.cpp b/src/frontend-common/xinput_controller_interface.cpp index 92866fd72..2833db177 100644 --- a/src/frontend-common/xinput_controller_interface.cpp +++ b/src/frontend-common/xinput_controller_interface.cpp @@ -39,11 +39,9 @@ bool XInputControllerInterface::Initialize(CommonHostInterface* host_interface) reinterpret_cast(GetProcAddress(m_xinput_module, reinterpret_cast(100))); if (!m_xinput_get_state) reinterpret_cast(GetProcAddress(m_xinput_module, "XInputGetState")); - m_xinput_get_capabilities = - reinterpret_cast(GetProcAddress(m_xinput_module, "XInputGetCapabilities")); m_xinput_set_state = reinterpret_cast(GetProcAddress(m_xinput_module, "XInputSetState")); - if (!m_xinput_get_state || !m_xinput_get_capabilities || !m_xinput_set_state) + if (!m_xinput_get_state || !m_xinput_set_state) { Log_ErrorPrintf("Failed to get XInput function pointers."); return false; @@ -72,7 +70,6 @@ void XInputControllerInterface::PollEvents() if (!cd.connected) { cd.connected = true; - UpdateCapabilities(i); OnControllerConnected(static_cast(i)); } @@ -155,17 +152,6 @@ void XInputControllerInterface::CheckForStateChanges(u32 index, const XINPUT_STA } } -void XInputControllerInterface::UpdateCapabilities(u32 index) -{ - ControllerData& cd = m_controllers[index]; - - XINPUT_CAPABILITIES caps = {}; - m_xinput_get_capabilities(index, 0, &caps); - cd.supports_rumble = (caps.Flags & 0x0001 /* XINPUT_CAPS_FFB_SUPPORTED */); - - Log_InfoPrintf("Controller %u: Rumble is %s", index, cd.supports_rumble ? "supported" : "not supported"); -} - void XInputControllerInterface::ClearBindings() { for (auto& it : m_controllers) @@ -277,7 +263,7 @@ u32 XInputControllerInterface::GetControllerRumbleMotorCount(int controller_inde if (static_cast(controller_index) >= XUSER_MAX_COUNT || !m_controllers[controller_index].connected) return 0; - return m_controllers[controller_index].supports_rumble ? NUM_RUMBLE_MOTORS : 0; + return NUM_RUMBLE_MOTORS; } void XInputControllerInterface::SetControllerRumbleStrength(int controller_index, const float* strengths, diff --git a/src/frontend-common/xinput_controller_interface.h b/src/frontend-common/xinput_controller_interface.h index 5949922e6..5d02e1262 100644 --- a/src/frontend-common/xinput_controller_interface.h +++ b/src/frontend-common/xinput_controller_interface.h @@ -60,7 +60,6 @@ private: { XINPUT_STATE last_state = {}; bool connected = false; - bool supports_rumble = false; // Scaling value of 1.30f to 1.40f recommended when using recent controllers float axis_scale = 1.00f; @@ -74,7 +73,6 @@ private: using ControllerDataArray = std::array; void CheckForStateChanges(u32 index, const XINPUT_STATE& new_state); - void UpdateCapabilities(u32 index); bool HandleAxisEvent(u32 index, Axis axis, s32 value); bool HandleButtonEvent(u32 index, u32 button, bool pressed); @@ -82,7 +80,6 @@ private: HMODULE m_xinput_module{}; DWORD(WINAPI* m_xinput_get_state)(DWORD, XINPUT_STATE*); - DWORD(WINAPI* m_xinput_get_capabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*); DWORD(WINAPI* m_xinput_set_state)(DWORD, XINPUT_VIBRATION*); std::mutex m_event_intercept_mutex; Hook::Callback m_event_intercept_callback; From 8def7420c4272c12a4d6b7a83ef5b6a84d0c3e65 Mon Sep 17 00:00:00 2001 From: Silent Date: Sat, 22 Aug 2020 22:52:54 +0200 Subject: [PATCH 2/2] XInput: Try to use XInput 1.3 if 1.4 is not present This simple change enables the use of Guide button for Windows 7 users, provided they have DirectX End-User Runtimes installed. XInput 9.1.0 does not have the hidden XInputGetStateEx export, so it was not possible to poll for Guide button. --- .../xinput_controller_interface.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/frontend-common/xinput_controller_interface.cpp b/src/frontend-common/xinput_controller_interface.cpp index 2833db177..076746f3b 100644 --- a/src/frontend-common/xinput_controller_interface.cpp +++ b/src/frontend-common/xinput_controller_interface.cpp @@ -23,15 +23,19 @@ ControllerInterface::Backend XInputControllerInterface::GetBackend() const bool XInputControllerInterface::Initialize(CommonHostInterface* host_interface) { - m_xinput_module = LoadLibraryA("xinput1_4.dll"); + m_xinput_module = LoadLibraryW(L"xinput1_4"); if (!m_xinput_module) { - m_xinput_module = LoadLibraryA("xinput9_1_0.dll"); - if (!m_xinput_module) - { - Log_ErrorPrintf("Failed to load XInput module."); - return false; - } + m_xinput_module = LoadLibraryW(L"xinput1_3"); + } + if (!m_xinput_module) + { + m_xinput_module = LoadLibraryW(L"xinput9_1_0"); + } + if (!m_xinput_module) + { + Log_ErrorPrintf("Failed to load XInput module."); + return false; } // Try the hidden version of XInputGetState(), which lets us query the guide button.