From 44076bdde05b7fd6761f40bbcb18f3c6ec191f68 Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Thu, 26 Sep 2013 12:44:52 +0100 Subject: [PATCH 1/2] Add rumble support to XInput driver --- input/winxinput_joypad.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index fd19711fb9..164cf87979 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -65,6 +65,12 @@ typedef struct XINPUT_GAMEPAD Gamepad; } XINPUT_STATE; +typedef struct +{ + uint16_t wLeftMotorSpeed; + uint16_t wRightMotorSpeed; +} XINPUT_VIBRATION; + #endif // Guide constant is not officially documented @@ -93,6 +99,9 @@ static HINSTANCE g_winxinput_dll; typedef uint32_t (__stdcall *XInputGetStateEx_t)(uint32_t, XINPUT_STATE*); static XInputGetStateEx_t g_XInputGetStateEx; +typedef uint32_t (__stdcall *XInputSetState_t)(uint32_t, XINPUT_VIBRATION*); +static XInputSetState_t g_XInputSetState; + // Guide button may or may not be available static bool g_winxinput_guide_button_supported; @@ -102,6 +111,8 @@ typedef struct bool connected; } winxinput_joypad_state; +static XINPUT_VIBRATION g_xinput_rumble_state; + static winxinput_joypad_state g_winxinput_states[4]; static inline int pad_index_to_xplayer_index(unsigned pad) @@ -174,12 +185,19 @@ static bool winxinput_joypad_init(void) g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); if (!g_XInputGetStateEx) { - RARCH_ERR("Failed to init XInput: xinput1_3.dll is invalid or corrupt.\n"); + RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); return false; // DLL was loaded but did not contain the correct function. } RARCH_WARN("XInput: No guide button support.\n"); } + g_XInputSetState = (XInputSetState_t) GetProcAddress(g_winxinput_dll, "XInputSetState"); + if (!g_XInputSetState) + { + RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); + return false; // DLL was loaded but did not contain the correct function. + } + // Zero out the states for (unsigned i = 0; i < 4; ++i) memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); @@ -364,6 +382,21 @@ static void winxinput_joypad_poll(void) dinput_joypad.poll(); } +static bool winxinput_joypad_rumble(unsigned pad, enum retro_rumble_effect effect, uint16_t strength) +{ + // Consider the low frequency (left) motor the "strong" one. + if (effect == RETRO_RUMBLE_STRONG) + g_xinput_rumble_state.wLeftMotorSpeed = strength; + else if (effect == RETRO_RUMBLE_WEAK) + g_xinput_rumble_state.wRightMotorSpeed = strength; + + int xplayer = pad_index_to_xplayer_index(pad); + if (xplayer == -1) + return dinput_joypad.set_rumble(pad, effect, strength); + + return (g_XInputSetState(xplayer, &g_xinput_rumble_state) == ERROR_SUCCESS); +} + const rarch_joypad_driver_t winxinput_joypad = { winxinput_joypad_init, winxinput_joypad_query_pad, @@ -371,7 +404,7 @@ const rarch_joypad_driver_t winxinput_joypad = { winxinput_joypad_button, winxinput_joypad_axis, winxinput_joypad_poll, - NULL, // FIXME: Add rumble. + winxinput_joypad_rumble, winxinput_joypad_name, "winxinput", }; From 061df5c878364953310b18b684825708faa384ef Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Thu, 26 Sep 2013 14:12:58 +0100 Subject: [PATCH 2/2] tweak xinput rumble --- input/winxinput_joypad.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index 164cf87979..baf46dc02b 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -111,7 +111,7 @@ typedef struct bool connected; } winxinput_joypad_state; -static XINPUT_VIBRATION g_xinput_rumble_state; +static XINPUT_VIBRATION g_xinput_rumble_states[4]; static winxinput_joypad_state g_winxinput_states[4]; @@ -186,6 +186,7 @@ static bool winxinput_joypad_init(void) if (!g_XInputGetStateEx) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); + FreeLibrary(g_winxinput_dll); return false; // DLL was loaded but did not contain the correct function. } RARCH_WARN("XInput: No guide button support.\n"); @@ -195,6 +196,7 @@ static bool winxinput_joypad_init(void) if (!g_XInputSetState) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); + FreeLibrary(g_winxinput_dll); return false; // DLL was loaded but did not contain the correct function. } @@ -384,17 +386,23 @@ static void winxinput_joypad_poll(void) static bool winxinput_joypad_rumble(unsigned pad, enum retro_rumble_effect effect, uint16_t strength) { - // Consider the low frequency (left) motor the "strong" one. - if (effect == RETRO_RUMBLE_STRONG) - g_xinput_rumble_state.wLeftMotorSpeed = strength; - else if (effect == RETRO_RUMBLE_WEAK) - g_xinput_rumble_state.wRightMotorSpeed = strength; - int xplayer = pad_index_to_xplayer_index(pad); if (xplayer == -1) - return dinput_joypad.set_rumble(pad, effect, strength); + { + if (dinput_joypad.set_rumble) + return dinput_joypad.set_rumble(pad, effect, strength);. + else + return false; + } + + + // Consider the low frequency (left) motor the "strong" one. + if (effect == RETRO_RUMBLE_STRONG) + g_xinput_rumble_states[xplayer].wLeftMotorSpeed = strength; + else if (effect == RETRO_RUMBLE_WEAK) + g_xinput_rumble_states[xplayer].wRightMotorSpeed = strength; - return (g_XInputSetState(xplayer, &g_xinput_rumble_state) == ERROR_SUCCESS); + return g_XInputSetState(xplayer, &g_xinput_rumble_states[xplayer]) == ERROR_SUCCESS; } const rarch_joypad_driver_t winxinput_joypad = {