Merge pull request #310 from pinumbernumber/master

Add rumble support to XInput driver
This commit is contained in:
Hans-Kristian Arntzen 2013-09-26 06:14:17 -07:00
commit 54d0fabbd7

View File

@ -65,6 +65,12 @@ typedef struct
XINPUT_GAMEPAD Gamepad; XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE; } XINPUT_STATE;
typedef struct
{
uint16_t wLeftMotorSpeed;
uint16_t wRightMotorSpeed;
} XINPUT_VIBRATION;
#endif #endif
// Guide constant is not officially documented // 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*); typedef uint32_t (__stdcall *XInputGetStateEx_t)(uint32_t, XINPUT_STATE*);
static XInputGetStateEx_t g_XInputGetStateEx; 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 // Guide button may or may not be available
static bool g_winxinput_guide_button_supported; static bool g_winxinput_guide_button_supported;
@ -102,6 +111,8 @@ typedef struct
bool connected; bool connected;
} winxinput_joypad_state; } winxinput_joypad_state;
static XINPUT_VIBRATION g_xinput_rumble_states[4];
static winxinput_joypad_state g_winxinput_states[4]; static winxinput_joypad_state g_winxinput_states[4];
static inline int pad_index_to_xplayer_index(unsigned pad) static inline int pad_index_to_xplayer_index(unsigned pad)
@ -174,12 +185,21 @@ static bool winxinput_joypad_init(void)
g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState");
if (!g_XInputGetStateEx) 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");
FreeLibrary(g_winxinput_dll);
return false; // DLL was loaded but did not contain the correct function. return false; // DLL was loaded but did not contain the correct function.
} }
RARCH_WARN("XInput: No guide button support.\n"); 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");
FreeLibrary(g_winxinput_dll);
return false; // DLL was loaded but did not contain the correct function.
}
// Zero out the states // Zero out the states
for (unsigned i = 0; i < 4; ++i) for (unsigned i = 0; i < 4; ++i)
memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state));
@ -364,6 +384,27 @@ static void winxinput_joypad_poll(void)
dinput_joypad.poll(); dinput_joypad.poll();
} }
static bool winxinput_joypad_rumble(unsigned pad, enum retro_rumble_effect effect, uint16_t strength)
{
int xplayer = pad_index_to_xplayer_index(pad);
if (xplayer == -1)
{
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_states[xplayer]) == ERROR_SUCCESS;
}
const rarch_joypad_driver_t winxinput_joypad = { const rarch_joypad_driver_t winxinput_joypad = {
winxinput_joypad_init, winxinput_joypad_init,
winxinput_joypad_query_pad, winxinput_joypad_query_pad,
@ -371,7 +412,7 @@ const rarch_joypad_driver_t winxinput_joypad = {
winxinput_joypad_button, winxinput_joypad_button,
winxinput_joypad_axis, winxinput_joypad_axis,
winxinput_joypad_poll, winxinput_joypad_poll,
NULL, // FIXME: Add rumble. winxinput_joypad_rumble,
winxinput_joypad_name, winxinput_joypad_name,
"winxinput", "winxinput",
}; };