diff --git a/input/drivers_joypad/dinput_joypad.c b/input/drivers_joypad/dinput_joypad.c
index 4b3021acae..2acfbad09e 100644
--- a/input/drivers_joypad/dinput_joypad.c
+++ b/input/drivers_joypad/dinput_joypad.c
@@ -39,15 +39,6 @@
/* TODO/FIXME - static globals */
static struct dinput_joypad_data g_pads[MAX_USERS];
static unsigned g_joypad_cnt;
-#ifdef HAVE_XINPUT
-static unsigned g_last_xinput_pad_idx;
-
-static const GUID common_xinput_guids[] = {
- {MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Valve streaming pad */
- {MAKELONG(0x045E, 0x02A1),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Wired 360 pad */
- {MAKELONG(0x045E, 0x028E),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}} /* wireless 360 pad */
-};
-#endif
/* forward declarations */
void dinput_destroy_context(void);
@@ -55,9 +46,18 @@ bool dinput_init_context(void);
extern LPDIRECTINPUT8 g_dinput_ctx;
+#include "dinput_joypad_inl.h"
+
#ifdef HAVE_XINPUT
extern bool g_xinput_block_pads;
extern int g_xinput_pad_indexes[MAX_USERS];
+static unsigned g_last_xinput_pad_idx;
+
+static const GUID common_xinput_guids[] = {
+ {MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Valve streaming pad */
+ {MAKELONG(0x045E, 0x02A1),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Wired 360 pad */
+ {MAKELONG(0x045E, 0x028E),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}} /* wireless 360 pad */
+};
bool dinput_joypad_get_vidpid_from_xinput_index(
int32_t index, int32_t *vid,
@@ -85,116 +85,7 @@ bool dinput_joypad_get_vidpid_from_xinput_index(
return false;
}
-#endif
-static void dinput_joypad_destroy(void)
-{
- unsigned i;
-
- for (i = 0; i < MAX_USERS; i++)
- {
- if (g_pads[i].joypad)
- {
- if (g_pads[i].rumble_iface[0])
- {
- IDirectInputEffect_Stop(g_pads[i].rumble_iface[0]);
- IDirectInputEffect_Release(g_pads[i].rumble_iface[0]);
- }
- if (g_pads[i].rumble_iface[1])
- {
- IDirectInputEffect_Stop(g_pads[i].rumble_iface[1]);
- IDirectInputEffect_Release(g_pads[i].rumble_iface[1]);
- }
-
- IDirectInputDevice8_Unacquire(g_pads[i].joypad);
- IDirectInputDevice8_Release(g_pads[i].joypad);
- }
-
- free(g_pads[i].joy_name);
- g_pads[i].joy_name = NULL;
- free(g_pads[i].joy_friendly_name);
- g_pads[i].joy_friendly_name = NULL;
-
- input_config_clear_device_name(i);
- }
-
- g_joypad_cnt = 0;
- memset(g_pads, 0, sizeof(g_pads));
-
- /* Can be blocked by global Dinput context. */
- dinput_destroy_context();
-}
-
-static void dinput_create_rumble_effects(struct dinput_joypad_data *pad)
-{
- DIENVELOPE dienv;
- DICONSTANTFORCE dicf;
- LONG direction = 0;
- DWORD axis = DIJOFS_X;
-
- dicf.lMagnitude = 0;
-
- dienv.dwSize = sizeof(DIENVELOPE);
- dienv.dwAttackLevel = 5000;
- dienv.dwAttackTime = 250000;
- dienv.dwFadeLevel = 0;
- dienv.dwFadeTime = 250000;
-
- pad->rumble_props.cAxes = 1;
- pad->rumble_props.dwTriggerButton = DIEB_NOTRIGGER;
- pad->rumble_props.dwTriggerRepeatInterval = 0;
- pad->rumble_props.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
- pad->rumble_props.dwDuration = INFINITE;
- pad->rumble_props.dwFlags = DIEFF_CARTESIAN |
- DIEFF_OBJECTOFFSETS;
- pad->rumble_props.dwGain = 0;
- pad->rumble_props.dwSize = sizeof(DIEFFECT);
- pad->rumble_props.dwStartDelay = 0;
- pad->rumble_props.lpEnvelope = &dienv;
- pad->rumble_props.lpvTypeSpecificParams = &dicf;
- pad->rumble_props.rgdwAxes = &axis;
- pad->rumble_props.rglDirection = &direction;
-
- axis = DIJOFS_Y;
-
-#ifdef __cplusplus
- if (IDirectInputDevice8_CreateEffect(pad->joypad, GUID_ConstantForce,
- &pad->rumble_props, &pad->rumble_iface[0], NULL) != DI_OK)
- RARCH_WARN("[DINPUT]: Strong rumble unavailable.\n");
-
- if (IDirectInputDevice8_CreateEffect(pad->joypad, GUID_ConstantForce,
- &pad->rumble_props, &pad->rumble_iface[1], NULL) != DI_OK)
- RARCH_WARN("[DINPUT]: Weak rumble unavailable.\n");
-#else
- if (IDirectInputDevice8_CreateEffect(pad->joypad, &GUID_ConstantForce,
- &pad->rumble_props, &pad->rumble_iface[0], NULL) != DI_OK)
- RARCH_WARN("[DINPUT]: Strong rumble unavailable.\n");
-
- if (IDirectInputDevice8_CreateEffect(pad->joypad, &GUID_ConstantForce,
- &pad->rumble_props, &pad->rumble_iface[1], NULL) != DI_OK)
- RARCH_WARN("[DINPUT]: Weak rumble unavailable.\n");
-#endif
-}
-
-static BOOL CALLBACK enum_axes_cb(
- const DIDEVICEOBJECTINSTANCE *inst, void *p)
-{
- DIPROPRANGE range;
- LPDIRECTINPUTDEVICE8 joypad = (LPDIRECTINPUTDEVICE8)p;
-
- range.diph.dwSize = sizeof(DIPROPRANGE);
- range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- range.diph.dwHow = DIPH_BYID;
- range.diph.dwObj = inst->dwType;
- range.lMin = -0x7fff;
- range.lMax = 0x7fff;
-
- IDirectInputDevice8_SetProperty(joypad, DIPROP_RANGE, &range.diph);
-
- return DIENUM_CONTINUE;
-}
-
-#ifdef HAVE_XINPUT
/* Based on SDL2's implementation. */
static bool guid_is_xinput_device(const GUID* product_guid)
{
@@ -289,13 +180,6 @@ static bool guid_is_xinput_device(const GUID* product_guid)
}
#endif
-static const char *dinput_joypad_name(unsigned port)
-{
- if (port < MAX_USERS)
- return g_pads[port].joy_name;
- return NULL;
-}
-
static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
{
#ifdef HAVE_XINPUT
@@ -407,184 +291,6 @@ static bool dinput_joypad_init(void *data)
return true;
}
-static int16_t dinput_joypad_button_state(
- const struct dinput_joypad_data *pad,
- uint16_t joykey)
-{
- unsigned hat_dir = GET_HAT_DIR(joykey);
-
- if (hat_dir)
- {
- unsigned h = GET_HAT(joykey);
-
- /* 4 is number of hats */
- if (h < 4)
- {
- unsigned pov = pad->joy_state.rgdwPOV[h];
- switch (hat_dir)
- {
- case HAT_UP_MASK:
- {
- static const unsigned check1 = (JOY_POVRIGHT/2);
- static const unsigned check2 = (JOY_POVLEFT+JOY_POVRIGHT/2);
- return (
- (pov == JOY_POVFORWARD) ||
- (pov == check1) ||
- (pov == check2)
- );
- }
- case HAT_RIGHT_MASK:
- {
- static const unsigned check1 = (JOY_POVRIGHT/2);
- static const unsigned check2 = (JOY_POVRIGHT+JOY_POVRIGHT/2);
- return (
- (pov == JOY_POVRIGHT) ||
- (pov == check1) ||
- (pov == check2)
- );
- }
- case HAT_DOWN_MASK:
- {
- static const unsigned check1 = (JOY_POVRIGHT+JOY_POVRIGHT/2);
- static const unsigned check2 = (JOY_POVBACKWARD+JOY_POVRIGHT/2);
- return
- (
- (pov == JOY_POVBACKWARD) ||
- (pov == check1) ||
- (pov == check2)
- );
- }
- case HAT_LEFT_MASK:
- {
- static const unsigned check1 = (JOY_POVBACKWARD+JOY_POVRIGHT/2);
- static const unsigned check2 = (JOY_POVLEFT+JOY_POVRIGHT/2);
-
- return
- (
- (pov == JOY_POVLEFT) ||
- (pov == check1) ||
- (pov == check2)
- );
- }
- default:
- break;
- }
- }
- /* hat requested and no hat button down */
- }
- else if (joykey < ARRAY_SIZE_RGB_BUTTONS)
- if (pad->joy_state.rgbButtons[joykey])
- return 1;
- return 0;
-}
-
-static int16_t dinput_joypad_axis_state(
- const struct dinput_joypad_data *pad,
- uint32_t joyaxis)
-{
- int val = 0;
- int axis = -1;
- bool is_neg = false;
- bool is_pos = false;
-
- if (AXIS_NEG_GET(joyaxis) <= 7)
- {
- axis = AXIS_NEG_GET(joyaxis);
- is_neg = true;
- }
- else if (AXIS_POS_GET(joyaxis) <= 7)
- {
- axis = AXIS_POS_GET(joyaxis);
- is_pos = true;
- }
- else
- return 0;
-
- switch (axis)
- {
- case 0:
- val = pad->joy_state.lX;
- break;
- case 1:
- val = pad->joy_state.lY;
- break;
- case 2:
- val = pad->joy_state.lZ;
- break;
- case 3:
- val = pad->joy_state.lRx;
- break;
- case 4:
- val = pad->joy_state.lRy;
- break;
- case 5:
- val = pad->joy_state.lRz;
- break;
- case 6:
- case 7:
- val = pad->joy_state.rglSlider[axis - 6];
- break;
- }
-
- if (is_neg && val > 0)
- return 0;
- else if (is_pos && val < 0)
- return 0;
- return val;
-}
-
-static int16_t dinput_joypad_button(unsigned port, uint16_t joykey)
-{
- const struct dinput_joypad_data *pad = &g_pads[port];
- if (!pad || !pad->joypad)
- return 0;
- return dinput_joypad_button_state(pad, joykey);
-}
-
-static int16_t dinput_joypad_axis(unsigned port, uint32_t joyaxis)
-{
- const struct dinput_joypad_data *pad = &g_pads[port];
- if (!pad || !pad->joypad)
- return 0;
- return dinput_joypad_axis_state(pad, joyaxis);
-}
-
-static int16_t dinput_joypad_state(
- rarch_joypad_info_t *joypad_info,
- const struct retro_keybind *binds,
- unsigned port)
-{
- unsigned i;
- int16_t ret = 0;
- uint16_t port_idx = joypad_info->joy_idx;
- const struct dinput_joypad_data *pad = &g_pads[port_idx];
-
- if (!pad || !pad->joypad)
- return 0;
- if (port_idx >= DEFAULT_MAX_PADS)
- return 0;
-
- for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
- {
- /* Auto-binds are per joypad, not per user. */
- const uint64_t joykey = (binds[i].joykey != NO_BTN)
- ? binds[i].joykey : joypad_info->auto_binds[i].joykey;
- const uint32_t joyaxis = (binds[i].joyaxis != AXIS_NONE)
- ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
- if (
- (uint16_t)joykey != NO_BTN
- && dinput_joypad_button_state(
- pad, (uint16_t)joykey))
- ret |= ( 1 << i);
- else if (joyaxis != AXIS_NONE &&
- ((float)abs(dinput_joypad_axis_state(pad, joyaxis))
- / 0x8000) > joypad_info->axis_threshold)
- ret |= (1 << i);
- }
-
- return ret;
-}
-
static void dinput_joypad_poll(void)
{
unsigned i;
@@ -656,32 +362,6 @@ static void dinput_joypad_poll(void)
}
}
-static bool dinput_joypad_query_pad(unsigned port)
-{
- return port < MAX_USERS && g_pads[port].joypad;
-}
-
-bool dinput_joypad_set_rumble(unsigned port,
- enum retro_rumble_effect type, uint16_t strength)
-{
- int i = type == RETRO_RUMBLE_STRONG ? 1 : 0;
-
- if (port >= g_joypad_cnt || !g_pads[port].rumble_iface[i])
- return false;
-
- if (strength)
- {
- g_pads[port].rumble_props.dwGain =
- (DWORD)((double)strength / 65535.0 * (double)DI_FFNOMINALMAX);
- IDirectInputEffect_SetParameters(g_pads[port].rumble_iface[i],
- &g_pads[port].rumble_props, DIEP_GAIN | DIEP_START);
- }
- else
- IDirectInputEffect_Stop(g_pads[port].rumble_iface[i]);
-
- return true;
-}
-
input_device_driver_t dinput_joypad = {
dinput_joypad_init,
dinput_joypad_query_pad,
diff --git a/input/drivers_joypad/dinput_joypad_inl.h b/input/drivers_joypad/dinput_joypad_inl.h
new file mode 100644
index 0000000000..e151055b95
--- /dev/null
+++ b/input/drivers_joypad/dinput_joypad_inl.h
@@ -0,0 +1,343 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2016 - Daniel De Matteis
+ * Copyright (C) 2016-2019 - Brad Parker
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#ifndef __DINPUT_JOYPAD_INL_H
+#define __DINPUT_JOYPAD_INL_H
+
+#include
+#include
+#include
+
+static void dinput_joypad_destroy(void)
+{
+ unsigned i;
+
+ for (i = 0; i < MAX_USERS; i++)
+ {
+ if (g_pads[i].joypad)
+ {
+ if (g_pads[i].rumble_iface[0])
+ {
+ IDirectInputEffect_Stop(g_pads[i].rumble_iface[0]);
+ IDirectInputEffect_Release(g_pads[i].rumble_iface[0]);
+ }
+ if (g_pads[i].rumble_iface[1])
+ {
+ IDirectInputEffect_Stop(g_pads[i].rumble_iface[1]);
+ IDirectInputEffect_Release(g_pads[i].rumble_iface[1]);
+ }
+
+ IDirectInputDevice8_Unacquire(g_pads[i].joypad);
+ IDirectInputDevice8_Release(g_pads[i].joypad);
+ }
+
+ free(g_pads[i].joy_name);
+ g_pads[i].joy_name = NULL;
+ free(g_pads[i].joy_friendly_name);
+ g_pads[i].joy_friendly_name = NULL;
+
+ input_config_clear_device_name(i);
+ }
+
+ g_joypad_cnt = 0;
+ memset(g_pads, 0, sizeof(g_pads));
+
+ /* Can be blocked by global Dinput context. */
+ dinput_destroy_context();
+}
+
+static void dinput_create_rumble_effects(struct dinput_joypad_data *pad)
+{
+ DIENVELOPE dienv;
+ DICONSTANTFORCE dicf;
+ LONG direction = 0;
+ DWORD axis = DIJOFS_X;
+
+ dicf.lMagnitude = 0;
+
+ dienv.dwSize = sizeof(DIENVELOPE);
+ dienv.dwAttackLevel = 5000;
+ dienv.dwAttackTime = 250000;
+ dienv.dwFadeLevel = 0;
+ dienv.dwFadeTime = 250000;
+
+ pad->rumble_props.cAxes = 1;
+ pad->rumble_props.dwTriggerButton = DIEB_NOTRIGGER;
+ pad->rumble_props.dwTriggerRepeatInterval = 0;
+ pad->rumble_props.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
+ pad->rumble_props.dwDuration = INFINITE;
+ pad->rumble_props.dwFlags = DIEFF_CARTESIAN |
+ DIEFF_OBJECTOFFSETS;
+ pad->rumble_props.dwGain = 0;
+ pad->rumble_props.dwSize = sizeof(DIEFFECT);
+ pad->rumble_props.dwStartDelay = 0;
+ pad->rumble_props.lpEnvelope = &dienv;
+ pad->rumble_props.lpvTypeSpecificParams = &dicf;
+ pad->rumble_props.rgdwAxes = &axis;
+ pad->rumble_props.rglDirection = &direction;
+
+ axis = DIJOFS_Y;
+
+#ifdef __cplusplus
+ if (IDirectInputDevice8_CreateEffect(pad->joypad, GUID_ConstantForce,
+ &pad->rumble_props, &pad->rumble_iface[0], NULL) != DI_OK)
+ RARCH_WARN("[DINPUT]: Strong rumble unavailable.\n");
+
+ if (IDirectInputDevice8_CreateEffect(pad->joypad, GUID_ConstantForce,
+ &pad->rumble_props, &pad->rumble_iface[1], NULL) != DI_OK)
+ RARCH_WARN("[DINPUT]: Weak rumble unavailable.\n");
+#else
+ if (IDirectInputDevice8_CreateEffect(pad->joypad, &GUID_ConstantForce,
+ &pad->rumble_props, &pad->rumble_iface[0], NULL) != DI_OK)
+ RARCH_WARN("[DINPUT]: Strong rumble unavailable.\n");
+
+ if (IDirectInputDevice8_CreateEffect(pad->joypad, &GUID_ConstantForce,
+ &pad->rumble_props, &pad->rumble_iface[1], NULL) != DI_OK)
+ RARCH_WARN("[DINPUT]: Weak rumble unavailable.\n");
+#endif
+}
+
+static BOOL CALLBACK enum_axes_cb(
+ const DIDEVICEOBJECTINSTANCE *inst, void *p)
+{
+ DIPROPRANGE range;
+ LPDIRECTINPUTDEVICE8 joypad = (LPDIRECTINPUTDEVICE8)p;
+
+ range.diph.dwSize = sizeof(DIPROPRANGE);
+ range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ range.diph.dwHow = DIPH_BYID;
+ range.diph.dwObj = inst->dwType;
+ range.lMin = -0x7fff;
+ range.lMax = 0x7fff;
+
+ IDirectInputDevice8_SetProperty(joypad, DIPROP_RANGE, &range.diph);
+
+ return DIENUM_CONTINUE;
+}
+
+static const char *dinput_joypad_name(unsigned port)
+{
+ if (port < MAX_USERS)
+ return g_pads[port].joy_name;
+ return NULL;
+}
+
+static int16_t dinput_joypad_button_state(
+ const struct dinput_joypad_data *pad,
+ uint16_t joykey)
+{
+ unsigned hat_dir = GET_HAT_DIR(joykey);
+
+ if (hat_dir)
+ {
+ unsigned h = GET_HAT(joykey);
+
+ /* 4 is number of hats */
+ if (h < 4)
+ {
+ unsigned pov = pad->joy_state.rgdwPOV[h];
+ switch (hat_dir)
+ {
+ case HAT_UP_MASK:
+ {
+ static const unsigned check1 = (JOY_POVRIGHT/2);
+ static const unsigned check2 = (JOY_POVLEFT+JOY_POVRIGHT/2);
+ return (
+ (pov == JOY_POVFORWARD) ||
+ (pov == check1) ||
+ (pov == check2)
+ );
+ }
+ case HAT_RIGHT_MASK:
+ {
+ static const unsigned check1 = (JOY_POVRIGHT/2);
+ static const unsigned check2 = (JOY_POVRIGHT+JOY_POVRIGHT/2);
+ return (
+ (pov == JOY_POVRIGHT) ||
+ (pov == check1) ||
+ (pov == check2)
+ );
+ }
+ case HAT_DOWN_MASK:
+ {
+ static const unsigned check1 = (JOY_POVRIGHT+JOY_POVRIGHT/2);
+ static const unsigned check2 = (JOY_POVBACKWARD+JOY_POVRIGHT/2);
+ return
+ (
+ (pov == JOY_POVBACKWARD) ||
+ (pov == check1) ||
+ (pov == check2)
+ );
+ }
+ case HAT_LEFT_MASK:
+ {
+ static const unsigned check1 = (JOY_POVBACKWARD+JOY_POVRIGHT/2);
+ static const unsigned check2 = (JOY_POVLEFT+JOY_POVRIGHT/2);
+
+ return
+ (
+ (pov == JOY_POVLEFT) ||
+ (pov == check1) ||
+ (pov == check2)
+ );
+ }
+ default:
+ break;
+ }
+ }
+ /* hat requested and no hat button down */
+ }
+ else if (joykey < ARRAY_SIZE_RGB_BUTTONS)
+ if (pad->joy_state.rgbButtons[joykey])
+ return 1;
+ return 0;
+}
+
+static int16_t dinput_joypad_axis_state(
+ const struct dinput_joypad_data *pad,
+ uint32_t joyaxis)
+{
+ int val = 0;
+ int axis = -1;
+ bool is_neg = false;
+ bool is_pos = false;
+
+ if (AXIS_NEG_GET(joyaxis) <= 7)
+ {
+ axis = AXIS_NEG_GET(joyaxis);
+ is_neg = true;
+ }
+ else if (AXIS_POS_GET(joyaxis) <= 7)
+ {
+ axis = AXIS_POS_GET(joyaxis);
+ is_pos = true;
+ }
+ else
+ return 0;
+
+ switch (axis)
+ {
+ case 0:
+ val = pad->joy_state.lX;
+ break;
+ case 1:
+ val = pad->joy_state.lY;
+ break;
+ case 2:
+ val = pad->joy_state.lZ;
+ break;
+ case 3:
+ val = pad->joy_state.lRx;
+ break;
+ case 4:
+ val = pad->joy_state.lRy;
+ break;
+ case 5:
+ val = pad->joy_state.lRz;
+ break;
+ case 6:
+ case 7:
+ val = pad->joy_state.rglSlider[axis - 6];
+ break;
+ }
+
+ if (is_neg && val > 0)
+ return 0;
+ else if (is_pos && val < 0)
+ return 0;
+ return val;
+}
+
+static int16_t dinput_joypad_button(unsigned port, uint16_t joykey)
+{
+ const struct dinput_joypad_data *pad = &g_pads[port];
+ if (!pad || !pad->joypad)
+ return 0;
+ return dinput_joypad_button_state(pad, joykey);
+}
+
+static int16_t dinput_joypad_axis(unsigned port, uint32_t joyaxis)
+{
+ const struct dinput_joypad_data *pad = &g_pads[port];
+ if (!pad || !pad->joypad)
+ return 0;
+ return dinput_joypad_axis_state(pad, joyaxis);
+}
+
+static int16_t dinput_joypad_state(
+ rarch_joypad_info_t *joypad_info,
+ const struct retro_keybind *binds,
+ unsigned port)
+{
+ unsigned i;
+ int16_t ret = 0;
+ uint16_t port_idx = joypad_info->joy_idx;
+ const struct dinput_joypad_data *pad = &g_pads[port_idx];
+
+ if (!pad || !pad->joypad)
+ return 0;
+ if (port_idx >= DEFAULT_MAX_PADS)
+ return 0;
+
+ for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
+ {
+ /* Auto-binds are per joypad, not per user. */
+ const uint64_t joykey = (binds[i].joykey != NO_BTN)
+ ? binds[i].joykey : joypad_info->auto_binds[i].joykey;
+ const uint32_t joyaxis = (binds[i].joyaxis != AXIS_NONE)
+ ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
+ if (
+ (uint16_t)joykey != NO_BTN
+ && dinput_joypad_button_state(
+ pad, (uint16_t)joykey))
+ ret |= ( 1 << i);
+ else if (joyaxis != AXIS_NONE &&
+ ((float)abs(dinput_joypad_axis_state(pad, joyaxis))
+ / 0x8000) > joypad_info->axis_threshold)
+ ret |= (1 << i);
+ }
+
+ return ret;
+}
+
+static bool dinput_joypad_query_pad(unsigned port)
+{
+ return port < MAX_USERS && g_pads[port].joypad;
+}
+
+bool dinput_joypad_set_rumble(unsigned port,
+ enum retro_rumble_effect type, uint16_t strength)
+{
+ int i = type == RETRO_RUMBLE_STRONG ? 1 : 0;
+
+ if (port >= g_joypad_cnt || !g_pads[port].rumble_iface[i])
+ return false;
+
+ if (strength)
+ {
+ g_pads[port].rumble_props.dwGain =
+ (DWORD)((double)strength / 65535.0 * (double)DI_FFNOMINALMAX);
+ IDirectInputEffect_SetParameters(g_pads[port].rumble_iface[i],
+ &g_pads[port].rumble_props, DIEP_GAIN | DIEP_START);
+ }
+ else
+ IDirectInputEffect_Stop(g_pads[port].rumble_iface[i]);
+
+ return true;
+}
+
+#endif
diff --git a/input/drivers_joypad/xinput_joypad.c b/input/drivers_joypad/xinput_joypad.c
index 600e69d8fd..43412ea3e8 100644
--- a/input/drivers_joypad/xinput_joypad.c
+++ b/input/drivers_joypad/xinput_joypad.c
@@ -108,6 +108,8 @@ static const uint16_t button_index_to_bitmap_code[] = {
#endif
};
+#include "xinput_joypad_inl.h"
+
static INLINE int pad_index_to_xuser_index(unsigned pad)
{
#ifdef HAVE_DINPUT
@@ -118,11 +120,6 @@ static INLINE int pad_index_to_xuser_index(unsigned pad)
#endif
}
-/* Generic 'XInput' instead of 'Xbox 360', because
- * there are some other non-Xbox third party PC
- * controllers */
-static const char XBOX_CONTROLLER_NAME[] = "XInput Controller";
-
static const char *xinput_joypad_name(unsigned pad)
{
#ifdef HAVE_DINPUT
@@ -130,6 +127,10 @@ static const char *xinput_joypad_name(unsigned pad)
* to get a name from the device itself */
return dinput_joypad.name(pad);
#else
+ /* Generic 'XInput' instead of 'Xbox 360', because
+ * there are some other non-Xbox third party PC
+ * controllers */
+ static const char XBOX_CONTROLLER_NAME[] = "XInput Controller";
if (pad_index_to_xuser_index(pad) < 0)
return NULL;
@@ -140,38 +141,6 @@ static const char *xinput_joypad_name(unsigned pad)
#endif
}
-#if defined(HAVE_DYNAMIC) && !defined(__WINRT__)
-static bool load_xinput_dll(void)
-{
- const char *version = "1.4";
- /* Find the correct path to load the DLL from.
- * Usually this will be from the system directory,
- * but occasionally a user may wish to use a third-party
- * wrapper DLL (such as x360ce); support these by checking
- * the working directory first.
- *
- * No need to check for existance as we will be checking dylib_load's
- * success anyway.
- */
-
- g_xinput_dll = dylib_load("xinput1_4.dll");
- if (!g_xinput_dll)
- {
- g_xinput_dll = dylib_load("xinput1_3.dll");
- version = "1.3";
- }
-
- if (!g_xinput_dll)
- {
- RARCH_ERR("[XInput]: Failed to load XInput, ensure DirectX and controller drivers are up to date.\n");
- return false;
- }
-
- RARCH_LOG("[XInput]: Found XInput v%s.\n", version);
- return true;
-}
-#endif
-
static bool xinput_joypad_init(void *data)
{
unsigned i, j;
@@ -354,33 +323,6 @@ static void xinput_joypad_destroy(void)
#endif
}
-static int16_t xinput_joypad_button_state(
- unsigned xuser, uint16_t btn_word,
- unsigned port, uint16_t joykey)
-{
- unsigned hat_dir = GET_HAT_DIR(joykey);
-
- if (hat_dir)
- {
- switch (hat_dir)
- {
- case HAT_UP_MASK:
- return (btn_word & XINPUT_GAMEPAD_DPAD_UP);
- case HAT_DOWN_MASK:
- return (btn_word & XINPUT_GAMEPAD_DPAD_DOWN);
- case HAT_LEFT_MASK:
- return (btn_word & XINPUT_GAMEPAD_DPAD_LEFT);
- case HAT_RIGHT_MASK:
- return (btn_word & XINPUT_GAMEPAD_DPAD_RIGHT);
- default:
- break;
- }
- /* hat requested and no hat button down */
- }
- else if (joykey < g_xinput_num_buttons)
- return (btn_word & button_index_to_bitmap_code[joykey]);
- return 0;
-}
static int16_t xinput_joypad_button(unsigned port, uint16_t joykey)
{
@@ -396,60 +338,6 @@ static int16_t xinput_joypad_button(unsigned port, uint16_t joykey)
return xinput_joypad_button_state(xuser, btn_word, port, joykey);
}
-static int16_t xinput_joypad_axis_state(
- XINPUT_GAMEPAD *pad,
- unsigned port, uint32_t joyaxis)
-{
- int16_t val = 0;
- int axis = -1;
- bool is_neg = false;
- bool is_pos = false;
- /* triggers (axes 4,5) cannot be negative */
- if (AXIS_NEG_GET(joyaxis) <= 3)
- {
- axis = AXIS_NEG_GET(joyaxis);
- is_neg = true;
- }
- else if (AXIS_POS_GET(joyaxis) <= 5)
- {
- axis = AXIS_POS_GET(joyaxis);
- is_pos = true;
- }
- else
- return 0;
-
- switch (axis)
- {
- case 0:
- val = pad->sThumbLX;
- break;
- case 1:
- val = pad->sThumbLY;
- break;
- case 2:
- val = pad->sThumbRX;
- break;
- case 3:
- val = pad->sThumbRY;
- break;
- case 4:
- val = pad->bLeftTrigger * 32767 / 255;
- break; /* map 0..255 to 0..32767 */
- case 5:
- val = pad->bRightTrigger * 32767 / 255;
- break;
- }
-
- if (is_neg && val > 0)
- return 0;
- else if (is_pos && val < 0)
- return 0;
- /* Clamp to avoid overflow error. */
- else if (val == -32768)
- return -32767;
- return val;
-}
-
static int16_t xinput_joypad_axis(unsigned port, uint32_t joyaxis)
{
int xuser = pad_index_to_xuser_index(port);
diff --git a/input/drivers_joypad/xinput_joypad_inl.h b/input/drivers_joypad/xinput_joypad_inl.h
new file mode 100644
index 0000000000..0687515860
--- /dev/null
+++ b/input/drivers_joypad/xinput_joypad_inl.h
@@ -0,0 +1,139 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2016 - Daniel De Matteis
+ * Copyright (C) 2016-2019 - Brad Parker
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#ifndef __XINPUT_JOYPAD_INL_H
+#define __XINPUT_JOYPAD_INL_H
+
+#include
+#include
+#include
+
+#if defined(HAVE_DYNAMIC) && !defined(__WINRT__)
+static bool load_xinput_dll(void)
+{
+ const char *version = "1.4";
+ /* Find the correct path to load the DLL from.
+ * Usually this will be from the system directory,
+ * but occasionally a user may wish to use a third-party
+ * wrapper DLL (such as x360ce); support these by checking
+ * the working directory first.
+ *
+ * No need to check for existance as we will be checking dylib_load's
+ * success anyway.
+ */
+
+ g_xinput_dll = dylib_load("xinput1_4.dll");
+ if (!g_xinput_dll)
+ {
+ g_xinput_dll = dylib_load("xinput1_3.dll");
+ version = "1.3";
+ }
+
+ if (!g_xinput_dll)
+ {
+ RARCH_ERR("[XInput]: Failed to load XInput, ensure DirectX and controller drivers are up to date.\n");
+ return false;
+ }
+
+ RARCH_LOG("[XInput]: Found XInput v%s.\n", version);
+ return true;
+}
+#endif
+
+static int16_t xinput_joypad_button_state(
+ unsigned xuser, uint16_t btn_word,
+ unsigned port, uint16_t joykey)
+{
+ unsigned hat_dir = GET_HAT_DIR(joykey);
+
+ if (hat_dir)
+ {
+ switch (hat_dir)
+ {
+ case HAT_UP_MASK:
+ return (btn_word & XINPUT_GAMEPAD_DPAD_UP);
+ case HAT_DOWN_MASK:
+ return (btn_word & XINPUT_GAMEPAD_DPAD_DOWN);
+ case HAT_LEFT_MASK:
+ return (btn_word & XINPUT_GAMEPAD_DPAD_LEFT);
+ case HAT_RIGHT_MASK:
+ return (btn_word & XINPUT_GAMEPAD_DPAD_RIGHT);
+ default:
+ break;
+ }
+ /* hat requested and no hat button down */
+ }
+ else if (joykey < g_xinput_num_buttons)
+ return (btn_word & button_index_to_bitmap_code[joykey]);
+ return 0;
+}
+
+static int16_t xinput_joypad_axis_state(
+ XINPUT_GAMEPAD *pad,
+ unsigned port, uint32_t joyaxis)
+{
+ int16_t val = 0;
+ int axis = -1;
+ bool is_neg = false;
+ bool is_pos = false;
+ /* triggers (axes 4,5) cannot be negative */
+ if (AXIS_NEG_GET(joyaxis) <= 3)
+ {
+ axis = AXIS_NEG_GET(joyaxis);
+ is_neg = true;
+ }
+ else if (AXIS_POS_GET(joyaxis) <= 5)
+ {
+ axis = AXIS_POS_GET(joyaxis);
+ is_pos = true;
+ }
+ else
+ return 0;
+
+ switch (axis)
+ {
+ case 0:
+ val = pad->sThumbLX;
+ break;
+ case 1:
+ val = pad->sThumbLY;
+ break;
+ case 2:
+ val = pad->sThumbRX;
+ break;
+ case 3:
+ val = pad->sThumbRY;
+ break;
+ case 4:
+ val = pad->bLeftTrigger * 32767 / 255;
+ break; /* map 0..255 to 0..32767 */
+ case 5:
+ val = pad->bRightTrigger * 32767 / 255;
+ break;
+ }
+
+ if (is_neg && val > 0)
+ return 0;
+ else if (is_pos && val < 0)
+ return 0;
+ /* Clamp to avoid overflow error. */
+ else if (val == -32768)
+ return -32767;
+ return val;
+}
+
+#endif