From f5454cd4462492ecadcd58dda616d7f993b40e39 Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Fri, 23 Aug 2013 13:09:59 +0100 Subject: [PATCH 1/6] Initial xinput support, fix msvc build --- Makefile.win | 10 +- frontend/frontend_context.c | 3 + input/dinput.c | 25 +- input/input_common.c | 3 + input/input_common.h | 1 + input/sdl_joypad.c | 29 +- input/winxinput_joypad.c | 361 ++++++++++++++++++++++ msvc/msvc-2010/RetroArch-msvc2010.vcxproj | 10 +- 8 files changed, 434 insertions(+), 8 deletions(-) create mode 100644 input/winxinput_joypad.c diff --git a/Makefile.win b/Makefile.win index 71036ccf47..df300fb4f7 100644 --- a/Makefile.win +++ b/Makefile.win @@ -44,7 +44,8 @@ JOBJ := conf/config_file.o \ compat/compat.o \ file_path.o \ tools/input_common_joyconfig.o \ - input/dinput.o + input/dinput.o \ + input/winxinput_joypad.o CC = gcc CXX = g++ @@ -63,6 +64,8 @@ HAVE_THREADS = 1 HAVE_RGUI = 1 DYNAMIC = 1 +USE_WINXINPUT = 1 + ifeq ($(SLIM),) HAVE_SDL = 1 HAVE_SDL_IMAGE = 1 @@ -212,6 +215,11 @@ ifeq ($(HAVE_PYTHON), 1) OBJ += gfx/py_state/py_state.o endif +ifeq ($(USE_WINXINPUT), 1) + DEFINES += -DUSE_WINXINPUT + OBJ += input/winxinput_joypad.o +endif + ifeq ($(HAVE_DINPUT), 1) LIBS += -ldinput8 -ldxguid -lole32 DEFINES += -DHAVE_DINPUT diff --git a/frontend/frontend_context.c b/frontend/frontend_context.c index 24fa1dd161..93fd0260b0 100644 --- a/frontend/frontend_context.c +++ b/frontend/frontend_context.c @@ -36,12 +36,15 @@ static const frontend_ctx_driver_t *frontend_ctx_drivers[] = { #if defined(IOS) || defined(OSX) &frontend_ctx_apple, #endif + NULL // zero length array is not valid }; const frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident) { for (unsigned i = 0; i < sizeof(frontend_ctx_drivers) / sizeof(frontend_ctx_drivers[0]); i++) { + if (!frontend_ctx_drivers[i]) // could be the dummy NULL + continue; if (strcmp(frontend_ctx_drivers[i]->ident, ident) == 0) return frontend_ctx_drivers[i]; } diff --git a/input/dinput.c b/input/dinput.c index 024f323ba9..620d3e645a 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -386,6 +386,8 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p) return DIENUM_CONTINUE; } +extern const LPCTSTR XBOX_PAD_NAMES_TO_REJECT[]; + static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) { (void)p; @@ -399,7 +401,28 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) #else if (FAILED(IDirectInput8_CreateDevice(g_ctx, &inst->guidInstance, pad, NULL))) #endif - return DIENUM_CONTINUE; + return DIENUM_CONTINUE; + +#ifdef USE_WINXINPUT + // Reject xbox 360 controllers, the xinput driver will take care of them + DIDEVICEINSTANCE info; + ZeroMemory(&info, sizeof(DIDEVICEINSTANCE)); + info.dwSize = sizeof(DIDEVICEINSTANCE); + IDirectInputDevice8_GetDeviceInfo(*pad, &info); + + unsigned test_name_index = 0; + while(1) + { + if (XBOX_PAD_NAMES_TO_REJECT[test_name_index] == NULL) + break; + if (lstrcmpi(info.tszProductName, XBOX_PAD_NAMES_TO_REJECT[test_name_index]) == 0) + { + RARCH_LOG("dinput: Rejected XInput controller \"%s\"", info.tszProductName); + return DIENUM_CONTINUE; + } + ++test_name_index; + } +#endif IDirectInputDevice8_SetDataFormat(*pad, &c_dfDIJoystick2); IDirectInputDevice8_SetCooperativeLevel(*pad, (HWND)driver.video_window, diff --git a/input/input_common.c b/input/input_common.c index 12be6eaf76..cc7ab96e80 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -41,6 +41,9 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { #ifndef IS_RETROLAUNCH +#ifdef USE_WINXINPUT + &winxinput_joypad, +#endif #ifdef HAVE_DINPUT &dinput_joypad, #endif diff --git a/input/input_common.h b/input/input_common.h index 2ce912e98a..dc118ff4e1 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -93,6 +93,7 @@ const char *input_joypad_name(const rarch_joypad_driver_t *driver, unsigned joyp extern const rarch_joypad_driver_t dinput_joypad; extern const rarch_joypad_driver_t linuxraw_joypad; +extern const rarch_joypad_driver_t winxinput_joypad; // Named as such to avoid confusion with xb1/360 port code extern const rarch_joypad_driver_t sdl_joypad; diff --git a/input/sdl_joypad.c b/input/sdl_joypad.c index 812936be56..0ed9411be8 100644 --- a/input/sdl_joypad.c +++ b/input/sdl_joypad.c @@ -39,6 +39,8 @@ static void sdl_joypad_destroy(void) memset(g_pads, 0, sizeof(g_pads)); } +extern const LPCTSTR XBOX_PAD_NAMES_TO_REJECT[]; + static bool sdl_joypad_init(void) { if (SDL_Init(SDL_INIT_JOYSTICK) < 0) @@ -54,9 +56,32 @@ static bool sdl_joypad_init(void) pad->joypad = SDL_JoystickOpen(i); if (!pad->joypad) { - RARCH_ERR("Couldn't open SDL joystick #%u.\n", i); - goto error; + RARCH_ERR("Couldn't open SDL joystick #%u.\n", i); + goto error; } + + + #ifdef USE_WINXINPUT + // Reject xbox 360 controllers, the xinput driver will take care of them. + unsigned test_name_index = 0; + while(1) + { + if (XBOX_PAD_NAMES_TO_REJECT[test_name_index] == NULL) + break; + if (lstrcmpi(SDL_JoystickName(i), XBOX_PAD_NAMES_TO_REJECT[test_name_index]) == 0) + { + RARCH_LOG("sdl joypad: Rejected XInput controller \"%s\"", SDL_JoystickName(i)); + pad->joypad = NULL; pad->num_axes = 0; pad->num_buttons = 0; pad->num_hats = 0; + + goto continue_after_xinput_rejection; + } + ++test_name_index; + } + #endif + + continue_after_xinput_rejection: + + // RARCH_LOG("Opened Joystick: %s (#%u).\n", SDL_JoystickName(i), i); diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c new file mode 100644 index 0000000000..0310b24c5b --- /dev/null +++ b/input/winxinput_joypad.c @@ -0,0 +1,361 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2013 - Hans-Kristian Arntzen + * + * 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 . + */ + +// Support 360 controllers on Windows. +// Said controllers do show under DInput but they have limitations in this mode; +// The triggers are combined rather than seperate and it is not possible to use +// the guide button. + +// Some wrappers for other controllers also simulate xinput (as it is easier to implement) +// so this may be useful for those also. + +// Note: if rumble is ever added (for psx and n64 cores), add rumble support to this +// as well as dinput. +#include "input_common.h" + +#include "../general.h" +#include "../boolean.h" + +#include +#include +#include + +//#include + +// There is no need to require the xinput headers and libs since +// we shall be dynamically loading them anyway. But first check that +// it hasn't been included anyway. +// official and mingw xinput headers have different include guards +#if ((!_XINPUT_H_) && (!__WINE_XINPUT_H)) + + #define XINPUT_GAMEPAD_DPAD_UP 0x0001 + #define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 + #define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 + #define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 + #define XINPUT_GAMEPAD_START 0x0010 + #define XINPUT_GAMEPAD_BACK 0x0020 + #define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 + #define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 + #define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 + #define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 + #define XINPUT_GAMEPAD_A 0x1000 + #define XINPUT_GAMEPAD_B 0x2000 + #define XINPUT_GAMEPAD_X 0x4000 + #define XINPUT_GAMEPAD_Y 0x8000 + + typedef struct + { + WORD wButtons; + BYTE bLeftTrigger; + BYTE bRightTrigger; + SHORT sThumbLX; + SHORT sThumbLY; + SHORT sThumbRX; + SHORT sThumbRY; + } XINPUT_GAMEPAD; + + typedef struct + { + DWORD dwPacketNumber; + XINPUT_GAMEPAD Gamepad; + } XINPUT_STATE; + +#endif + +// Guide constant is not officially documented +#define XINPUT_GAMEPAD_GUIDE 0x0400 + +#ifndef ERROR_DEVICE_NOT_CONNECTED + #define ERROR_DEVICE_NOT_CONNECTED 1167 +#endif + +// To load xinput1_3.dll +static HINSTANCE g_winxinput_dll; + +// Function pointer, to be assigned with GetProcAddress +typedef __stdcall DWORD (*XInputGetStateEx_t)(DWORD, XINPUT_STATE*); +static XInputGetStateEx_t g_XInputGetStateEx; + +// Guide button may or may not be available, +// but if it is available +static bool g_winxinput_guide_button_supported; + +typedef struct +{ + XINPUT_STATE xstate; + bool connected; +} winxinput_joypad_state; + +static winxinput_joypad_state g_winxinput_states[4]; + +static bool winxinput_joypad_init(void) +{ + g_winxinput_dll = NULL; + + // 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 LoadLibrary's + // success anyway. + TCHAR dll_path[MAX_PATH]; + strcpy(dll_path, "xinput1_3.dll"); + g_winxinput_dll = LoadLibrary(dll_path); + if (!g_winxinput_dll) + { + // Loading from working dir failed, try to load from system. + GetSystemDirectory(dll_path, sizeof(dll_path)); + strcpy(dll_path, "xinput1_3.dll"); + g_winxinput_dll = LoadLibrary(dll_path); + + if (!g_winxinput_dll) + { + RARCH_ERR("Failed to init XInput, ensure DirectX and controller drivers are up to date.\n"); + return false; // DLL does not exist or is invalid + } + + } + + // If we get here then an xinput DLL is correctly loaded. + // First try to load ordinal 100 (XInputGetStateEx). + // Cast to make C++ happy. + g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (LPCSTR)100); + g_winxinput_guide_button_supported = true; + + if (!g_XInputGetStateEx) + { + // no ordinal 100. (old version of x360ce perhaps). Load the ordinary XInputGetState, + // at the cost of losing guide button support. + g_winxinput_guide_button_supported = false; + g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); + if (!g_XInputGetStateEx) + { + RARCH_ERR("Failed to init XInput.\n"); + return false; // DLL was loaded but did not contain the correct function. + } + } + + // zero out the states + for (unsigned i = 0; i < 4; ++i) + ZeroMemory(&g_winxinput_states[i], sizeof(winxinput_joypad_state)); + + // Do a dummy poll to check which controllers are connected. + XINPUT_STATE dummy_state; + for (unsigned i = 0; i < 4; ++i) + { + g_winxinput_states[i].connected = !(g_XInputGetStateEx(i, &dummy_state) == ERROR_DEVICE_NOT_CONNECTED); + if (g_winxinput_states[i].connected) + RARCH_LOG("Found XInput controller, player #%u\n", i); + } + + + return true; +} + +static bool winxinput_joypad_query_pad(unsigned pad) +{ + if (pad >= 4) + return false; + else + return g_winxinput_states[pad].connected; +} + +static void winxinput_joypad_destroy(void) +{ + for (unsigned i = 0; i < 4; ++i) + ZeroMemory(&g_winxinput_states[i], sizeof(winxinput_joypad_state)); + + FreeLibrary(g_winxinput_dll); + g_winxinput_dll = NULL; + g_XInputGetStateEx = NULL; +} + +// Buttons are provided by XInput as bits of a uint16. +// Map from button index (0..10) to mask to AND against. +// dpad is handled seperately. +// Order: +// a, b, x, y, leftbump, rightbump, back, start, leftstick, rightstick, guide. +static const WORD button_index_to_bitmap_code[] = { + 0x1000, 0x2000, 0x4000, 0x8000, 0x0100, 0x0200, 0x0020, 0x0010, + 0x0040, 0x0080, 0x0400 +}; + +static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey) +{ + if (joykey == NO_BTN) + return false; + + if (!(g_winxinput_states[port_num].connected)) + return false; + + + + uint16_t btn_word = g_winxinput_states[port_num].xstate.Gamepad.wButtons; + + + if (GET_HAT_DIR(joykey)) + { + + switch (GET_HAT_DIR(joykey)) + { + 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; + } + + return false; // hat requested and no hat button down + } + else + { + // non-hat button + unsigned num_buttons = g_winxinput_guide_button_supported ? 11 : 10; + + if (joykey >= num_buttons) + return false; + else + return btn_word & button_index_to_bitmap_code[joykey]; + } + + return false; + +} +//#include +static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) +{ + //printf("Requested axis: %u\n", joyaxis); + if (joyaxis == AXIS_NONE) + return 0; + + if (!(g_winxinput_states[port_num].connected)) + return 0; + + /*switch (joyaxis) + { + case 0: return(g_winxinput_states[port_num].xstate.Gamepad.sThumbLX); + case 1: return (g_winxinput_states[port_num].xstate.Gamepad.sThumbLX); + case 2: return 0; + case 3: return 0; //do axes now + case 4: return 0; + case 5: return 0; + default: return 0; + }*/ + + + int16_t val = 0; + int axis = -1; + + bool is_neg = false; + bool is_pos = false; + + 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; + } + + XINPUT_GAMEPAD* pad = &(g_winxinput_states[port_num].xstate.Gamepad); + 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; + case 5: val = pad->bRightTrigger * 32767 / 255; break; + } + + if (is_neg && val > 0) + val = 0; + else if (is_pos && val < 0) + val = 0; + + return val; + +} + +static void winxinput_joypad_poll(void) +{ + for (unsigned i = 0; i < 4; ++i) + if (g_XInputGetStateEx(i, &(g_winxinput_states[i].xstate)) == ERROR_DEVICE_NOT_CONNECTED) + g_winxinput_states[i].connected = false; +} + +static const char* const XBOX_CONTROLLER_NAMES[4] = +{ + "Xbox 360 Controller (Player 1)", + "Xbox 360 Controller (Player 2)", + "Xbox 360 Controller (Player 3)", + "Xbox 360 Controller (Player 4)" +}; + +const char* winxinput_joypad_name (unsigned pad) +{ + if (pad > 3) + return NULL; + else + return XBOX_CONTROLLER_NAMES[pad]; +} + + +const rarch_joypad_driver_t winxinput_joypad = { + winxinput_joypad_init, + winxinput_joypad_query_pad, + winxinput_joypad_destroy, + winxinput_joypad_button, + winxinput_joypad_axis, + winxinput_joypad_poll, + winxinput_joypad_name, + "winxinput", +}; + +// A list of names for other (dinput) drivers to reject. +const LPCTSTR XBOX_PAD_NAMES_TO_REJECT[] = +{ + "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 Receiver for Windows (Wireless Controller)", + "Xbox wireless receiver for windows (Controller)", + NULL +}; + + +/* +typedef struct rarch_joypad_driver +{ + bool (*init)(void); + bool (*query_pad)(unsigned); + void (*destroy)(void); + bool (*button)(unsigned, uint16_t); + int16_t (*axis)(unsigned, uint32_t); + void (*poll)(void); + const char *(*name)(unsigned); + + const char *ident; +} rarch_joypad_driver_t; + +*/ \ No newline at end of file diff --git a/msvc/msvc-2010/RetroArch-msvc2010.vcxproj b/msvc/msvc-2010/RetroArch-msvc2010.vcxproj index 17c46dec6d..3a7d4085ad 100644 --- a/msvc/msvc-2010/RetroArch-msvc2010.vcxproj +++ b/msvc/msvc-2010/RetroArch-msvc2010.vcxproj @@ -88,7 +88,7 @@ Level3 Disabled - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp @@ -108,7 +108,7 @@ Level3 Disabled - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp @@ -130,7 +130,7 @@ MaxSpeed true true - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp @@ -154,7 +154,7 @@ MaxSpeed true true - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_ZLIB;WANT_MINIZ;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_ZLIB;WANT_MINIZ;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp @@ -250,6 +250,8 @@ + + From 3370684a06a9b9d69ab549110eb522d196a02815 Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Sun, 25 Aug 2013 17:17:23 +0100 Subject: [PATCH 2/6] Improved XInput support, misc tweaks --- frontend/frontend_context.c | 2 +- input/dinput.c | 57 +++++--- input/sdl_joypad.c | 29 +--- input/winxinput_joypad.c | 188 ++++++++++++-------------- msvc/msvc-2010/RetroArch-msvc2010.sln | 20 +++ 5 files changed, 152 insertions(+), 144 deletions(-) create mode 100644 msvc/msvc-2010/RetroArch-msvc2010.sln diff --git a/frontend/frontend_context.c b/frontend/frontend_context.c index 93fd0260b0..fcb03e084f 100644 --- a/frontend/frontend_context.c +++ b/frontend/frontend_context.c @@ -43,7 +43,7 @@ const frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident) { for (unsigned i = 0; i < sizeof(frontend_ctx_drivers) / sizeof(frontend_ctx_drivers[0]); i++) { - if (!frontend_ctx_drivers[i]) // could be the dummy NULL + if (!frontend_ctx_drivers[i]) // check for dummy NULL continue; if (strcmp(frontend_ctx_drivers[i]->ident, ident) == 0) return frontend_ctx_drivers[i]; diff --git a/input/dinput.c b/input/dinput.c index 620d3e645a..237a09f9d4 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -68,11 +68,11 @@ static bool dinput_init_context(void) if (g_ctx) return true; - if (driver.display_type != RARCH_DISPLAY_WIN32) + /*if (driver.display_type != RARCH_DISPLAY_WIN32) { RARCH_ERR("Cannot open DInput as no Win32 window is present.\n"); return false; - } + }*/ // Not needed, interferes with joyconfig CoInitialize(NULL); @@ -386,7 +386,35 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p) return DIENUM_CONTINUE; } -extern const LPCTSTR XBOX_PAD_NAMES_TO_REJECT[]; +static const LPCTSTR XBOX_PAD_NAMES[] = +{ + "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 Receiver for Windows (Wireless Controller)", + "Xbox wireless receiver for windows (Controller)", + NULL +}; + +static bool name_is_360_pad(LPCSTR name) +{ + for (unsigned i = 0; ; ++i) + { + LPCSTR t = XBOX_PAD_NAMES[i]; + if (t == NULL) + return false; + else if (lstrcmpi(name, t) == 0) + return true; + } +} + +// Keep track of which pad indexes are 360 controllers +// not static, will be read in winxinput_joypad.c +// -1 = not xbox pad, otherwise 0..3 +int g_xbox_pad_indexes[MAX_PLAYERS]; static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) { @@ -404,23 +432,13 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) return DIENUM_CONTINUE; #ifdef USE_WINXINPUT - // Reject xbox 360 controllers, the xinput driver will take care of them - DIDEVICEINSTANCE info; - ZeroMemory(&info, sizeof(DIDEVICEINSTANCE)); - info.dwSize = sizeof(DIDEVICEINSTANCE); - IDirectInputDevice8_GetDeviceInfo(*pad, &info); + int last_xbox_pad_index = 0; - unsigned test_name_index = 0; - while(1) + if (name_is_360_pad(inst->tszProductName)) { - if (XBOX_PAD_NAMES_TO_REJECT[test_name_index] == NULL) - break; - if (lstrcmpi(info.tszProductName, XBOX_PAD_NAMES_TO_REJECT[test_name_index]) == 0) - { - RARCH_LOG("dinput: Rejected XInput controller \"%s\"", info.tszProductName); - return DIENUM_CONTINUE; - } - ++test_name_index; + if (last_xbox_pad_index < 4) + g_xbox_pad_indexes[g_joypad_cnt] = last_xbox_pad_index; + ++last_xbox_pad_index; } #endif @@ -440,6 +458,9 @@ static bool dinput_joypad_init(void) { if (!dinput_init_context()) return false; + + for (unsigned i = 0; i < MAX_PLAYERS; ++i) + g_xbox_pad_indexes[i] = -1; RARCH_LOG("Enumerating DInput joypads ...\n"); IDirectInput8_EnumDevices(g_ctx, DI8DEVCLASS_GAMECTRL, diff --git a/input/sdl_joypad.c b/input/sdl_joypad.c index 0ed9411be8..812936be56 100644 --- a/input/sdl_joypad.c +++ b/input/sdl_joypad.c @@ -39,8 +39,6 @@ static void sdl_joypad_destroy(void) memset(g_pads, 0, sizeof(g_pads)); } -extern const LPCTSTR XBOX_PAD_NAMES_TO_REJECT[]; - static bool sdl_joypad_init(void) { if (SDL_Init(SDL_INIT_JOYSTICK) < 0) @@ -56,32 +54,9 @@ static bool sdl_joypad_init(void) pad->joypad = SDL_JoystickOpen(i); if (!pad->joypad) { - RARCH_ERR("Couldn't open SDL joystick #%u.\n", i); - goto error; + RARCH_ERR("Couldn't open SDL joystick #%u.\n", i); + goto error; } - - - #ifdef USE_WINXINPUT - // Reject xbox 360 controllers, the xinput driver will take care of them. - unsigned test_name_index = 0; - while(1) - { - if (XBOX_PAD_NAMES_TO_REJECT[test_name_index] == NULL) - break; - if (lstrcmpi(SDL_JoystickName(i), XBOX_PAD_NAMES_TO_REJECT[test_name_index]) == 0) - { - RARCH_LOG("sdl joypad: Rejected XInput controller \"%s\"", SDL_JoystickName(i)); - pad->joypad = NULL; pad->num_axes = 0; pad->num_buttons = 0; pad->num_hats = 0; - - goto continue_after_xinput_rejection; - } - ++test_name_index; - } - #endif - - continue_after_xinput_rejection: - - // RARCH_LOG("Opened Joystick: %s (#%u).\n", SDL_JoystickName(i), i); diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index 0310b24c5b..234e57ac53 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -20,9 +20,6 @@ // Some wrappers for other controllers also simulate xinput (as it is easier to implement) // so this may be useful for those also. - -// Note: if rumble is ever added (for psx and n64 cores), add rumble support to this -// as well as dinput. #include "input_common.h" #include "../general.h" @@ -32,12 +29,8 @@ #include #include -//#include - -// There is no need to require the xinput headers and libs since -// we shall be dynamically loading them anyway. But first check that -// it hasn't been included anyway. -// official and mingw xinput headers have different include guards +// Check the definitions do not already exist. +// Official and mingw xinput headers have different include guards #if ((!_XINPUT_H_) && (!__WINE_XINPUT_H)) #define XINPUT_GAMEPAD_DPAD_UP 0x0001 @@ -81,25 +74,40 @@ #define ERROR_DEVICE_NOT_CONNECTED 1167 #endif -// To load xinput1_3.dll +#ifndef HAVE_DINPUT + #error Cannot compile xinput without dinput. +#endif + +// Due to 360 pads showing up under both XI and DI, and since we are going +// to have to pass through unhandled joypad numbers to DI, a slightly ugly +// hack is required here. dinput_joypad_init will fill this. +// For each pad index, the appropriate entry will be set to -1 if it is not +// a 360 pad, or the correct XInput player number (0..3 inclusive) if it is. +extern int g_xbox_pad_indexes[MAX_PLAYERS]; + +// For xinput1_3.dll static HINSTANCE g_winxinput_dll; // Function pointer, to be assigned with GetProcAddress -typedef __stdcall DWORD (*XInputGetStateEx_t)(DWORD, XINPUT_STATE*); +typedef DWORD (__stdcall *XInputGetStateEx_t)(DWORD, XINPUT_STATE*); static XInputGetStateEx_t g_XInputGetStateEx; -// Guide button may or may not be available, -// but if it is available +// Guide button may or may not be available static bool g_winxinput_guide_button_supported; typedef struct { XINPUT_STATE xstate; - bool connected; + bool connected; } winxinput_joypad_state; static winxinput_joypad_state g_winxinput_states[4]; +static int pad_index_to_xplayer_index(unsigned pad) +{ + return g_xbox_pad_indexes[pad]; +} + static bool winxinput_joypad_init(void) { g_winxinput_dll = NULL; @@ -119,12 +127,13 @@ static bool winxinput_joypad_init(void) { // Loading from working dir failed, try to load from system. GetSystemDirectory(dll_path, sizeof(dll_path)); - strcpy(dll_path, "xinput1_3.dll"); + strcat(dll_path, "\\xinput1_3.dll"); g_winxinput_dll = LoadLibrary(dll_path); if (!g_winxinput_dll) { RARCH_ERR("Failed to init XInput, ensure DirectX and controller drivers are up to date.\n"); + //g_dinput_should_filter_xinput_controllers = false; return false; // DLL does not exist or is invalid } @@ -132,21 +141,22 @@ static bool winxinput_joypad_init(void) // If we get here then an xinput DLL is correctly loaded. // First try to load ordinal 100 (XInputGetStateEx). - // Cast to make C++ happy. g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (LPCSTR)100); g_winxinput_guide_button_supported = true; if (!g_XInputGetStateEx) { - // no ordinal 100. (old version of x360ce perhaps). Load the ordinary XInputGetState, + // no ordinal 100. (old version of x360ce perhaps?) Load the ordinary XInputGetState, // at the cost of losing guide button support. g_winxinput_guide_button_supported = false; g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); if (!g_XInputGetStateEx) { - RARCH_ERR("Failed to init XInput.\n"); + RARCH_ERR("Failed to init XInput: Found an XInput DLL but it is invalid or corrupt.\n"); + //g_dinput_should_filter_xinput_controllers = false; return false; // DLL was loaded but did not contain the correct function. } + RARCH_WARN("XInput: No guide button support.\n"); } // zero out the states @@ -161,17 +171,26 @@ static bool winxinput_joypad_init(void) if (g_winxinput_states[i].connected) RARCH_LOG("Found XInput controller, player #%u\n", i); } - - return true; + if ((!g_winxinput_states[0].connected) && + (!g_winxinput_states[1].connected) && + (!g_winxinput_states[2].connected) && + (!g_winxinput_states[3].connected)) + return false; + + + // We're going to have to be buddies with dinput if we want to be able + // to use XI and non-XI controllers together. + return dinput_joypad.init(); } static bool winxinput_joypad_query_pad(unsigned pad) { - if (pad >= 4) - return false; + int xplayer = pad_index_to_xplayer_index(pad); + if (xplayer > -1) + return g_winxinput_states[0].connected; else - return g_winxinput_states[pad].connected; + return dinput_joypad.query_pad(pad); } static void winxinput_joypad_destroy(void) @@ -180,36 +199,45 @@ static void winxinput_joypad_destroy(void) ZeroMemory(&g_winxinput_states[i], sizeof(winxinput_joypad_state)); FreeLibrary(g_winxinput_dll); - g_winxinput_dll = NULL; + g_winxinput_dll = NULL; g_XInputGetStateEx = NULL; + + dinput_joypad.destroy(); } // Buttons are provided by XInput as bits of a uint16. -// Map from button index (0..10) to mask to AND against. +// Map from rarch button index (0..10) to a mask to bitwise-& the buttons against. // dpad is handled seperately. -// Order: -// a, b, x, y, leftbump, rightbump, back, start, leftstick, rightstick, guide. static const WORD button_index_to_bitmap_code[] = { - 0x1000, 0x2000, 0x4000, 0x8000, 0x0100, 0x0200, 0x0020, 0x0010, - 0x0040, 0x0080, 0x0400 + XINPUT_GAMEPAD_A , + XINPUT_GAMEPAD_B , + XINPUT_GAMEPAD_X , + XINPUT_GAMEPAD_Y , + XINPUT_GAMEPAD_LEFT_SHOULDER , + XINPUT_GAMEPAD_RIGHT_SHOULDER, + XINPUT_GAMEPAD_START , + XINPUT_GAMEPAD_BACK , + XINPUT_GAMEPAD_LEFT_THUMB , + XINPUT_GAMEPAD_RIGHT_THUMB , + XINPUT_GAMEPAD_GUIDE }; static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey) { if (joykey == NO_BTN) return false; - - if (!(g_winxinput_states[port_num].connected)) + + int xplayer = pad_index_to_xplayer_index(port_num); + if (xplayer == -1) + return dinput_joypad.button(port_num, joykey); + + if (!(g_winxinput_states[xplayer].connected)) return false; - - - - uint16_t btn_word = g_winxinput_states[port_num].xstate.Gamepad.wButtons; - + + uint16_t btn_word = g_winxinput_states[xplayer].xstate.Gamepad.wButtons; if (GET_HAT_DIR(joykey)) { - switch (GET_HAT_DIR(joykey)) { case HAT_UP_MASK: return btn_word & XINPUT_GAMEPAD_DPAD_UP; @@ -217,7 +245,6 @@ static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey) case HAT_LEFT_MASK: return btn_word & XINPUT_GAMEPAD_DPAD_LEFT; case HAT_RIGHT_MASK: return btn_word & XINPUT_GAMEPAD_DPAD_RIGHT; } - return false; // hat requested and no hat button down } else @@ -225,44 +252,32 @@ static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey) // non-hat button unsigned num_buttons = g_winxinput_guide_button_supported ? 11 : 10; - if (joykey >= num_buttons) - return false; - else + if (joykey < num_buttons) return btn_word & button_index_to_bitmap_code[joykey]; } - return false; - } -//#include + static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) { - //printf("Requested axis: %u\n", joyaxis); if (joyaxis == AXIS_NONE) return 0; - if (!(g_winxinput_states[port_num].connected)) - return 0; - - /*switch (joyaxis) - { - case 0: return(g_winxinput_states[port_num].xstate.Gamepad.sThumbLX); - case 1: return (g_winxinput_states[port_num].xstate.Gamepad.sThumbLX); - case 2: return 0; - case 3: return 0; //do axes now - case 4: return 0; - case 5: return 0; - default: return 0; - }*/ + int xplayer = pad_index_to_xplayer_index(port_num); + if (xplayer == -1) + return dinput_joypad.axis(port_num, joyaxis); + + if (!(g_winxinput_states[xplayer].connected)) + return false; int16_t val = 0; - int axis = -1; + int axis = -1; bool is_neg = false; bool is_pos = false; - if (AXIS_NEG_GET(joyaxis) <= 3) + if (AXIS_NEG_GET(joyaxis) <= 3) // triggers (axes 4,5) cannot be negative { axis = AXIS_NEG_GET(joyaxis); is_neg = true; @@ -273,7 +288,8 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) is_pos = true; } - XINPUT_GAMEPAD* pad = &(g_winxinput_states[port_num].xstate.Gamepad); + XINPUT_GAMEPAD* pad = &(g_winxinput_states[xplayer].xstate.Gamepad); + switch (axis) { case 0: val = pad->sThumbLX; break; @@ -281,7 +297,7 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) case 2: val = pad->sThumbRX; break; case 3: val = pad->sThumbRY; break; - case 4: val = pad->bLeftTrigger * 32767 / 255; break; + case 4: val = pad->bLeftTrigger * 32767 / 255; break; // map 0..255 to 0..32767 case 5: val = pad->bRightTrigger * 32767 / 255; break; } @@ -289,9 +305,12 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) val = 0; else if (is_pos && val < 0) val = 0; + + // Clamp to avoid overflow error + if (val == -32768) + val = -32767; return val; - } static void winxinput_joypad_poll(void) @@ -299,6 +318,8 @@ static void winxinput_joypad_poll(void) for (unsigned i = 0; i < 4; ++i) if (g_XInputGetStateEx(i, &(g_winxinput_states[i].xstate)) == ERROR_DEVICE_NOT_CONNECTED) g_winxinput_states[i].connected = false; + + dinput_joypad.poll(); } static const char* const XBOX_CONTROLLER_NAMES[4] = @@ -311,13 +332,15 @@ static const char* const XBOX_CONTROLLER_NAMES[4] = const char* winxinput_joypad_name (unsigned pad) { - if (pad > 3) - return NULL; + int xplayer = pad_index_to_xplayer_index(pad); + + if (xplayer < 0) + return dinput_joypad.name(pad); else - return XBOX_CONTROLLER_NAMES[pad]; + // TODO: Different name if disconnected? + return XBOX_CONTROLLER_NAMES[xplayer]; } - const rarch_joypad_driver_t winxinput_joypad = { winxinput_joypad_init, winxinput_joypad_query_pad, @@ -328,34 +351,3 @@ const rarch_joypad_driver_t winxinput_joypad = { winxinput_joypad_name, "winxinput", }; - -// A list of names for other (dinput) drivers to reject. -const LPCTSTR XBOX_PAD_NAMES_TO_REJECT[] = -{ - "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 Receiver for Windows (Wireless Controller)", - "Xbox wireless receiver for windows (Controller)", - NULL -}; - - -/* -typedef struct rarch_joypad_driver -{ - bool (*init)(void); - bool (*query_pad)(unsigned); - void (*destroy)(void); - bool (*button)(unsigned, uint16_t); - int16_t (*axis)(unsigned, uint32_t); - void (*poll)(void); - const char *(*name)(unsigned); - - const char *ident; -} rarch_joypad_driver_t; - -*/ \ No newline at end of file diff --git a/msvc/msvc-2010/RetroArch-msvc2010.sln b/msvc/msvc-2010/RetroArch-msvc2010.sln new file mode 100644 index 0000000000..6bb4b9c199 --- /dev/null +++ b/msvc/msvc-2010/RetroArch-msvc2010.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RetroArch-msvc2010", "RetroArch-msvc2010.vcxproj", "{27FF7CE1-4059-4AA1-8062-FD529560FA54}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|Win32.ActiveCfg = Debug|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Debug|Win32.Build.0 = Debug|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|Win32.ActiveCfg = Release|Win32 + {27FF7CE1-4059-4AA1-8062-FD529560FA54}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal From f3de828444328cc9ae16c7088fc39e27bf80487d Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Sun, 25 Aug 2013 18:54:20 +0100 Subject: [PATCH 3/6] Eradicated some win32 macros/typedefs --- input/dinput.c | 4 ++-- input/winxinput_joypad.c | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/input/dinput.c b/input/dinput.c index 237a09f9d4..cb10f3b788 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -399,11 +399,11 @@ static const LPCTSTR XBOX_PAD_NAMES[] = NULL }; -static bool name_is_360_pad(LPCSTR name) +static bool name_is_360_pad(const char* name) { for (unsigned i = 0; ; ++i) { - LPCSTR t = XBOX_PAD_NAMES[i]; + const char* t = XBOX_PAD_NAMES[i]; if (t == NULL) return false; else if (lstrcmpi(name, t) == 0) diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index 234e57ac53..d7666140e9 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -50,18 +50,18 @@ typedef struct { - WORD wButtons; - BYTE bLeftTrigger; - BYTE bRightTrigger; - SHORT sThumbLX; - SHORT sThumbLY; - SHORT sThumbRX; - SHORT sThumbRY; + uint16_t wButtons; + uint8_t bLeftTrigger; + uint8_t bRightTrigger; + int16_t sThumbLX; + int16_t sThumbLY; + int16_t sThumbRX; + int16_t sThumbRY; } XINPUT_GAMEPAD; typedef struct { - DWORD dwPacketNumber; + uint32_t dwPacketNumber; XINPUT_GAMEPAD Gamepad; } XINPUT_STATE; @@ -89,7 +89,7 @@ extern int g_xbox_pad_indexes[MAX_PLAYERS]; static HINSTANCE g_winxinput_dll; // Function pointer, to be assigned with GetProcAddress -typedef DWORD (__stdcall *XInputGetStateEx_t)(DWORD, XINPUT_STATE*); +typedef uint32_t (__stdcall *XInputGetStateEx_t)(uint32_t, XINPUT_STATE*); static XInputGetStateEx_t g_XInputGetStateEx; // Guide button may or may not be available @@ -120,7 +120,7 @@ static bool winxinput_joypad_init(void) // No need to check for existance as we will be checking LoadLibrary's // success anyway. - TCHAR dll_path[MAX_PATH]; + char dll_path[MAX_PATH]; strcpy(dll_path, "xinput1_3.dll"); g_winxinput_dll = LoadLibrary(dll_path); if (!g_winxinput_dll) @@ -141,7 +141,7 @@ static bool winxinput_joypad_init(void) // If we get here then an xinput DLL is correctly loaded. // First try to load ordinal 100 (XInputGetStateEx). - g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (LPCSTR)100); + g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (const char*)100); g_winxinput_guide_button_supported = true; if (!g_XInputGetStateEx) @@ -161,7 +161,7 @@ static bool winxinput_joypad_init(void) // zero out the states for (unsigned i = 0; i < 4; ++i) - ZeroMemory(&g_winxinput_states[i], sizeof(winxinput_joypad_state)); + memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); // Do a dummy poll to check which controllers are connected. XINPUT_STATE dummy_state; @@ -196,7 +196,7 @@ static bool winxinput_joypad_query_pad(unsigned pad) static void winxinput_joypad_destroy(void) { for (unsigned i = 0; i < 4; ++i) - ZeroMemory(&g_winxinput_states[i], sizeof(winxinput_joypad_state)); + memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); FreeLibrary(g_winxinput_dll); g_winxinput_dll = NULL; @@ -208,7 +208,7 @@ static void winxinput_joypad_destroy(void) // Buttons are provided by XInput as bits of a uint16. // Map from rarch button index (0..10) to a mask to bitwise-& the buttons against. // dpad is handled seperately. -static const WORD button_index_to_bitmap_code[] = { +static const uint16_t button_index_to_bitmap_code[] = { XINPUT_GAMEPAD_A , XINPUT_GAMEPAD_B , XINPUT_GAMEPAD_X , From ef8a86e794e40a451f0cfb654aa62ae8e2cc142d Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Sun, 25 Aug 2013 18:57:23 +0100 Subject: [PATCH 4/6] more win32 typedef removal --- input/dinput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/dinput.c b/input/dinput.c index cb10f3b788..9df0386b52 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -386,7 +386,7 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p) return DIENUM_CONTINUE; } -static const LPCTSTR XBOX_PAD_NAMES[] = +static const char* const XBOX_PAD_NAMES[] = { "Controller (Gamepad for Xbox 360)", "Controller (XBOX 360 For Windows)", From 333ae68163e95c1dc2cccda56450ad99cf42938a Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Mon, 26 Aug 2013 12:13:41 +0100 Subject: [PATCH 5/6] more small style tweaks --- Makefile.win | 6 +- frontend/frontend_context.c | 6 +- input/dinput.c | 8 +- input/input_common.c | 2 +- input/winxinput_joypad.c | 109 +++++++++++----------- msvc/msvc-2010/RetroArch-msvc2010.vcxproj | 8 +- 6 files changed, 64 insertions(+), 75 deletions(-) diff --git a/Makefile.win b/Makefile.win index df300fb4f7..27cdb3cc11 100644 --- a/Makefile.win +++ b/Makefile.win @@ -64,7 +64,7 @@ HAVE_THREADS = 1 HAVE_RGUI = 1 DYNAMIC = 1 -USE_WINXINPUT = 1 +HAVE_WINXINPUT = 1 ifeq ($(SLIM),) HAVE_SDL = 1 @@ -215,8 +215,8 @@ ifeq ($(HAVE_PYTHON), 1) OBJ += gfx/py_state/py_state.o endif -ifeq ($(USE_WINXINPUT), 1) - DEFINES += -DUSE_WINXINPUT +ifeq ($(HAVE_WINXINPUT), 1) + DEFINES += -DHAVE_WINXINPUT OBJ += input/winxinput_joypad.o endif diff --git a/frontend/frontend_context.c b/frontend/frontend_context.c index fcb03e084f..3072732b4c 100644 --- a/frontend/frontend_context.c +++ b/frontend/frontend_context.c @@ -41,10 +41,8 @@ static const frontend_ctx_driver_t *frontend_ctx_drivers[] = { const frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident) { - for (unsigned i = 0; i < sizeof(frontend_ctx_drivers) / sizeof(frontend_ctx_drivers[0]); i++) + for (unsigned i = 0; frontend_ctx_drivers[i]; i++) { - if (!frontend_ctx_drivers[i]) // check for dummy NULL - continue; if (strcmp(frontend_ctx_drivers[i]->ident, ident) == 0) return frontend_ctx_drivers[i]; } @@ -54,7 +52,7 @@ const frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident) const frontend_ctx_driver_t *frontend_ctx_init_first(void) { - for (unsigned i = 0; i < sizeof(frontend_ctx_drivers) / sizeof(frontend_ctx_drivers[0]); i++) + for (unsigned i = 0; frontend_ctx_drivers[i]; i++) return frontend_ctx_drivers[i]; return NULL; diff --git a/input/dinput.c b/input/dinput.c index 9df0386b52..972772da75 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -68,12 +68,6 @@ static bool dinput_init_context(void) if (g_ctx) return true; - /*if (driver.display_type != RARCH_DISPLAY_WIN32) - { - RARCH_ERR("Cannot open DInput as no Win32 window is present.\n"); - return false; - }*/ // Not needed, interferes with joyconfig - CoInitialize(NULL); // Who said we shouldn't have same call signature in a COM API? <_< @@ -431,7 +425,7 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) #endif return DIENUM_CONTINUE; -#ifdef USE_WINXINPUT +#ifdef HAVE_WINXINPUT int last_xbox_pad_index = 0; if (name_is_360_pad(inst->tszProductName)) diff --git a/input/input_common.c b/input/input_common.c index cc7ab96e80..fb799e3884 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -41,7 +41,7 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { #ifndef IS_RETROLAUNCH -#ifdef USE_WINXINPUT +#ifdef HAVE_WINXINPUT &winxinput_joypad, #endif #ifdef HAVE_DINPUT diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index d7666140e9..d07af3a1cb 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -1,6 +1,5 @@ /* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2013 - Hans-Kristian Arntzen - * + * * 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. @@ -33,37 +32,37 @@ // Official and mingw xinput headers have different include guards #if ((!_XINPUT_H_) && (!__WINE_XINPUT_H)) - #define XINPUT_GAMEPAD_DPAD_UP 0x0001 - #define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 - #define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 - #define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 - #define XINPUT_GAMEPAD_START 0x0010 - #define XINPUT_GAMEPAD_BACK 0x0020 - #define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 - #define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 - #define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 - #define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 - #define XINPUT_GAMEPAD_A 0x1000 - #define XINPUT_GAMEPAD_B 0x2000 - #define XINPUT_GAMEPAD_X 0x4000 - #define XINPUT_GAMEPAD_Y 0x8000 - - typedef struct - { - uint16_t wButtons; - uint8_t bLeftTrigger; - uint8_t bRightTrigger; - int16_t sThumbLX; - int16_t sThumbLY; - int16_t sThumbRX; - int16_t sThumbRY; - } XINPUT_GAMEPAD; +#define XINPUT_GAMEPAD_DPAD_UP 0x0001 +#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 +#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 +#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 +#define XINPUT_GAMEPAD_START 0x0010 +#define XINPUT_GAMEPAD_BACK 0x0020 +#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 +#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 +#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 +#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 +#define XINPUT_GAMEPAD_A 0x1000 +#define XINPUT_GAMEPAD_B 0x2000 +#define XINPUT_GAMEPAD_X 0x4000 +#define XINPUT_GAMEPAD_Y 0x8000 - typedef struct - { - uint32_t dwPacketNumber; - XINPUT_GAMEPAD Gamepad; - } XINPUT_STATE; +typedef struct +{ + uint16_t wButtons; + uint8_t bLeftTrigger; + uint8_t bRightTrigger; + int16_t sThumbLX; + int16_t sThumbLY; + int16_t sThumbRX; + int16_t sThumbRY; +} XINPUT_GAMEPAD; + +typedef struct +{ + uint32_t dwPacketNumber; + XINPUT_GAMEPAD Gamepad; +} XINPUT_STATE; #endif @@ -71,11 +70,11 @@ #define XINPUT_GAMEPAD_GUIDE 0x0400 #ifndef ERROR_DEVICE_NOT_CONNECTED - #define ERROR_DEVICE_NOT_CONNECTED 1167 +#define ERROR_DEVICE_NOT_CONNECTED 1167 #endif #ifndef HAVE_DINPUT - #error Cannot compile xinput without dinput. +#error Cannot compile xinput without dinput. #endif // Due to 360 pads showing up under both XI and DI, and since we are going @@ -120,20 +119,20 @@ static bool winxinput_joypad_init(void) // No need to check for existance as we will be checking LoadLibrary's // success anyway. - char dll_path[MAX_PATH]; - strcpy(dll_path, "xinput1_3.dll"); - g_winxinput_dll = LoadLibrary(dll_path); + const char* DLL_NAME = "xinput1_3.dll"; + g_winxinput_dll = LoadLibrary(DLL_NAME); // Using dylib_* complicates building joyconfig. if (!g_winxinput_dll) { // Loading from working dir failed, try to load from system. + char dll_path[MAX_PATH]; GetSystemDirectory(dll_path, sizeof(dll_path)); - strcat(dll_path, "\\xinput1_3.dll"); + strlcat(dll_path, "\\", 1); + strlcat(dll_path, DLL_NAME, sizeof(DLL_NAME)); g_winxinput_dll = LoadLibrary(dll_path); if (!g_winxinput_dll) { - RARCH_ERR("Failed to init XInput, ensure DirectX and controller drivers are up to date.\n"); - //g_dinput_should_filter_xinput_controllers = false; + RARCH_ERR("Failed to load xinput1_3.dll, ensure DirectX and controller drivers are up to date.\n"); return false; // DLL does not exist or is invalid } @@ -152,8 +151,7 @@ static bool winxinput_joypad_init(void) g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); if (!g_XInputGetStateEx) { - RARCH_ERR("Failed to init XInput: Found an XInput DLL but it is invalid or corrupt.\n"); - //g_dinput_should_filter_xinput_controllers = false; + RARCH_ERR("Failed to init XInput: xinput1_3.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"); @@ -173,12 +171,11 @@ static bool winxinput_joypad_init(void) } if ((!g_winxinput_states[0].connected) && - (!g_winxinput_states[1].connected) && - (!g_winxinput_states[2].connected) && - (!g_winxinput_states[3].connected)) - return false; + (!g_winxinput_states[1].connected) && + (!g_winxinput_states[2].connected) && + (!g_winxinput_states[3].connected)) + return false; - // We're going to have to be buddies with dinput if we want to be able // to use XI and non-XI controllers together. return dinput_joypad.init(); @@ -209,16 +206,16 @@ static void winxinput_joypad_destroy(void) // Map from rarch button index (0..10) to a mask to bitwise-& the buttons against. // dpad is handled seperately. static const uint16_t button_index_to_bitmap_code[] = { - XINPUT_GAMEPAD_A , - XINPUT_GAMEPAD_B , - XINPUT_GAMEPAD_X , - XINPUT_GAMEPAD_Y , - XINPUT_GAMEPAD_LEFT_SHOULDER , + XINPUT_GAMEPAD_A, + XINPUT_GAMEPAD_B, + XINPUT_GAMEPAD_X, + XINPUT_GAMEPAD_Y, + XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, - XINPUT_GAMEPAD_START , - XINPUT_GAMEPAD_BACK , - XINPUT_GAMEPAD_LEFT_THUMB , - XINPUT_GAMEPAD_RIGHT_THUMB , + XINPUT_GAMEPAD_START, + XINPUT_GAMEPAD_BACK, + XINPUT_GAMEPAD_LEFT_THUMB, + XINPUT_GAMEPAD_RIGHT_THUMB, XINPUT_GAMEPAD_GUIDE }; diff --git a/msvc/msvc-2010/RetroArch-msvc2010.vcxproj b/msvc/msvc-2010/RetroArch-msvc2010.vcxproj index 3a7d4085ad..45bbb6b6cd 100644 --- a/msvc/msvc-2010/RetroArch-msvc2010.vcxproj +++ b/msvc/msvc-2010/RetroArch-msvc2010.vcxproj @@ -88,7 +88,7 @@ Level3 Disabled - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp @@ -108,7 +108,7 @@ Level3 Disabled - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreadedDebug CompileAsCpp @@ -130,7 +130,7 @@ MaxSpeed true true - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;HAVE_ZLIB;WANT_MINIZ;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;_CRT_SECURE_NO_WARNINGS;__SSE__;__i686__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp @@ -154,7 +154,7 @@ MaxSpeed true true - WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;USE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_ZLIB;WANT_MINIZ;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC + WIN32;HAVE_WIN32_D3D9;HAVE_CG;HAVE_GLSL;HAVE_FBO;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);HAVE_SCREENSHOTS;HAVE_BSV_MOVIE;HAVE_DINPUT;HAVE_WINXINPUT;HAVE_XAUDIO;HAVE_DSOUND;HAVE_OPENGL;HAVE_DYLIB;HAVE_NETPLAY;HAVE_NETWORK_CMD;HAVE_COMMAND;HAVE_STDIN_CMD;HAVE_THREADS;HAVE_DYNAMIC;HAVE_ZLIB;WANT_MINIZ;_CRT_SECURE_NO_WARNINGS;__SSE__;__SSE2__;__x86_64__;HAVE_OVERLAY;HAVE_RGUI;HAVE_GL_SYNC $(MSBuildProjectDirectory);$(MSBuildProjectDirectory)\..\..\;$(CG_INC_PATH);%(AdditionalIncludeDirectories) MultiThreaded CompileAsCpp From d5eea1e575dcf2840a827a6cf4ca5b9aa4a14b7d Mon Sep 17 00:00:00 2001 From: pinumbernumber <1337rz@gmail.com> Date: Mon, 26 Aug 2013 15:37:01 +0100 Subject: [PATCH 6/6] fixed attribution --- input/winxinput_joypad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index d07af3a1cb..00ab50c60b 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -1,5 +1,6 @@ /* RetroArch - A frontend for libretro. - * + * Copyright (C) 2013 - pinumbernumber + * * 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.