diff --git a/gfx/fonts/d3d_font.c b/gfx/fonts/d3d_font.c index ae150b9ec2..71b8e8f522 100644 --- a/gfx/fonts/d3d_font.c +++ b/gfx/fonts/d3d_font.c @@ -29,7 +29,8 @@ static const d3d_font_renderer_t *d3d_font_backends[] = { const d3d_font_renderer_t *d3d_font_init_first(void *data, const char *font_path, unsigned font_size) { - for (unsigned i = 0; i < ARRAY_SIZE(d3d_font_backends); i++) + unsigned i; + for (i = 0; i < ARRAY_SIZE(d3d_font_backends); i++) { if (d3d_font_backends[i]->init(data, font_path, font_size)) return d3d_font_backends[i]; diff --git a/input/dinput.c b/input/dinput.c index 73335efa5b..72bc4af0b6 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -611,49 +611,63 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p) return DIENUM_CONTINUE; } -// TODO: Use a better way of detecting dual XInput/DInput pads. This current method -// will not work correctly for third-party controllers or future MS pads (Xbox One?). -// An example of this is provided in the DX SDK, which advises "Enum each PNP device -// using WMI and check each device ID to see if it contains "IG_"". Unfortunately the -// example code is a horrible unsightly mess. -static const char* const XINPUT_PAD_NAMES[] = -{ - "XBOX 360 For Windows", - "Controller (Gamepad for Xbox 360)", - "Controller (XBOX 360 For Windows)", - "Controller (Xbox 360 Wireless Receiver for Windows)", - "Controller (Xbox wireless receiver for windows)", - "XBOX 360 For Windows (Controller)", - "Xbox 360 Wireless Receiver", - "Xbox 360 Wireless Controller", - "Xbox Receiver for Windows (Wireless Controller)", - "Xbox wireless receiver for windows (Controller)", - "Gamepad F310 (Controller)", - "Controller (Gamepad F310)", - "Wireless Gamepad F710 (Controller)", - "Controller (Batarang wired controller (XBOX))", - "Afterglow Gamepad for Xbox 360 (Controller)" - "Controller (Rumble Gamepad F510)", - "Controller (Wireless Gamepad F710)", - "Controller (Xbox 360 Wireless Receiver for Windows)", - "Controller (Xbox wireless receiver for windows)", - "Controller (XBOX360 GAMEPAD)", - "MadCatz GamePad", - "MadCatz GamePad (Controller)", - "Controller (MadCatz GamePad)", - "Controller (GPX Gamepad)", - NULL +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 }; -static bool name_is_xinput_pad(const char* name) +// Based on SDL2's implementation +static bool guid_is_xinput_device(const GUID* product_guid) { + PRAWINPUTDEVICELIST raw_devs = NULL; + unsigned num_raw_devs = 0; unsigned i; - for (i = 0; XINPUT_PAD_NAMES[i]; i++) + + // Check for well known XInput device GUIDs, thereby removing the need for the IG_ check. + // This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. + for (i = 0; i < ARRAY_SIZE(common_xinput_guids); ++i) { - if (strcasecmp(name, XINPUT_PAD_NAMES[i]) == 0) + if (memcmp(product_guid, &common_xinput_guids[i], sizeof(GUID)) == 0) return true; } + /* Go through RAWINPUT (WinXP and later) to find HID devices. */ + if (!raw_devs) + { + if ((GetRawInputDeviceList(NULL, &num_raw_devs, sizeof (RAWINPUTDEVICELIST)) == -1) || (!num_raw_devs)) + return false; + + raw_devs = (PRAWINPUTDEVICELIST) malloc(sizeof(RAWINPUTDEVICELIST) * num_raw_devs); + if (!raw_devs) + return false; + + if (GetRawInputDeviceList(raw_devs, &num_raw_devs, sizeof (RAWINPUTDEVICELIST)) == -1) + { + free(raw_devs); + raw_devs = NULL; + return false; + } + } + + for (i = 0; i < num_raw_devs; i++) + { + RID_DEVICE_INFO rdi; + char devName[128]; + UINT rdiSize = sizeof(rdi); + UINT nameSize = sizeof(devName); + + rdi.cbSize = sizeof (rdi); + if ((raw_devs[i].dwType == RIM_TYPEHID) && + (GetRawInputDeviceInfoA(raw_devs[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) && + (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)product_guid->Data1)) && + (GetRawInputDeviceInfoA(raw_devs[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) && + (strstr(devName, "IG_") != NULL) ) + { + return true; + } + } + return false; } @@ -679,7 +693,8 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) g_pads[g_joypad_cnt].joy_name = strdup(inst->tszProductName); #ifdef HAVE_WINXINPUT - bool is_xinput_pad = g_xinput_block_pads && name_is_xinput_pad(inst->tszProductName); + //bool is_xinput_pad = g_xinput_block_pads && name_is_xinput_pad(inst->tszProductName); + bool is_xinput_pad = g_xinput_block_pads && guid_is_xinput_device(&inst->guidProduct); if (is_xinput_pad) { diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index 0f70ac3541..82a3c9672f 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -92,7 +92,7 @@ typedef struct extern int g_xinput_pad_indexes[MAX_PLAYERS]; extern bool g_xinput_block_pads; -// For xinput1_3.dll +// For xinput1_n.dll static HINSTANCE g_winxinput_dll; // Function pointer, to be assigned with GetProcAddress @@ -141,8 +141,6 @@ const char* winxinput_joypad_name (unsigned pad) return XBOX_CONTROLLER_NAMES[xplayer]; } - - static bool winxinput_joypad_init(void) { unsigned i, autoconf_pad; @@ -240,7 +238,6 @@ static bool winxinput_joypad_init(void) } return true; - } static bool winxinput_joypad_query_pad(unsigned pad) @@ -261,6 +258,7 @@ static void winxinput_joypad_destroy(void) FreeLibrary(g_winxinput_dll); g_winxinput_dll = NULL; g_XInputGetStateEx = NULL; + g_XInputSetState = NULL; dinput_joypad.destroy(); g_xinput_block_pads = false;