diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index cd6b4fe..912771c --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,43 @@ +PROJECT(koku-xinput-wine) cmake_minimum_required(VERSION 2.8) -project(koku-xinput-wine) -ADD_LIBRARY(koku-xinput-wine SHARED main.cpp config.cpp xinput.cpp device.cpp) +# Check for C++11 +include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +else() + message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +endif() -#For SDL: -target_link_libraries(koku-xinput-wine SDL) -set(CMAKE_CXX_FLAGS "-std=c++0x -m32") +# Check for 32bit version +option(BUILD_M32 "Build library in 32Bit mode" ON) +if(BUILD_M32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") +endif() -#For SDL2: -#target_link_libraries(koku-xinput-wine SDL2) -#set(CMAKE_CXX_FLAGS "-std=c++0x -m32 -DUSE_SDL2") +ADD_LIBRARY(koku-xinput-wine SHARED main.cpp xinput.cpp device.cpp) +# Pull in pkgconfig +include(FindPkgConfig) + +# - Try to find SDL +# Once done this will define +# +# SDL_FOUND - system has libSDL +# SDL_INCLUDE_DIRS - the libSDL include directory +# SDL_LIBRARIES - The libSDL libraries +if(PKG_CONFIG_FOUND) + pkg_check_modules (SDL REQUIRED sdl2) +else() + find_package(SDL2 REQURIED) + list(APPEND SDL_INCLUDE_DIRS ${SDL2_INCLUDE_DIR}) + list(APPEND SDL_LIBRARIES ${SDL2_LIBRARIES}) +endif() + +# Link SDL +target_link_libraries(koku-xinput-wine ${SDL_LIBRARY}) set_target_properties(koku-xinput-wine PROPERTIES PREFIX "") diff --git a/README.md b/README.md index 7e066cb..352767f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ koku-xinput-wine ================ Adds xinput support to wine, without changing the source of wine. +Modified to use SDL2 gamepad mappings Install --------------------- @@ -9,9 +10,9 @@ If you are on 64Bit you will need 32Bit tool-chain (multilib) Because this will generate 32Bit code, no 64Bit support ! -It depens on SDL1.2-Librarys. +It depens on SDL2-Librarys. - [user@host code]$git clone https://github.com/KoKuToru/koku-xinput-wine + [user@host code]$git clone https://github.com/KoKuToru/koku-xinput-wine.git [user@host code]$cd koku-xinput-wine [user&host code]$cmake . [user@host code]$make @@ -29,49 +30,7 @@ Of course it would be wiser to put this code into wine.. Config --------------------- -File at ~/.config/koku-xinput-wine.ini, gets auto generated at first usage. - XINPUT_GAMEPAD_LEFT_THUMB_X = A01 - XINPUT_GAMEPAD_LEFT_THUMB_Y = A02*-1 - ... - XINPUT_GAMEPAD_DPAD_UP = H01&0x0001 - ... - XINPUT_GAMEPAD_Y = B04 - -### First config-parameter - XINPUT_GAMEPAD_DPAD_UP - -i thinks this parameters pretty much explain itself.. if you don't understand, feel free to ask me. +You can add sdl2 gamepad mappings by putting them in file named "gamecontrollerdb.txt" and place it next to your game executable, or via the *SDL_GAMECONTROLLERCONFIG* environment variable. -### Second config-parameter - -The first letter stands for: - - A = Axis - B = Buttons - H = Hats - -Follwing with a number, which explains the id. - - A10 - - Axi with id 10. - -### Third config-parameter (optional) - -Starts with a '&', followed by a 16-Bit hex number. -Bit mask are useful for hats, hats return 1 value for 4 different directions. - - 0x0001 = SDL_HAT_UP - 0x0002 = SDL_HAT_RIGHT - 0x0004 = SDL_HAT_DOWN - 0x0008 = SLD_HAT_LEFT - -### Forth config-parameter (optional) - -Starts with a '*', followed by a integer number. -Multiplys the result with the value. - - A02*-1 - -Flips the Axi Nr. 2. +You can find a premade gamecontrollerdb.txt with a lot of mappings [here](https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt) diff --git a/config.cpp b/config.cpp deleted file mode 100644 index f263dd2..0000000 --- a/config.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "config.h" -#include - -//global gamepad struct -SGamepadData gamepad; - -//Setup mapping data -const Smapping mapping[20] = -{ - {"XINPUT_GAMEPAD_LEFT_THUMB_X", &gamepad.left_thumb_x , 0}, - {"XINPUT_GAMEPAD_LEFT_THUMB_Y", &gamepad.left_thumb_y , 0}, - {"XINPUT_GAMEPAD_RIGHT_THUMB_X", &gamepad.right_thumb_x , 0}, - {"XINPUT_GAMEPAD_RIGHT_THUMB_Y", &gamepad.right_thumb_y , 0}, - {"XINPUT_GAMEPAD_DPAD_UP", &gamepad.buttons , short(XINPUT_GAMEPAD_DPAD_UP)}, - {"XINPUT_GAMEPAD_DPAD_DOWN", &gamepad.buttons , short(XINPUT_GAMEPAD_DPAD_DOWN)}, - {"XINPUT_GAMEPAD_DPAD_LEFT", &gamepad.buttons , short(XINPUT_GAMEPAD_DPAD_LEFT)}, - {"XINPUT_GAMEPAD_DPAD_RIGHT", &gamepad.buttons , short(XINPUT_GAMEPAD_DPAD_RIGHT)}, - {"XINPUT_GAMEPAD_START", &gamepad.buttons , short(XINPUT_GAMEPAD_START)}, - {"XINPUT_GAMEPAD_BACK", &gamepad.buttons , short(XINPUT_GAMEPAD_BACK)}, - {"XINPUT_GAMEPAD_LEFT_THUMB", &gamepad.buttons , short(XINPUT_GAMEPAD_LEFT_THUMB)}, - {"XINPUT_GAMEPAD_RIGHT_THUMB", &gamepad.buttons , short(XINPUT_GAMEPAD_RIGHT_THUMB)}, - {"XINPUT_GAMEPAD_LEFT_SHOULDER", &gamepad.buttons , short(XINPUT_GAMEPAD_LEFT_SHOULDER)}, - {"XINPUT_GAMEPAD_LEFT_SHOULDER2", &gamepad.left_shoulder , 0}, - {"XINPUT_GAMEPAD_RIGHT_SHOULDER", &gamepad.buttons , short(XINPUT_GAMEPAD_RIGHT_SHOULDER)}, - {"XINPUT_GAMEPAD_RIGHT_SHOULDER2", &gamepad.right_shoulder, 0}, - {"XINPUT_GAMEPAD_A", &gamepad.buttons , short(XINPUT_GAMEPAD_A)}, - {"XINPUT_GAMEPAD_B", &gamepad.buttons , short(XINPUT_GAMEPAD_B)}, - {"XINPUT_GAMEPAD_X", &gamepad.buttons , short(XINPUT_GAMEPAD_X)}, - {"XINPUT_GAMEPAD_Y", &gamepad.buttons , short(XINPUT_GAMEPAD_Y)} -}; - -//Setup default settings, can be overwritten by config file (need to be in same order as "mapping") -//Works for Logitech Rumplepad 2 -Ssettings settings[20] = -{ - /*XINPUT_GAMEPAD_LEFT_THUMB_X*/ {'A', 1, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_LEFT_THUMB_Y*/ {'A', 2, short(0xFFFF), -1}, - /*XINPUT_GAMEPAD_RIGHT_THUMB_X*/ {'A', 3, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_RIGHT_THUMB_Y*/ {'A', 4, short(0xFFFF), -1}, - /*XINPUT_GAMEPAD_DPAD_UP*/ {'H', 1, short(SDL_HAT_UP), 1}, - /*XINPUT_GAMEPAD_DPAD_DOWN*/ {'H', 1, short(SDL_HAT_DOWN), 1}, - /*XINPUT_GAMEPAD_DPAD_LEFT*/ {'H', 1, short(SDL_HAT_LEFT), 1}, - /*XINPUT_GAMEPAD_DPAD_RIGHT*/ {'H', 1, short(SDL_HAT_RIGHT),1}, - /*XINPUT_GAMEPAD_START*/ {'B', 10, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_BACK*/ {'B', 9, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_LEFT_THUMB*/ {'B', 11, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_RIGHT_THUMB*/ {'B', 12, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_LEFT_SHOULDER*/ {'B', 5, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_LEFT_SHOULDER2*/ {'B', 7, short(0xFFFF), 255}, //scale 1 to 255 L2 and R2 are analog values in XInput - /*XINPUT_GAMEPAD_RIGHT_SHOULDER*/ {'B', 6, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_RIGHT_SHOULDER2*/{'B', 8, short(0xFFFF), 255}, - /*XINPUT_GAMEPAD_A*/ {'B', 2, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_B*/ {'B', 3, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_X*/ {'B', 1, short(0xFFFF), 1}, - /*XINPUT_GAMEPAD_Y*/ {'B', 4, short(0xFFFF), 1} -}; diff --git a/config.h b/config.h deleted file mode 100644 index 531f153..0000000 --- a/config.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef KOKU_CONFIG_H -#define KOKU_CONFIG_H -#include "xinput.h" - -struct SGamepadData -{ - short left_thumb_x; - short left_thumb_y; - short right_thumb_x; - short right_thumb_y; - short buttons; - short left_shoulder; - short right_shoulder; -}; - -struct Smapping -{ - const char* name; //name of the map - short* addr; //adress to SGamepadData members - short mask; //masking -}; - -struct Ssettings -{ - char type; //A = Axis, B = Button, H = Hat (DPad) - char id; //id of A,B or H - short mask; //masking - short scale; //scaling -}; - -extern const Smapping mapping[20]; -extern Ssettings settings[20]; -extern SGamepadData gamepad; - -#endif diff --git a/main.cpp b/main.cpp index 2185e03..f5b66ae 100644 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include "main.h" #include "device.h" #include +#include using namespace std; #ifdef __LP64__ diff --git a/xinput.cpp b/xinput.cpp old mode 100644 new mode 100755 index ff478b8..0ceab04 --- a/xinput.cpp +++ b/xinput.cpp @@ -1,14 +1,9 @@ #include "xinput.h" -#include "config.h" #include "main.h" -#ifndef USE_SDL2 -#include -#define SDL_INIT_HAPTIC 0 -#define SDL_Haptic void -#else + #include #include -#endif + #include #include #include @@ -17,514 +12,286 @@ #include #include #include + +#define WINE_XINPUT_AXES 8 +#define MAX_XINPUT_BUTTONS 14 using namespace std; bool active = true; struct Sgamepad_sdl { - SDL_Joystick *joystick; - SDL_Haptic *haptic; - int haptic_effects[2]; + SDL_Joystick *joystick; + SDL_GameController* controller; + SDL_Haptic *haptic; + int haptic_effects[2]; }; static vector gamepads_sdl; - +static const unsigned int xbuttons[MAX_XINPUT_BUTTONS] = {XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB, XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT, XINPUT_GAMEPAD_DPAD_UP}; +static const SDL_GameControllerButton sdlbuttons[MAX_XINPUT_BUTTONS] = {SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_LEFTSTICK, SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_LEFT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_UP}; GUID GUID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}}; void GamepadInitSDL() { - static bool inited = false; - if (inited) - { - return; - } - - inited = true; - //init: - SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_HAPTIC); - SDL_JoystickEventState(SDL_IGNORE); - for(int i = 0; i < SDL_NumJoysticks(); ++i) - { - SDL_Joystick* joy = SDL_JoystickOpen(i); - if (joy) - { - Sgamepad_sdl new_gamepad; - new_gamepad.joystick = joy; - new_gamepad.haptic = 0; - //check for haptic - #ifdef USE_SDL2 - new_gamepad.haptic = SDL_HapticOpenFromJoystick(new_gamepad.joystick); - if (new_gamepad.haptic != 0) - { - //start haptic effects - SDL_HapticEffect effect[2]; - memset(&effect, 0, sizeof(SDL_HapticEffect)*2); - - effect[0].type = SDL_HAPTIC_SINE; //constant somehow don't work, or I don't undestand what it does.. - effect[0].periodic.direction.type = SDL_HAPTIC_CARTESIAN; - effect[0].periodic.direction.dir[0] = 1; - effect[0].periodic.period = 0; - effect[0].periodic.magnitude = 0; - effect[0].periodic.length = SDL_HAPTIC_INFINITY; - - effect[1] = effect[0]; - effect[1].periodic.direction.dir[0] = -1; - effect[1].periodic.magnitude = 0; - - new_gamepad.haptic_effects[0] = SDL_HapticNewEffect(new_gamepad.haptic, &(effect[0])); - new_gamepad.haptic_effects[1] = SDL_HapticNewEffect(new_gamepad.haptic, &(effect[1])); - - SDL_HapticRunEffect(new_gamepad.haptic, new_gamepad.haptic_effects[0], 1); - SDL_HapticRunEffect(new_gamepad.haptic, new_gamepad.haptic_effects[1], 1); - } - #endif - gamepads_sdl.push_back(new_gamepad); - } - } - - XINPUT_VIBRATION welcome_vibration; - welcome_vibration.wLeftMotorSpeed = 65535; - welcome_vibration.wRightMotorSpeed = 0; - XInputSetState(0, &welcome_vibration); - SDL_Delay(250); - welcome_vibration.wLeftMotorSpeed = 0; - welcome_vibration.wRightMotorSpeed = 0; - XInputSetState(0, &welcome_vibration); - SDL_Delay(250); - welcome_vibration.wLeftMotorSpeed = 0; - welcome_vibration.wRightMotorSpeed = 65535; - XInputSetState(0, &welcome_vibration); - SDL_Delay(250); - welcome_vibration.wLeftMotorSpeed = 0; - welcome_vibration.wRightMotorSpeed = 0; - XInputSetState(0, &welcome_vibration); - - //load config: - string path = string(getenv("HOME"))+"/.config/koku-xinput-wine.ini"; - ifstream iconfig(path.c_str(), ifstream::in); - if (iconfig.is_open()) - { - if (debug) - { - clog << "koku-xinput-wine: Load config \"" << path << "\"" << endl; - } - //load config - - while (iconfig.good()) - { - string line; - std::getline(iconfig, line); - - if (line.size() == 0) - { - //empty line - continue; - } - - if (line[0] == ';') - { - //comment - continue; - } - - int pos = 0; - //read until not A-Z a-z 0-9 - string name; - while(pos < line.size()) - { - char c = line[pos++]; - if (((c >= 'A')&&(c <= 'Z')) || - ((c >= 'a')&&(c <= 'z')) || - ((c >= '0')&&(c <= '9')) || (c == '_')) - { - name += c; - } - else - { - break; - } - } - - //search name in mapping - for(int i = 0; i < 20; ++i) - { - if (mapping[i].name == name) - { - //name found - if (debug) - { - clog << "koku-xinput-wine: Load parameter for \"" << name << "\"" << endl; - } - //read until "=" - while(pos < line.size()) - { - char c = line[pos++]; - if (c == '=') - { - break; - } - } - - //read until A-Z a-z 0-9 - while(pos < line.size()) - { - char c = line[pos++]; - if (((c >= 'A')&&(c <= 'Z')) || - ((c >= 'a')&&(c <= 'z')) || - ((c >= '0')&&(c <= '9'))) - { - --pos; - break; - } - } - - if (pos >= line.size()) break; - - //read the type - settings[i].type = line[pos++]; - settings[i].mask = short(0xFFFF); - settings[i].scale = 1; - settings[i].id = 0; - - if (debug) - { - switch(settings[i].type) - { - case 'A': - clog << "koku-xinput-wine: Type = Axis" << endl; - break; - case 'B': - clog << "koku-xinput-wine: Type = Buttons" << endl; - break; - case 'H': - clog << "koku-xinput-wine: Type = Hats" << endl; - break; - default: - clog << "koku-xinput-wine: Type = Unknow" << endl; - break; - } - } - - if (pos >= line.size()) break; - - //parse number - { - stringstream ss(string(line.c_str()+pos, line.size()-pos)); - int id; - ss >> id; - settings[i].id = id; - } - - if (debug) - { - clog << "koku-xinput-wine: Id = " << right << setw(2) << setfill('0') << int(settings[i].id) << setfill(' ') << setw(0) << left << endl; - } - - //read until '&' - while(pos < line.size()) - { - char c = line[pos++]; - if (c == '&') - { - pos--; - break; - } - if (c == '*') - { - pos--; - break; - } - } - - if (pos >= line.size()) break; - - if (line[pos++] == '&') - { - if (pos >= line.size()) break; - if (line[pos++] != '0') break; - if (pos >= line.size()) break; - if (line[pos++] != 'x') break; - if (pos >= line.size()) break; - - //parse number - { - stringstream ss(string(line.c_str()+pos, line.size()-pos)); - int mask; - ss >> hex >> mask >> dec; - settings[i].mask = short(mask); - } - - if (debug) - { - clog << "koku-xinput-wine: Mask = 0x" << right << setw(4) << setfill('0') << hex << settings[i].mask << setfill(' ') << dec << setw(0) << left << endl; - } - - //read until '*' - while(pos < line.size()) - { - char c = line[pos++]; - if (c == '*') - { - break; - } - } - } - - if (pos >= line.size()) break; - - //parse number - { - stringstream ss(string(line.c_str()+pos, line.size()-pos)); - ss >> settings[i].scale; - } - - if (debug) - { - clog << "koku-xinput-wine: Scale = " << settings[i].scale << endl; - } - - //exit loop - break; - } - } - } - - iconfig.close(); - } - else - { - if (debug) - { - clog << "koku-xinput-wine: Save default config \"" << path << "\"" << endl; - } - //write default config - ofstream oconfig(path.c_str(), ifstream::out); - if (oconfig.is_open()) - { - oconfig << ";koku-xinput-wine config, for more information see https://github.com/KoKuToru/koku-xinput-wine" << endl; - for(int i = 0; i < 20; ++i) - { - oconfig << left << setw(30) << mapping[i].name << " = " << right << settings[i].type << setfill('0') << setw(2) << int(settings[i].id) << setfill(' ') ; - if (settings[i].mask != short(0xFFFF)) - { - oconfig << "&0x" << setfill('0') << setw(4) << hex << settings[i].mask << setfill(' ') << dec; - } - if (settings[i].scale != 1) - { - oconfig << "*" << settings[i].scale; - } - oconfig << endl; - } - oconfig.close(); - }else - { - clog << "koku-xinput-wine: couldn't open file" << endl; - } - } + static bool inited = false; + if (inited) + { + return; + } + + inited = true; + //init: + SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_HAPTIC|SDL_INIT_GAMECONTROLLER); + SDL_JoystickEventState(SDL_IGNORE); + SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt"); + for(int i = 0; i < SDL_NumJoysticks(); ++i) + { + SDL_Joystick* joy = SDL_JoystickOpen(i); + if (joy) + { + Sgamepad_sdl new_gamepad; + SDL_GameController* controller = SDL_GameControllerOpen(i); + if (controller) { + + new_gamepad.joystick = joy; + new_gamepad.controller = controller; + new_gamepad.haptic = 0; + //check for haptic + + new_gamepad.haptic = SDL_HapticOpenFromJoystick(new_gamepad.joystick); + if (new_gamepad.haptic != 0) + { + //start haptic effects + SDL_HapticEffect effect[2]; + memset(&effect, 0, sizeof(SDL_HapticEffect)*2); + + effect[0].type = SDL_HAPTIC_SINE; //constant somehow don't work, or I don't undestand what it does.. + effect[0].periodic.direction.type = SDL_HAPTIC_CARTESIAN; + effect[0].periodic.direction.dir[0] = 1; + effect[0].periodic.period = 0; + effect[0].periodic.magnitude = 0; + effect[0].periodic.length = SDL_HAPTIC_INFINITY; + + effect[1] = effect[0]; + effect[1].periodic.direction.dir[0] = -1; + effect[1].periodic.magnitude = 0; + + new_gamepad.haptic_effects[0] = SDL_HapticNewEffect(new_gamepad.haptic, &(effect[0])); + new_gamepad.haptic_effects[1] = SDL_HapticNewEffect(new_gamepad.haptic, &(effect[1])); + + SDL_HapticRunEffect(new_gamepad.haptic, new_gamepad.haptic_effects[0], 1); + SDL_HapticRunEffect(new_gamepad.haptic, new_gamepad.haptic_effects[1], 1); + } + gamepads_sdl.push_back(new_gamepad); + } + + } + } + + XINPUT_VIBRATION welcome_vibration; + welcome_vibration.wLeftMotorSpeed = 65535; + welcome_vibration.wRightMotorSpeed = 0; + XInputSetState(0, &welcome_vibration); + SDL_Delay(250); + welcome_vibration.wLeftMotorSpeed = 0; + welcome_vibration.wRightMotorSpeed = 0; + XInputSetState(0, &welcome_vibration); + SDL_Delay(250); + welcome_vibration.wLeftMotorSpeed = 0; + welcome_vibration.wRightMotorSpeed = 65535; + XInputSetState(0, &welcome_vibration); + SDL_Delay(250); + welcome_vibration.wLeftMotorSpeed = 0; + welcome_vibration.wRightMotorSpeed = 0; + XInputSetState(0, &welcome_vibration); } void WINAPI XInputEnable(bool enable) { - if (!enable) - { - XINPUT_VIBRATION stop_vibration; - stop_vibration.wLeftMotorSpeed = 0; - stop_vibration.wRightMotorSpeed = 0; - for(int i = 0; i < 4; ++i) - { - XInputSetState(i, &stop_vibration); - } - } - active = enable; + if (!enable) + { + XINPUT_VIBRATION stop_vibration; + stop_vibration.wLeftMotorSpeed = 0; + stop_vibration.wRightMotorSpeed = 0; + for(int i = 0; i < 4; ++i) + { + XInputSetState(i, &stop_vibration); + } + } + active = enable; } unsigned WINAPI XInputGetAudioDeviceIds(unsigned dwUserIndex, short* pRenderDeviceId, unsigned *pRenderCount, short* pCaptureDeviceId, unsigned *pCaptureCount) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - /* - If there is no headset connected to the controller, - the function will also retrieve ERROR_SUCCESS with NULL as the values - for pRenderDeviceId and pCaptureDeviceId. - */ - *pRenderDeviceId = 0; - *pCaptureDeviceId = 0; - return ERROR_SUCCESS; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + /* + If there is no headset connected to the controller, + the function will also retrieve ERROR_SUCCESS with NULL as the values + for pRenderDeviceId and pCaptureDeviceId. + */ + *pRenderDeviceId = 0; + *pCaptureDeviceId = 0; + return ERROR_SUCCESS; } unsigned WINAPI XInputGetBatteryInformation(unsigned dwUserIndex, char devType, XINPUT_BATTERY_INFORMATION *pBatteryInformation) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - if (devType == BATTERY_DEVTYPE_GAMEPAD) - { - //sorry no real battery check - pBatteryInformation->BatteryType = BATTERY_TYPE_WIRED; - pBatteryInformation->BatteryLevel = BATTERY_LEVEL_FULL; - } - else - { - pBatteryInformation->BatteryType = BATTERY_TYPE_DISCONNECTED; - pBatteryInformation->BatteryLevel = BATTERY_LEVEL_EMPTY; - } - return ERROR_SUCCESS; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + if (devType == BATTERY_DEVTYPE_GAMEPAD) + { + //sorry no real battery check + pBatteryInformation->BatteryType = BATTERY_TYPE_WIRED; + pBatteryInformation->BatteryLevel = BATTERY_LEVEL_FULL; + } + else + { + pBatteryInformation->BatteryType = BATTERY_TYPE_DISCONNECTED; + pBatteryInformation->BatteryLevel = BATTERY_LEVEL_EMPTY; + } + return ERROR_SUCCESS; } unsigned WINAPI XInputGetCapabilities(unsigned dwUserIndex, unsigned dwFlags, XINPUT_CAPABILITIES *pCapabilities) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - pCapabilities->Type = XINPUT_DEVTYPE_GAMEPAD; - pCapabilities->SubType = XINPUT_DEVSUBTYPE_GAMEPAD; - pCapabilities->Flags = (gamepads_sdl[dwUserIndex].haptic != 0)?XINPUT_CAPS_FFB_SUPPORTED:0; - pCapabilities->Gamepad.wButtons = 0xFFFF; - pCapabilities->Gamepad.bLeftTrigger = 255; - pCapabilities->Gamepad.bRightTrigger = 255; - pCapabilities->Gamepad.sThumbLX = 32767; - pCapabilities->Gamepad.sThumbLY = 32767; - pCapabilities->Gamepad.xThumbRX = 32767; - pCapabilities->Gamepad.xThumbRY = 32767; - if (gamepads_sdl[dwUserIndex].haptic != 0) - { - pCapabilities->Vibration.wLeftMotorSpeed = 65535; - pCapabilities->Vibration.wRightMotorSpeed = 65535; - } - else - { - pCapabilities->Vibration.wLeftMotorSpeed = 0; - pCapabilities->Vibration.wRightMotorSpeed = 0; - } - return ERROR_SUCCESS; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + pCapabilities->Type = XINPUT_DEVTYPE_GAMEPAD; + pCapabilities->SubType = XINPUT_DEVSUBTYPE_GAMEPAD; + pCapabilities->Flags = (gamepads_sdl[dwUserIndex].haptic != 0)?XINPUT_CAPS_FFB_SUPPORTED:0; + pCapabilities->Gamepad.wButtons = 0xFFFF; + pCapabilities->Gamepad.bLeftTrigger = 255; + pCapabilities->Gamepad.bRightTrigger = 255; + pCapabilities->Gamepad.sThumbLX = 32767; + pCapabilities->Gamepad.sThumbLY = 32767; + pCapabilities->Gamepad.sThumbRX = 32767; + pCapabilities->Gamepad.sThumbRY = 32767; + if (gamepads_sdl[dwUserIndex].haptic != 0) + { + pCapabilities->Vibration.wLeftMotorSpeed = 65535; + pCapabilities->Vibration.wRightMotorSpeed = 65535; + } + else + { + pCapabilities->Vibration.wLeftMotorSpeed = 0; + pCapabilities->Vibration.wRightMotorSpeed = 0; + } + return ERROR_SUCCESS; } unsigned WINAPI XInputGetDSoundAudioDeviceGuids(unsigned dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - /* - If there is no headset connected to the controller, - the function also retrieves ERROR_SUCCESS with GUID_NULL as the values - for pDSoundRenderGuid and pDSoundCaptureGuid. - */ - *pDSoundRenderGuid = GUID_NULL; - *pDSoundCaptureGuid = GUID_NULL; - return ERROR_SUCCESS; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + /* + If there is no headset connected to the controller, + the function also retrieves ERROR_SUCCESS with GUID_NULL as the values + for pDSoundRenderGuid and pDSoundCaptureGuid. + */ + *pDSoundRenderGuid = GUID_NULL; + *pDSoundCaptureGuid = GUID_NULL; + return ERROR_SUCCESS; } unsigned WINAPI XInputGetKeystroke(unsigned dwUserIndex, unsigned dwReserved, XINPUT_KEYSTROKE* pKeystroke) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - //If no new keys have been pressed, the return value is ERROR_EMPTY. - return ERROR_EMPTY; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + //If no new keys have been pressed, the return value is ERROR_EMPTY. + return ERROR_EMPTY; } unsigned WINAPI XInputGetState(unsigned dwUserIndex, XINPUT_STATE *pState) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - SDL_JoystickUpdate(); - //load data - for(int i = 0; i < 20; ++i) - { - short value = 0; - switch(settings[i].type) - { - case 'A': - value = max(SDL_JoystickGetAxis(gamepads_sdl[dwUserIndex].joystick , settings[i].id-1)&settings[i].mask, -32767)*settings[i].scale; - break; - case 'H': - value = max(SDL_JoystickGetHat(gamepads_sdl[dwUserIndex].joystick , settings[i].id-1)&settings[i].mask, -32767)*settings[i].scale; - break; - case 'B': - value = max(SDL_JoystickGetButton(gamepads_sdl[dwUserIndex].joystick , settings[i].id-1)&settings[i].mask, -32767)*settings[i].scale; - break; - default: - //uhm - break; - } - if (mapping[i].mask == 0) - { - *(mapping[i].addr) = value; - } - else if (value != 0) - { - *(mapping[i].addr) |= mapping[i].mask; - } - else - { - *(mapping[i].addr) &= (~mapping[i].mask); - } - } - - //set data - static int dwPacketNumber = 0; - pState->dwPacketNumber = ++dwPacketNumber; - pState->Gamepad.wButtons = *(reinterpret_cast(&gamepad.buttons)); - pState->Gamepad.bLeftTrigger = gamepad.left_shoulder; - pState->Gamepad.bRightTrigger = gamepad.right_shoulder; - pState->Gamepad.sThumbLX = gamepad.left_thumb_x; - pState->Gamepad.sThumbLY = gamepad.left_thumb_y; - pState->Gamepad.xThumbRX = gamepad.right_thumb_x; - pState->Gamepad.xThumbRY = gamepad.right_thumb_y; - return ERROR_SUCCESS; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + SDL_JoystickUpdate(); + SDL_GameControllerUpdate(); + + //set data + SDL_GameController* controller = gamepads_sdl[dwUserIndex].controller; + + for (int j = 0; j < MAX_XINPUT_BUTTONS; j++) { + + Uint8 result = SDL_GameControllerGetButton(controller, sdlbuttons[j]); + //printf("result for %d: %d\n", j, result); + if (result) { + pState->Gamepad.wButtons |= xbuttons[j]; + } + else { + pState->Gamepad.wButtons &= ~(xbuttons[j]); + } + } + + short ly = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + short ry = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); + + pState->Gamepad.sThumbLX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); + pState->Gamepad.sThumbLY = (ly == 0 ? 0 : -ly -1); + pState->Gamepad.sThumbRX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); + pState->Gamepad.sThumbRY = ry == 0 ? 0 : -ry -1; + pState->Gamepad.bLeftTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT); + pState->Gamepad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); + + static int dwPacketNumber = 0; + pState->dwPacketNumber = ++dwPacketNumber; + + return ERROR_SUCCESS; } unsigned WINAPI XInputSetState(unsigned dwUserIndex, XINPUT_VIBRATION *pVibration) { - GamepadInitSDL(); - if (dwUserIndex >= gamepads_sdl.size()) - { - return ERROR_DEVICE_NOT_CONNECTED; - } - - if (active) - { - //Sorry no vibration in SDL1.2, maybe SDL2 - #ifdef USE_SDL2 - if (gamepads_sdl[dwUserIndex].haptic != 0) - { - SDL_HapticEffect effect[2]; - memset(&effect, 0, sizeof(SDL_HapticEffect)*2); - - effect[0].type = SDL_HAPTIC_SINE; - effect[0].periodic.direction.type = SDL_HAPTIC_CARTESIAN; - effect[0].periodic.direction.dir[0] = 1; - effect[0].periodic.period = 0; - effect[0].periodic.magnitude = pVibration->wLeftMotorSpeed>>1; - effect[0].periodic.length = SDL_HAPTIC_INFINITY; - - effect[1] = effect[0]; - effect[1].periodic.direction.dir[0] = -1; - effect[1].periodic.magnitude = pVibration->wRightMotorSpeed>>1; - - SDL_HapticUpdateEffect(gamepads_sdl[dwUserIndex].haptic, gamepads_sdl[dwUserIndex].haptic_effects[0], &(effect[0])); - SDL_HapticUpdateEffect(gamepads_sdl[dwUserIndex].haptic, gamepads_sdl[dwUserIndex].haptic_effects[1], &(effect[1])); - } - #endif - } - return ERROR_SUCCESS; + GamepadInitSDL(); + if (dwUserIndex >= gamepads_sdl.size()) + { + return ERROR_DEVICE_NOT_CONNECTED; + } + + if (active) + { + if (gamepads_sdl[dwUserIndex].haptic != 0) + { + SDL_HapticEffect effect[2]; + memset(&effect, 0, sizeof(SDL_HapticEffect)*2); + + effect[0].type = SDL_HAPTIC_SINE; + effect[0].periodic.direction.type = SDL_HAPTIC_CARTESIAN; + effect[0].periodic.direction.dir[0] = 1; + effect[0].periodic.period = 0; + effect[0].periodic.magnitude = pVibration->wLeftMotorSpeed>>1; + effect[0].periodic.length = SDL_HAPTIC_INFINITY; + + effect[1] = effect[0]; + effect[1].periodic.direction.dir[0] = -1; + effect[1].periodic.magnitude = pVibration->wRightMotorSpeed>>1; + + SDL_HapticUpdateEffect(gamepads_sdl[dwUserIndex].haptic, gamepads_sdl[dwUserIndex].haptic_effects[0], &(effect[0])); + SDL_HapticUpdateEffect(gamepads_sdl[dwUserIndex].haptic, gamepads_sdl[dwUserIndex].haptic_effects[1], &(effect[1])); + } + } + return ERROR_SUCCESS; } diff --git a/xinput.h b/xinput.h old mode 100644 new mode 100755 index 0911459..8d507c5 --- a/xinput.h +++ b/xinput.h @@ -40,8 +40,8 @@ struct XINPUT_GAMEPAD unsigned char bRightTrigger; short sThumbLX; short sThumbLY; - short xThumbRX; - short xThumbRY; + short sThumbRX; + short sThumbRY; }; struct XINPUT_STATE