From 85a132c149381ff903db0beb6b0d08a136aad689 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Tue, 23 Aug 2022 00:05:50 -0500 Subject: [PATCH] Port Ediolon's SDL GameController work Basically instantly solved all of the issues that made this branch completely unusable --- src/g_input.c | 161 ++++++++++++++++++++------------------------- src/g_input.h | 15 +++-- src/k_menufunc.c | 97 +++++++++++++-------------- src/sdl/i_system.c | 126 +++++++++++++++-------------------- src/sdl/i_video.c | 108 +++++++++--------------------- src/sdl/sdlmain.h | 14 ++-- 6 files changed, 220 insertions(+), 301 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index 120dd6a79..ead8cab27 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -173,7 +173,7 @@ void G_MapEventsToControls(event_t *ev) break; case ev_joystick: // buttons are virtual keys - if (ev->data1 >= JOYAXISSET) + if (ev->data1 >= JOYAXISSETS) { #ifdef PARANOIA CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1); @@ -181,37 +181,56 @@ void G_MapEventsToControls(event_t *ev) break; } - i = ev->data1 * 4; + i = ev->data1; - if (ev->data2 != INT32_MAX) + if (i >= JOYANALOGS) { - if (ev->data2 < 0) + // The trigger axes are handled specially. + i -= JOYANALOGS; + + if (ev->data2 != INT32_MAX) { - // Left - gamekeydown[ev->device][KEY_AXIS1 + i] = abs(ev->data2); - gamekeydown[ev->device][KEY_AXIS1 + i + 1] = 0; + gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2); } - else + + if (ev->data3 != INT32_MAX) { - // Right - gamekeydown[ev->device][KEY_AXIS1 + i] = 0; - gamekeydown[ev->device][KEY_AXIS1 + i + 1] = abs(ev->data2); + gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3); } } - - if (ev->data3 != INT32_MAX) + else { - if (ev->data3 < 0) + // Actual analog sticks + if (ev->data2 != INT32_MAX) { - // Up - gamekeydown[ev->device][KEY_AXIS1 + i + 2] = abs(ev->data3); - gamekeydown[ev->device][KEY_AXIS1 + i + 3] = 0; + if (ev->data2 < 0) + { + // Left + gamekeydown[ev->device][KEY_AXIS1 + (i * 4)] = abs(ev->data2); + gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 1] = 0; + } + else + { + // Right + gamekeydown[ev->device][KEY_AXIS1 + (i * 4)] = 0; + gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2); + } } - else + + if (ev->data3 != INT32_MAX) { - // Down - gamekeydown[ev->device][KEY_AXIS1 + i + 2] = 0; - gamekeydown[ev->device][KEY_AXIS1 + i + 3] = abs(ev->data3); + if (ev->data3 < 0) + { + // Up + gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3); + gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 3] = 0; + } + else + { + // Down + gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 2] = 0; + gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3); + } } } break; @@ -316,76 +335,38 @@ static keyname_t keynames[] = {KEY_MOUSEWHEELUP, "Wheel Up"}, {KEY_MOUSEWHEELDOWN, "Wheel Down"}, - {KEY_JOY1+0, "JOY1"}, - {KEY_JOY1+1, "JOY2"}, - {KEY_JOY1+2, "JOY3"}, - {KEY_JOY1+3, "JOY4"}, - {KEY_JOY1+4, "JOY5"}, - {KEY_JOY1+5, "JOY6"}, - {KEY_JOY1+6, "JOY7"}, - {KEY_JOY1+7, "JOY8"}, - {KEY_JOY1+8, "JOY9"}, -#if !defined (NOMOREJOYBTN_1S) - // we use up to 32 buttons in DirectInput - {KEY_JOY1+9, "JOY10"}, - {KEY_JOY1+10, "JOY11"}, - {KEY_JOY1+11, "JOY12"}, - {KEY_JOY1+12, "JOY13"}, - {KEY_JOY1+13, "JOY14"}, - {KEY_JOY1+14, "JOY15"}, - {KEY_JOY1+15, "JOY16"}, - {KEY_JOY1+16, "JOY17"}, - {KEY_JOY1+17, "JOY18"}, - {KEY_JOY1+18, "JOY19"}, - {KEY_JOY1+19, "JOY20"}, - {KEY_JOY1+20, "JOY21"}, - {KEY_JOY1+21, "JOY22"}, - {KEY_JOY1+22, "JOY23"}, - {KEY_JOY1+23, "JOY24"}, - {KEY_JOY1+24, "JOY25"}, - {KEY_JOY1+25, "JOY26"}, - {KEY_JOY1+26, "JOY27"}, - {KEY_JOY1+27, "JOY28"}, - {KEY_JOY1+28, "JOY29"}, - {KEY_JOY1+29, "JOY30"}, - {KEY_JOY1+30, "JOY31"}, - {KEY_JOY1+31, "JOY32"}, -#endif + {KEY_JOY1+0, "A BUTTON"}, + {KEY_JOY1+1, "B BUTTON"}, + {KEY_JOY1+2, "X BUTTON"}, + {KEY_JOY1+3, "Y BUTTON"}, + {KEY_JOY1+4, "BACK BUTTON"}, + {KEY_JOY1+5, "GUIDE BUTTON"}, + {KEY_JOY1+6, "START BUTTON"}, + {KEY_JOY1+7, "L-STICK CLICK"}, + {KEY_JOY1+8, "R-STICK CLICK"}, + {KEY_JOY1+9, "L BUMPER"}, + {KEY_JOY1+10, "R BUMPER"}, + {KEY_JOY1+11, "D-PAD UP"}, + {KEY_JOY1+12, "D-PAD DOWN"}, + {KEY_JOY1+13, "D-PAD LEFT"}, + {KEY_JOY1+14, "D-PAD RIGHT"}, + {KEY_JOY1+15, "MISC. BUTTON"}, + {KEY_JOY1+16, "PADDLE1 BUTTON"}, + {KEY_JOY1+17, "PADDLE2 BUTTON"}, + {KEY_JOY1+18, "PADDLE3 BUTTON"}, + {KEY_JOY1+19, "PADDLE4 BUTTON"}, + {KEY_JOY1+20, "TOUCHPAD"}, - // the DOS version uses Allegro's joystick support - {KEY_HAT1+0, "HATUP"}, - {KEY_HAT1+1, "HATDOWN"}, - {KEY_HAT1+2, "HATLEFT"}, - {KEY_HAT1+3, "HATRIGHT"}, - {KEY_HAT1+4, "HATUP2"}, - {KEY_HAT1+5, "HATDOWN2"}, - {KEY_HAT1+6, "HATLEFT2"}, - {KEY_HAT1+7, "HATRIGHT2"}, - {KEY_HAT1+8, "HATUP3"}, - {KEY_HAT1+9, "HATDOWN3"}, - {KEY_HAT1+10, "HATLEFT3"}, - {KEY_HAT1+11, "HATRIGHT3"}, - {KEY_HAT1+12, "HATUP4"}, - {KEY_HAT1+13, "HATDOWN4"}, - {KEY_HAT1+14, "HATLEFT4"}, - {KEY_HAT1+15, "HATRIGHT4"}, - - {KEY_AXIS1+0, "AXISX-"}, - {KEY_AXIS1+1, "AXISX+"}, - {KEY_AXIS1+2, "AXISY-"}, - {KEY_AXIS1+3, "AXISY+"}, - {KEY_AXIS1+4, "AXISZ-"}, - {KEY_AXIS1+5, "AXISZ+"}, - {KEY_AXIS1+6, "AXISXRUDDER-"}, - {KEY_AXIS1+7, "AXISXRUDDER+"}, - {KEY_AXIS1+8, "AXISYRUDDER-"}, - {KEY_AXIS1+9, "AXISYRUDDER+"}, - {KEY_AXIS1+10, "AXISZRUDDER-"}, - {KEY_AXIS1+11, "AXISZRUDDER+"}, - {KEY_AXIS1+12, "AXISU-"}, - {KEY_AXIS1+13, "AXISU+"}, - {KEY_AXIS1+14, "AXISV-"}, - {KEY_AXIS1+15, "AXISV+"}, + {KEY_AXIS1+0, "L-STICK LEFT"}, + {KEY_AXIS1+1, "L-STICK RIGHT"}, + {KEY_AXIS1+2, "L-STICK UP"}, + {KEY_AXIS1+3, "L-STICK DOWN"}, + {KEY_AXIS1+4, "R-STICK LEFT"}, + {KEY_AXIS1+5, "R-STICK RIGHT"}, + {KEY_AXIS1+6, "R-STICK UP"}, + {KEY_AXIS1+7, "R-STICK DOWN"}, + {KEY_AXIS1+8, "L TRIGGER"}, + {KEY_AXIS1+9, "R TRIGGER"}, }; static const char *gamecontrolname[num_gamecontrols] = diff --git a/src/g_input.h b/src/g_input.h index ae9b130bc..14aa5aba3 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -23,9 +23,12 @@ #define NUMKEYS 256 #define MOUSEBUTTONS 8 -#define JOYBUTTONS 32 // 32 buttons -#define JOYHATS 4 // 4 hats -#define JOYAXISSET 4 // 4 Sets of 2 axises + +#define JOYBUTTONS 21 // 21 buttons, to match SDL_GameControllerButton +#define JOYANALOGS 2 // 2 sets of analog stick axes, with positive and negative each +#define JOYTRIGGERS 1 // 1 set of trigger axes, positive only +#define JOYAXISSETS (JOYANALOGS + JOYTRIGGERS) +#define JOYAXES ((4 * JOYANALOGS) + (2 * JOYTRIGGERS)) #define MAXINPUTMAPPING 4 @@ -35,9 +38,9 @@ typedef enum { KEY_JOY1 = NUMKEYS, - KEY_HAT1 = KEY_JOY1 + JOYBUTTONS, - KEY_AXIS1 = KEY_HAT1 + JOYHATS*4, - JOYINPUTEND = KEY_AXIS1 + JOYAXISSET*2*2, // 4 sets of 2 axes, each with positive & negative + KEY_HAT1 = KEY_JOY1 + 11, // macro for SDL_CONTROLLER_BUTTON_DPAD_UP + KEY_AXIS1 = KEY_JOY1 + JOYBUTTONS, + JOYINPUTEND = KEY_AXIS1 + JOYAXES, KEY_MOUSE1 = JOYINPUTEND, KEY_MOUSEMOVE = KEY_MOUSE1 + MOUSEBUTTONS, diff --git a/src/k_menufunc.c b/src/k_menufunc.c index f2b9133fb..fe62e82b5 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -2418,10 +2418,14 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num) // this is to allow them to retain controller usage when they play alone. // Because let's face it, when you test mods, you're often lazy to grab your controller for menuing :) if (!i && !num) + { setup_player[num].ponedevice = cv_usejoystick[num].value; + } else if (num) + { // For any player past player 1, set controls to default profile controls, otherwise it's generally awful to do any menuing... memcpy(&gamecontrol[num], gamecontroldefault, sizeof(gamecontroldefault)); + } CV_SetValue(&cv_usejoystick[num], i); @@ -3132,7 +3136,9 @@ void M_CharacterSelectTick(void) // P1 is alone, set their old device just in case. if (setup_numplayers < 2 && setup_player[0].ponedevice) + { CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice); + } M_SetupNextMenu(&PLAY_MainDef, false); } @@ -5307,7 +5313,7 @@ void M_MapProfileControl(event_t *ev) #endif break; case ev_joystick: - if (ev->data1 >= JOYAXISSET) + if (ev->data1 >= JOYAXES) { #ifdef PARANOIA CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1); @@ -5320,65 +5326,58 @@ void M_MapProfileControl(event_t *ev) boolean responsivelr = ((ev->data2 != INT32_MAX) && (abs(ev->data2) >= deadzone)); boolean responsiveud = ((ev->data3 != INT32_MAX) && (abs(ev->data3) >= deadzone)); - // Only consider unambiguous assignment. - if (responsivelr == responsiveud) - return; + i = ev->data1; - i = (ev->data1 * 4); - - if (responsivelr) + if (i >= JOYANALOGS) { - if (ev->data2 < 0) + // The trigger axes are handled specially. + i -= JOYANALOGS; + + if (responsivelr) { - // Left - c = KEY_AXIS1 + i; + c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2); } - else + else if (responsiveud) { - // Right - c = KEY_AXIS1 + i + 1; + c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1; } } - else //if (responsiveud) + else { - if (ev->data3 < 0) + // Actual analog sticks + + // Only consider unambiguous assignment. + if (responsivelr == responsiveud) + return; + + if (responsivelr) { - // Up - c = KEY_AXIS1 + i + 2; + if (ev->data2 < 0) + { + // Left + c = KEY_AXIS1 + (i * 4); + } + else + { + // Right + c = KEY_AXIS1 + (i * 4) + 1; + } } - else + else //if (responsiveud) { - // Down - c = KEY_AXIS1 + i + 3; + if (ev->data3 < 0) + { + // Up + c = KEY_AXIS1 + (i * 4) + 2; + } + else + { + // Down + c = KEY_AXIS1 + (i * 4) + 3; + } } } } - - /* I hate this. - I shouldn't have to do this. - But we HAVE to because of some controllers, INCLUDING MINE. - - Triggers on X360 controllers go from -1024 when not held - To 1023 when pressed. - The result is that pressing the trigger makes the game THINK the input is for a negative value. - Which then means that the input is considered pressed when the trigger is released. - - So what we're going to do is make sure that the detected 'c' key is the same for multiple rolls of ev_joystick. - NOTE: We need the player to press the key all the way down otherwise this might just not work... - - @TODO: This isn't entirely consistent because we only check for events..... maybe check continuously for gamekeydown[]? - but this seems messy... - */ - - //CONS_Printf("mapping joystick ... attempt (%d)\n", optionsmenu.keyheldfor); - - if (c != optionsmenu.lastkey) - { - optionsmenu.lastkey = c; - optionsmenu.keyheldfor = 0; - return; - } - break; default: return; @@ -5411,7 +5410,8 @@ void M_MapProfileControl(event_t *ev) // If possible, reapply the profile... // 19/05/22: Actually, no, don't do that, it just fucks everything up in too many cases. - /*if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked. + /* + if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked. { // Apply the profile's properties to player 1 but keep the last profile cv to p1's ACTUAL profile to revert once we exit. UINT8 lastp = cv_lastprofile[0].value; @@ -5430,7 +5430,8 @@ void M_MapProfileControl(event_t *ev) break; } } - }*/ + } + */ } #undef KEYHOLDFOR diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 6ad02df07..a89dd649c 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -200,12 +200,12 @@ static char returnWadPath[256]; #include "../byteptr.h" #endif -void I_StoreExJoystick(SDL_Joystick *dev) +void I_StoreExJoystick(SDL_GameController *dev) { // ExJoystick is a massive hack to avoid needing to completely // rewrite pretty much all of the controller support from scratch... - // Used in favor of most instances of SDL_JoystickClose. + // Used in favor of most instances of SDL_GameControllerClose. // If a joystick would've been discarded, then save it in an array, // because we want it have it for the joystick input screen. @@ -217,12 +217,12 @@ void I_StoreExJoystick(SDL_Joystick *dev) return; } - index = SDL_JoystickInstanceID(dev); + index = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(dev)); if (index >= MAXGAMEPADS || index < 0) { // Not enough space to save this joystick, completely discard. - SDL_JoystickClose(dev); + SDL_GameControllerClose(dev); return; } @@ -235,7 +235,7 @@ void I_StoreExJoystick(SDL_Joystick *dev) if (ExJoystick[index] != NULL) { // Discard joystick in the old slot. - SDL_JoystickClose(ExJoystick[index]); + SDL_GameControllerClose(ExJoystick[index]); } // Keep for safe-keeping. @@ -267,7 +267,7 @@ static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; /** \brief SDL info about joystick 1 */ SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; -SDL_Joystick *ExJoystick[MAXGAMEPADS]; +SDL_GameController *ExJoystick[MAXGAMEPADS]; SDL_bool consolevent = SDL_FALSE; SDL_bool framebuffer = SDL_FALSE; @@ -989,29 +989,16 @@ void I_JoyScale4(void) JoyInfo[3].scale = Joystick[3].bGamepadStyle?1:cv_joyscale[1].value; } -// Cheat to get the device index for a joystick handle -INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev) +// Cheat to get the device index for a game controller handle +INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev) { - INT32 i, count = SDL_NumJoysticks(); + SDL_Joystick *joystick = NULL; - for (i = 0; dev && i < count; i++) + joystick = SDL_GameControllerGetJoystick(dev); + + if (joystick) { - SDL_Joystick *test = SDL_JoystickOpen(i); - if (test && test == dev) - return i; - else - { - UINT8 j; - - for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) - { - if (JoyInfo[j].dev == test) - break; - } - - if (j == MAXSPLITSCREENPLAYERS) - I_StoreExJoystick(test); - } + return SDL_JoystickInstanceID(joystick); } return -1; @@ -1082,7 +1069,7 @@ void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer) */ void I_ShutdownJoystick(UINT8 index) { - INT32 i, j; + INT32 i; event_t event; event.device = I_GetJoystickDeviceIndex(JoyInfo[index].dev); @@ -1093,23 +1080,13 @@ void I_ShutdownJoystick(UINT8 index) // emulate the up of all joystick buttons for (i = 0; i < JOYBUTTONS; i++) { - event.data1=KEY_JOY1+i; + event.data1 = KEY_JOY1+i; D_PostEvent(&event); } - // emulate the up of all joystick hats - for (i = 0; i < JOYHATS*4; i++) - { - for (j = 0; j < 4; j++) - { - event.data1 = KEY_HAT1 + (i * 4) + j; - D_PostEvent(&event); - } - } - // reset joystick position event.type = ev_joystick; - for (i = 0; i < JOYAXISSET; i++) + for (i = 0; i < JOYAXES; i++) { event.data1 = i; D_PostEvent(&event); @@ -1131,7 +1108,7 @@ void I_ShutdownJoystick(UINT8 index) */ static int joy_open(int playerIndex, int joyIndex) { - SDL_Joystick *newdev = NULL; + SDL_GameController *newdev = NULL; int num_joy = 0; if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) @@ -1140,6 +1117,12 @@ static int joy_open(int playerIndex, int joyIndex) return -1; } + if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0) + { + CONS_Printf(M_GetText("Game Controller subsystem not started\n")); + return -1; + } + if (joyIndex <= 0) return -1; @@ -1151,7 +1134,7 @@ static int joy_open(int playerIndex, int joyIndex) return -1; } - newdev = SDL_JoystickOpen(joyIndex-1); + newdev = SDL_GameControllerOpen(joyIndex-1); // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging // This indexing is SDL's responsibility and there's not much we can do about it. @@ -1166,9 +1149,9 @@ static int joy_open(int playerIndex, int joyIndex) if (JoyInfo[playerIndex].dev) { if (JoyInfo[playerIndex].dev == newdev // same device, nothing to do - || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo[playerIndex].dev))) // we failed, but already have a working device + || (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo[playerIndex].dev))) // we failed, but already have a working device { - return JoyInfo[playerIndex].axises; + return SDL_CONTROLLER_AXIS_MAX; } // Else, we're changing devices, so send neutral joy events @@ -1185,29 +1168,12 @@ static int joy_open(int playerIndex, int joyIndex) } else { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: %s\n"), playerIndex+1, SDL_JoystickName(JoyInfo[playerIndex].dev)); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: %s\n"), playerIndex+1, SDL_GameControllerName(JoyInfo[playerIndex].dev)); - JoyInfo[playerIndex].axises = SDL_JoystickNumAxes(JoyInfo[playerIndex].dev); - if (JoyInfo[playerIndex].axises > JOYAXISSET*2) - JoyInfo[playerIndex].axises = JOYAXISSET*2; - - /* - if (joyaxes<2) - { - I_OutputMsg("Not enought axes?\n"); - return 0; - } - */ - - JoyInfo[playerIndex].buttons = SDL_JoystickNumButtons(JoyInfo[playerIndex].dev); - if (JoyInfo[playerIndex].buttons > JOYBUTTONS) - JoyInfo[playerIndex].buttons = JOYBUTTONS; - - JoyInfo[playerIndex].hats = SDL_JoystickNumHats(JoyInfo[playerIndex].dev); - if (JoyInfo[playerIndex].hats > JOYHATS) - JoyInfo[playerIndex].hats = JOYHATS; - - JoyInfo[playerIndex].balls = SDL_JoystickNumBalls(JoyInfo[playerIndex].dev); + JoyInfo[playerIndex].axises = SDL_CONTROLLER_AXIS_MAX; + JoyInfo[playerIndex].buttons = SDL_CONTROLLER_BUTTON_MAX; + JoyInfo[playerIndex].hats = 1; + JoyInfo[playerIndex].balls = 0; //JoyInfo[playerIndex].bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo[playerIndex].dev), "pad"); @@ -1220,7 +1186,7 @@ static int joy_open(int playerIndex, int joyIndex) // void I_InitJoystick(UINT8 index) { - SDL_Joystick *newjoy = NULL; + SDL_GameController *newcontroller = NULL; UINT8 i; //I_ShutdownJoystick(); @@ -1245,23 +1211,32 @@ void I_InitJoystick(UINT8 index) } } + if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0) + { + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1) + { + CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError()); + return; + } + } + if (cv_usejoystick[index].value) - newjoy = SDL_JoystickOpen(cv_usejoystick[index].value-1); + newcontroller = SDL_GameControllerOpen(cv_usejoystick[index].value-1); for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { if (i == index) continue; - if (JoyInfo[i].dev == newjoy) + if (JoyInfo[i].dev == newcontroller) break; } - if (newjoy && i < MAXSPLITSCREENPLAYERS) // don't override an active device + if (newcontroller && i < MAXSPLITSCREENPLAYERS) // don't override an active device { cv_usejoystick[index].value = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1; } - else if (newjoy && joy_open(index, cv_usejoystick[index].value) != -1) + else if (newcontroller && joy_open(index, cv_usejoystick[index].value) != -1) { // SDL's device indexes are unstable, so cv_usejoystick may not match // the actual device index. So let's cheat a bit and find the device's current index. @@ -1278,14 +1253,14 @@ void I_InitJoystick(UINT8 index) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (JoyInfo[i].dev == newjoy) + if (JoyInfo[i].dev == newcontroller) break; } if (i == MAXSPLITSCREENPLAYERS) { // Joystick didn't end up being used - I_StoreExJoystick(newjoy); + I_StoreExJoystick(newcontroller); } } @@ -1320,6 +1295,13 @@ static void I_ShutdownInput(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) I_ShutdownJoystick(i); + if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == SDL_INIT_GAMECONTROLLER) + { + CONS_Printf("Shutting down gamecontroller system\n"); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + I_OutputMsg("I_Joystick: SDL's Game Controller system has been shutdown\n"); + } + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { CONS_Printf("Shutting down joy system\n"); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index aa40721e6..79b5473d0 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -770,9 +770,10 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt) } } -static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt) +static void Impl_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt) { event_t event; + INT32 value; event.type = ev_joystick; @@ -782,78 +783,32 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt) return; } - evt.axis++; event.data1 = event.data2 = event.data3 = INT32_MAX; //axis - if (evt.axis > JOYAXISSET*2) + if (evt.axis > 2 * JOYAXISSETS) { return; } //vaule[sic] - if (evt.axis % 2) + value = SDLJoyAxis(evt.value, evt.which); + + if (evt.axis & 1) { - event.data1 = evt.axis / 2; - event.data2 = SDLJoyAxis(evt.value, 0); // TODO: replace 0 with pid + event.data3 = value; } else { - evt.axis--; - event.data1 = evt.axis / 2; - event.data3 = SDLJoyAxis(evt.value, 0); // TODO: replace 0 with pid + event.data2 = value; } + event.data1 = evt.axis / 2; + D_PostEvent(&event); } -static void Impl_SendHatEvent(SDL_JoyHatEvent evt, UINT64 hatFlag, UINT8 keyOffset) -{ - event_t event; - - event.device = 1 + evt.which; - if (event.device == INT32_MAX) - { - return; - } - - event.data1 = KEY_HAT1 + keyOffset; - - if (evt.hat < JOYHATS) - { - event.data1 += (evt.hat * 4); - } - else - { - return; - } - - if (evt.value & hatFlag) - { - event.type = ev_keydown; - } - else - { - event.type = ev_keyup; - } - - SDLJoyRemap(&event); - - if (event.type != ev_console) - { - D_PostEvent(&event); - } -} - -static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) -{ - Impl_SendHatEvent(evt, SDL_HAT_UP, 0); - Impl_SendHatEvent(evt, SDL_HAT_DOWN, 1); - Impl_SendHatEvent(evt, SDL_HAT_LEFT, 2); - Impl_SendHatEvent(evt, SDL_HAT_RIGHT, 3); -} - -static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type) +static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type) { event_t event; @@ -866,11 +821,11 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type) event.data1 = KEY_JOY1; - if (type == SDL_JOYBUTTONUP) + if (type == SDL_CONTROLLERBUTTONUP) { event.type = ev_keyup; } - else if (type == SDL_JOYBUTTONDOWN) + else if (type == SDL_CONTROLLERBUTTONDOWN) { event.type = ev_keydown; } @@ -936,26 +891,23 @@ void I_GetEvent(void) case SDL_MOUSEWHEEL: Impl_HandleMouseWheelEvent(evt.wheel); break; - case SDL_JOYAXISMOTION: - Impl_HandleJoystickAxisEvent(evt.jaxis); + case SDL_CONTROLLERAXISMOTION: + Impl_HandleControllerAxisEvent(evt.caxis); break; - case SDL_JOYHATMOTION: - Impl_HandleJoystickHatEvent(evt.jhat); - break; - case SDL_JOYBUTTONUP: - case SDL_JOYBUTTONDOWN: - Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); + case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERBUTTONDOWN: + Impl_HandleControllerButtonEvent(evt.cbutton, evt.type); break; //////////////////////////////////////////////////////////// - case SDL_JOYDEVICEADDED: + case SDL_CONTROLLERDEVICEADDED: { // OH BOY are you in for a good time! #abominationstation - SDL_Joystick *newjoy = SDL_JoystickOpen(evt.jdevice.which); + SDL_GameController *newcontroller = SDL_GameControllerOpen(evt.cdevice.which); - CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1); + CONS_Debug(DBG_GAMELOGIC, "Controller device index %d added\n", evt.cdevice.which + 1); //////////////////////////////////////////////////////////// // Because SDL's device index is unstable, we're going to cheat here a bit: @@ -970,7 +922,7 @@ void I_GetEvent(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (newjoy && (!JoyInfo[i].dev || !SDL_JoystickGetAttached(JoyInfo[i].dev))) + if (newcontroller && (!JoyInfo[i].dev || !SDL_GameControllerGetAttached(JoyInfo[i].dev))) { UINT8 j; @@ -979,14 +931,14 @@ void I_GetEvent(void) if (i == j) continue; - if (JoyInfo[j].dev == newjoy) + if (JoyInfo[j].dev == newcontroller) break; } if (j == MAXSPLITSCREENPLAYERS) { // ensures we aren't overriding a currently active device - cv_usejoystick[i].value = evt.jdevice.which + 1; + cv_usejoystick[i].value = evt.cdevice.which + 1; I_UpdateJoystickDeviceIndices(0); } } @@ -1028,21 +980,21 @@ void I_GetEvent(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (JoyInfo[i].dev == newjoy) + if (JoyInfo[i].dev == newcontroller) break; } if (i == MAXSPLITSCREENPLAYERS) - I_StoreExJoystick(newjoy); + I_StoreExJoystick(newcontroller); } break; //////////////////////////////////////////////////////////// - case SDL_JOYDEVICEREMOVED: + case SDL_CONTROLLERDEVICEREMOVED: for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (JoyInfo[i].dev && !SDL_JoystickGetAttached(JoyInfo[i].dev)) + if (JoyInfo[i].dev && !SDL_GameControllerGetAttached(JoyInfo[i].dev)) { CONS_Debug(DBG_GAMELOGIC, "Joystick%d removed, device index: %d\n", i+1, JoyInfo[i].oldjoy); I_ShutdownJoystick(i); @@ -1146,8 +1098,8 @@ void I_OsPolling(void) if (consolevent) I_GetConsoleEvents(); - if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - SDL_JoystickUpdate(); + if (SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER)) + SDL_GameControllerUpdate(); I_GetEvent(); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 391614bcd..86d584632 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -41,8 +41,8 @@ extern SDL_bool framebuffer; */ typedef struct SDLJoyInfo_s { - /// Joystick handle - SDL_Joystick *dev; + /// Controller handle + SDL_GameController *dev; /// number of old joystick int oldjoy; /// number of axies @@ -58,12 +58,12 @@ typedef struct SDLJoyInfo_s } SDLJoyInfo_t; -/** \brief SDL info about joysticks +/** \brief SDL info about controllers */ extern SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; -extern SDL_Joystick *ExJoystick[MAXGAMEPADS]; +extern SDL_GameController *ExJoystick[MAXGAMEPADS]; -void I_StoreExJoystick(SDL_Joystick *dev); +void I_StoreExJoystick(SDL_GameController *dev); /** \brief joystick axis deadzone */ @@ -75,8 +75,8 @@ void I_GetConsoleEvents(void); // So we can call this from i_video event loop void I_ShutdownJoystick(UINT8 index); -// Cheat to get the device index for a joystick handle -INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev); +// Cheat to get the device index for a game controller handle +INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev); // Quick thing to make SDL_JOYDEVICEADDED events less of an abomination void I_UpdateJoystickDeviceIndex(UINT8 player);