Port Ediolon's SDL GameController work

Basically instantly solved all of the issues that made this branch completely unusable
This commit is contained in:
Eidolon 2022-08-23 00:05:50 -05:00 committed by Sally Coolatta
parent a8d847227d
commit 85a132c149
6 changed files with 220 additions and 301 deletions

View file

@ -173,7 +173,7 @@ void G_MapEventsToControls(event_t *ev)
break; break;
case ev_joystick: // buttons are virtual keys case ev_joystick: // buttons are virtual keys
if (ev->data1 >= JOYAXISSET) if (ev->data1 >= JOYAXISSETS)
{ {
#ifdef PARANOIA #ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1); CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1);
@ -181,37 +181,56 @@ void G_MapEventsToControls(event_t *ev)
break; 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 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
gamekeydown[ev->device][KEY_AXIS1 + i] = abs(ev->data2);
gamekeydown[ev->device][KEY_AXIS1 + i + 1] = 0;
} }
else
if (ev->data3 != INT32_MAX)
{ {
// Right gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
gamekeydown[ev->device][KEY_AXIS1 + i] = 0;
gamekeydown[ev->device][KEY_AXIS1 + i + 1] = abs(ev->data2);
} }
} }
else
if (ev->data3 != INT32_MAX)
{ {
if (ev->data3 < 0) // Actual analog sticks
if (ev->data2 != INT32_MAX)
{ {
// Up if (ev->data2 < 0)
gamekeydown[ev->device][KEY_AXIS1 + i + 2] = abs(ev->data3); {
gamekeydown[ev->device][KEY_AXIS1 + i + 3] = 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 if (ev->data3 < 0)
gamekeydown[ev->device][KEY_AXIS1 + i + 2] = 0; {
gamekeydown[ev->device][KEY_AXIS1 + i + 3] = abs(ev->data3); // 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; break;
@ -316,76 +335,38 @@ static keyname_t keynames[] =
{KEY_MOUSEWHEELUP, "Wheel Up"}, {KEY_MOUSEWHEELUP, "Wheel Up"},
{KEY_MOUSEWHEELDOWN, "Wheel Down"}, {KEY_MOUSEWHEELDOWN, "Wheel Down"},
{KEY_JOY1+0, "JOY1"}, {KEY_JOY1+0, "A BUTTON"},
{KEY_JOY1+1, "JOY2"}, {KEY_JOY1+1, "B BUTTON"},
{KEY_JOY1+2, "JOY3"}, {KEY_JOY1+2, "X BUTTON"},
{KEY_JOY1+3, "JOY4"}, {KEY_JOY1+3, "Y BUTTON"},
{KEY_JOY1+4, "JOY5"}, {KEY_JOY1+4, "BACK BUTTON"},
{KEY_JOY1+5, "JOY6"}, {KEY_JOY1+5, "GUIDE BUTTON"},
{KEY_JOY1+6, "JOY7"}, {KEY_JOY1+6, "START BUTTON"},
{KEY_JOY1+7, "JOY8"}, {KEY_JOY1+7, "L-STICK CLICK"},
{KEY_JOY1+8, "JOY9"}, {KEY_JOY1+8, "R-STICK CLICK"},
#if !defined (NOMOREJOYBTN_1S) {KEY_JOY1+9, "L BUMPER"},
// we use up to 32 buttons in DirectInput {KEY_JOY1+10, "R BUMPER"},
{KEY_JOY1+9, "JOY10"}, {KEY_JOY1+11, "D-PAD UP"},
{KEY_JOY1+10, "JOY11"}, {KEY_JOY1+12, "D-PAD DOWN"},
{KEY_JOY1+11, "JOY12"}, {KEY_JOY1+13, "D-PAD LEFT"},
{KEY_JOY1+12, "JOY13"}, {KEY_JOY1+14, "D-PAD RIGHT"},
{KEY_JOY1+13, "JOY14"}, {KEY_JOY1+15, "MISC. BUTTON"},
{KEY_JOY1+14, "JOY15"}, {KEY_JOY1+16, "PADDLE1 BUTTON"},
{KEY_JOY1+15, "JOY16"}, {KEY_JOY1+17, "PADDLE2 BUTTON"},
{KEY_JOY1+16, "JOY17"}, {KEY_JOY1+18, "PADDLE3 BUTTON"},
{KEY_JOY1+17, "JOY18"}, {KEY_JOY1+19, "PADDLE4 BUTTON"},
{KEY_JOY1+18, "JOY19"}, {KEY_JOY1+20, "TOUCHPAD"},
{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
// the DOS version uses Allegro's joystick support {KEY_AXIS1+0, "L-STICK LEFT"},
{KEY_HAT1+0, "HATUP"}, {KEY_AXIS1+1, "L-STICK RIGHT"},
{KEY_HAT1+1, "HATDOWN"}, {KEY_AXIS1+2, "L-STICK UP"},
{KEY_HAT1+2, "HATLEFT"}, {KEY_AXIS1+3, "L-STICK DOWN"},
{KEY_HAT1+3, "HATRIGHT"}, {KEY_AXIS1+4, "R-STICK LEFT"},
{KEY_HAT1+4, "HATUP2"}, {KEY_AXIS1+5, "R-STICK RIGHT"},
{KEY_HAT1+5, "HATDOWN2"}, {KEY_AXIS1+6, "R-STICK UP"},
{KEY_HAT1+6, "HATLEFT2"}, {KEY_AXIS1+7, "R-STICK DOWN"},
{KEY_HAT1+7, "HATRIGHT2"}, {KEY_AXIS1+8, "L TRIGGER"},
{KEY_HAT1+8, "HATUP3"}, {KEY_AXIS1+9, "R TRIGGER"},
{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+"},
}; };
static const char *gamecontrolname[num_gamecontrols] = static const char *gamecontrolname[num_gamecontrols] =

View file

@ -23,9 +23,12 @@
#define NUMKEYS 256 #define NUMKEYS 256
#define MOUSEBUTTONS 8 #define MOUSEBUTTONS 8
#define JOYBUTTONS 32 // 32 buttons
#define JOYHATS 4 // 4 hats #define JOYBUTTONS 21 // 21 buttons, to match SDL_GameControllerButton
#define JOYAXISSET 4 // 4 Sets of 2 axises #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 #define MAXINPUTMAPPING 4
@ -35,9 +38,9 @@
typedef enum typedef enum
{ {
KEY_JOY1 = NUMKEYS, KEY_JOY1 = NUMKEYS,
KEY_HAT1 = KEY_JOY1 + JOYBUTTONS, KEY_HAT1 = KEY_JOY1 + 11, // macro for SDL_CONTROLLER_BUTTON_DPAD_UP
KEY_AXIS1 = KEY_HAT1 + JOYHATS*4, KEY_AXIS1 = KEY_JOY1 + JOYBUTTONS,
JOYINPUTEND = KEY_AXIS1 + JOYAXISSET*2*2, // 4 sets of 2 axes, each with positive & negative JOYINPUTEND = KEY_AXIS1 + JOYAXES,
KEY_MOUSE1 = JOYINPUTEND, KEY_MOUSE1 = JOYINPUTEND,
KEY_MOUSEMOVE = KEY_MOUSE1 + MOUSEBUTTONS, KEY_MOUSEMOVE = KEY_MOUSE1 + MOUSEBUTTONS,

View file

@ -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. // 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 :) // Because let's face it, when you test mods, you're often lazy to grab your controller for menuing :)
if (!i && !num) if (!i && !num)
{
setup_player[num].ponedevice = cv_usejoystick[num].value; setup_player[num].ponedevice = cv_usejoystick[num].value;
}
else if (num) else if (num)
{
// For any player past player 1, set controls to default profile controls, otherwise it's generally awful to do any menuing... // 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)); memcpy(&gamecontrol[num], gamecontroldefault, sizeof(gamecontroldefault));
}
CV_SetValue(&cv_usejoystick[num], i); CV_SetValue(&cv_usejoystick[num], i);
@ -3132,7 +3136,9 @@ void M_CharacterSelectTick(void)
// P1 is alone, set their old device just in case. // P1 is alone, set their old device just in case.
if (setup_numplayers < 2 && setup_player[0].ponedevice) if (setup_numplayers < 2 && setup_player[0].ponedevice)
{
CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice); CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice);
}
M_SetupNextMenu(&PLAY_MainDef, false); M_SetupNextMenu(&PLAY_MainDef, false);
} }
@ -5307,7 +5313,7 @@ void M_MapProfileControl(event_t *ev)
#endif #endif
break; break;
case ev_joystick: case ev_joystick:
if (ev->data1 >= JOYAXISSET) if (ev->data1 >= JOYAXES)
{ {
#ifdef PARANOIA #ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1); 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 responsivelr = ((ev->data2 != INT32_MAX) && (abs(ev->data2) >= deadzone));
boolean responsiveud = ((ev->data3 != INT32_MAX) && (abs(ev->data3) >= deadzone)); boolean responsiveud = ((ev->data3 != INT32_MAX) && (abs(ev->data3) >= deadzone));
// Only consider unambiguous assignment. i = ev->data1;
if (responsivelr == responsiveud)
return;
i = (ev->data1 * 4); if (i >= JOYANALOGS)
if (responsivelr)
{ {
if (ev->data2 < 0) // The trigger axes are handled specially.
i -= JOYANALOGS;
if (responsivelr)
{ {
// Left c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2);
c = KEY_AXIS1 + i;
} }
else else if (responsiveud)
{ {
// Right c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1;
c = KEY_AXIS1 + i + 1;
} }
} }
else //if (responsiveud) else
{ {
if (ev->data3 < 0) // Actual analog sticks
// Only consider unambiguous assignment.
if (responsivelr == responsiveud)
return;
if (responsivelr)
{ {
// Up if (ev->data2 < 0)
c = KEY_AXIS1 + i + 2; {
// Left
c = KEY_AXIS1 + (i * 4);
}
else
{
// Right
c = KEY_AXIS1 + (i * 4) + 1;
}
} }
else else //if (responsiveud)
{ {
// Down if (ev->data3 < 0)
c = KEY_AXIS1 + i + 3; {
// 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; break;
default: default:
return; return;
@ -5411,7 +5410,8 @@ void M_MapProfileControl(event_t *ev)
// If possible, reapply the profile... // If possible, reapply the profile...
// 19/05/22: Actually, no, don't do that, it just fucks everything up in too many cases. // 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. // 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; UINT8 lastp = cv_lastprofile[0].value;
@ -5430,7 +5430,8 @@ void M_MapProfileControl(event_t *ev)
break; break;
} }
} }
}*/ }
*/
} }
#undef KEYHOLDFOR #undef KEYHOLDFOR

View file

@ -200,12 +200,12 @@ static char returnWadPath[256];
#include "../byteptr.h" #include "../byteptr.h"
#endif #endif
void I_StoreExJoystick(SDL_Joystick *dev) void I_StoreExJoystick(SDL_GameController *dev)
{ {
// ExJoystick is a massive hack to avoid needing to completely // ExJoystick is a massive hack to avoid needing to completely
// rewrite pretty much all of the controller support from scratch... // 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, // If a joystick would've been discarded, then save it in an array,
// because we want it have it for the joystick input screen. // because we want it have it for the joystick input screen.
@ -217,12 +217,12 @@ void I_StoreExJoystick(SDL_Joystick *dev)
return; return;
} }
index = SDL_JoystickInstanceID(dev); index = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(dev));
if (index >= MAXGAMEPADS || index < 0) if (index >= MAXGAMEPADS || index < 0)
{ {
// Not enough space to save this joystick, completely discard. // Not enough space to save this joystick, completely discard.
SDL_JoystickClose(dev); SDL_GameControllerClose(dev);
return; return;
} }
@ -235,7 +235,7 @@ void I_StoreExJoystick(SDL_Joystick *dev)
if (ExJoystick[index] != NULL) if (ExJoystick[index] != NULL)
{ {
// Discard joystick in the old slot. // Discard joystick in the old slot.
SDL_JoystickClose(ExJoystick[index]); SDL_GameControllerClose(ExJoystick[index]);
} }
// Keep for safe-keeping. // Keep for safe-keeping.
@ -267,7 +267,7 @@ static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0};
/** \brief SDL info about joystick 1 /** \brief SDL info about joystick 1
*/ */
SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
SDL_Joystick *ExJoystick[MAXGAMEPADS]; SDL_GameController *ExJoystick[MAXGAMEPADS];
SDL_bool consolevent = SDL_FALSE; SDL_bool consolevent = SDL_FALSE;
SDL_bool framebuffer = 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; JoyInfo[3].scale = Joystick[3].bGamepadStyle?1:cv_joyscale[1].value;
} }
// Cheat to get the device index for a joystick handle // Cheat to get the device index for a game controller handle
INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev) 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); return SDL_JoystickInstanceID(joystick);
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 -1; return -1;
@ -1082,7 +1069,7 @@ void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer)
*/ */
void I_ShutdownJoystick(UINT8 index) void I_ShutdownJoystick(UINT8 index)
{ {
INT32 i, j; INT32 i;
event_t event; event_t event;
event.device = I_GetJoystickDeviceIndex(JoyInfo[index].dev); event.device = I_GetJoystickDeviceIndex(JoyInfo[index].dev);
@ -1093,23 +1080,13 @@ void I_ShutdownJoystick(UINT8 index)
// emulate the up of all joystick buttons // emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++) for (i = 0; i < JOYBUTTONS; i++)
{ {
event.data1=KEY_JOY1+i; event.data1 = KEY_JOY1+i;
D_PostEvent(&event); 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 // reset joystick position
event.type = ev_joystick; event.type = ev_joystick;
for (i = 0; i < JOYAXISSET; i++) for (i = 0; i < JOYAXES; i++)
{ {
event.data1 = i; event.data1 = i;
D_PostEvent(&event); D_PostEvent(&event);
@ -1131,7 +1108,7 @@ void I_ShutdownJoystick(UINT8 index)
*/ */
static int joy_open(int playerIndex, int joyIndex) static int joy_open(int playerIndex, int joyIndex)
{ {
SDL_Joystick *newdev = NULL; SDL_GameController *newdev = NULL;
int num_joy = 0; int num_joy = 0;
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
@ -1140,6 +1117,12 @@ static int joy_open(int playerIndex, int joyIndex)
return -1; return -1;
} }
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
{
CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
return -1;
}
if (joyIndex <= 0) if (joyIndex <= 0)
return -1; return -1;
@ -1151,7 +1134,7 @@ static int joy_open(int playerIndex, int joyIndex)
return -1; 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 // 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. // 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)
{ {
if (JoyInfo[playerIndex].dev == newdev // same device, nothing to do 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 // Else, we're changing devices, so send neutral joy events
@ -1185,29 +1168,12 @@ static int joy_open(int playerIndex, int joyIndex)
} }
else 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); JoyInfo[playerIndex].axises = SDL_CONTROLLER_AXIS_MAX;
if (JoyInfo[playerIndex].axises > JOYAXISSET*2) JoyInfo[playerIndex].buttons = SDL_CONTROLLER_BUTTON_MAX;
JoyInfo[playerIndex].axises = JOYAXISSET*2; JoyInfo[playerIndex].hats = 1;
JoyInfo[playerIndex].balls = 0;
/*
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].bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo[playerIndex].dev), "pad"); //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) void I_InitJoystick(UINT8 index)
{ {
SDL_Joystick *newjoy = NULL; SDL_GameController *newcontroller = NULL;
UINT8 i; UINT8 i;
//I_ShutdownJoystick(); //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) 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++) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{ {
if (i == index) if (i == index)
continue; continue;
if (JoyInfo[i].dev == newjoy) if (JoyInfo[i].dev == newcontroller)
break; 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; 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 // 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. // 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++) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{ {
if (JoyInfo[i].dev == newjoy) if (JoyInfo[i].dev == newcontroller)
break; break;
} }
if (i == MAXSPLITSCREENPLAYERS) if (i == MAXSPLITSCREENPLAYERS)
{ {
// Joystick didn't end up being used // 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++) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
I_ShutdownJoystick(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) if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{ {
CONS_Printf("Shutting down joy system\n"); CONS_Printf("Shutting down joy system\n");

View file

@ -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; event_t event;
INT32 value;
event.type = ev_joystick; event.type = ev_joystick;
@ -782,78 +783,32 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
return; return;
} }
evt.axis++;
event.data1 = event.data2 = event.data3 = INT32_MAX; event.data1 = event.data2 = event.data3 = INT32_MAX;
//axis //axis
if (evt.axis > JOYAXISSET*2) if (evt.axis > 2 * JOYAXISSETS)
{ {
return; return;
} }
//vaule[sic] //vaule[sic]
if (evt.axis % 2) value = SDLJoyAxis(evt.value, evt.which);
if (evt.axis & 1)
{ {
event.data1 = evt.axis / 2; event.data3 = value;
event.data2 = SDLJoyAxis(evt.value, 0); // TODO: replace 0 with pid
} }
else else
{ {
evt.axis--; event.data2 = value;
event.data1 = evt.axis / 2;
event.data3 = SDLJoyAxis(evt.value, 0); // TODO: replace 0 with pid
} }
event.data1 = evt.axis / 2;
D_PostEvent(&event); D_PostEvent(&event);
} }
static void Impl_SendHatEvent(SDL_JoyHatEvent evt, UINT64 hatFlag, UINT8 keyOffset) static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type)
{
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)
{ {
event_t event; event_t event;
@ -866,11 +821,11 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
event.data1 = KEY_JOY1; event.data1 = KEY_JOY1;
if (type == SDL_JOYBUTTONUP) if (type == SDL_CONTROLLERBUTTONUP)
{ {
event.type = ev_keyup; event.type = ev_keyup;
} }
else if (type == SDL_JOYBUTTONDOWN) else if (type == SDL_CONTROLLERBUTTONDOWN)
{ {
event.type = ev_keydown; event.type = ev_keydown;
} }
@ -936,26 +891,23 @@ void I_GetEvent(void)
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
Impl_HandleMouseWheelEvent(evt.wheel); Impl_HandleMouseWheelEvent(evt.wheel);
break; break;
case SDL_JOYAXISMOTION: case SDL_CONTROLLERAXISMOTION:
Impl_HandleJoystickAxisEvent(evt.jaxis); Impl_HandleControllerAxisEvent(evt.caxis);
break; break;
case SDL_JOYHATMOTION: case SDL_CONTROLLERBUTTONUP:
Impl_HandleJoystickHatEvent(evt.jhat); case SDL_CONTROLLERBUTTONDOWN:
break; Impl_HandleControllerButtonEvent(evt.cbutton, evt.type);
case SDL_JOYBUTTONUP:
case SDL_JOYBUTTONDOWN:
Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type);
break; break;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
case SDL_JOYDEVICEADDED: case SDL_CONTROLLERDEVICEADDED:
{ {
// OH BOY are you in for a good time! #abominationstation // 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: // 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++) 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; UINT8 j;
@ -979,14 +931,14 @@ void I_GetEvent(void)
if (i == j) if (i == j)
continue; continue;
if (JoyInfo[j].dev == newjoy) if (JoyInfo[j].dev == newcontroller)
break; break;
} }
if (j == MAXSPLITSCREENPLAYERS) if (j == MAXSPLITSCREENPLAYERS)
{ {
// ensures we aren't overriding a currently active device // 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); I_UpdateJoystickDeviceIndices(0);
} }
} }
@ -1028,21 +980,21 @@ void I_GetEvent(void)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{ {
if (JoyInfo[i].dev == newjoy) if (JoyInfo[i].dev == newcontroller)
break; break;
} }
if (i == MAXSPLITSCREENPLAYERS) if (i == MAXSPLITSCREENPLAYERS)
I_StoreExJoystick(newjoy); I_StoreExJoystick(newcontroller);
} }
break; break;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
case SDL_JOYDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMOVED:
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) 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); CONS_Debug(DBG_GAMELOGIC, "Joystick%d removed, device index: %d\n", i+1, JoyInfo[i].oldjoy);
I_ShutdownJoystick(i); I_ShutdownJoystick(i);
@ -1146,8 +1098,8 @@ void I_OsPolling(void)
if (consolevent) if (consolevent)
I_GetConsoleEvents(); I_GetConsoleEvents();
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) if (SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER))
SDL_JoystickUpdate(); SDL_GameControllerUpdate();
I_GetEvent(); I_GetEvent();

View file

@ -41,8 +41,8 @@ extern SDL_bool framebuffer;
*/ */
typedef struct SDLJoyInfo_s typedef struct SDLJoyInfo_s
{ {
/// Joystick handle /// Controller handle
SDL_Joystick *dev; SDL_GameController *dev;
/// number of old joystick /// number of old joystick
int oldjoy; int oldjoy;
/// number of axies /// number of axies
@ -58,12 +58,12 @@ typedef struct SDLJoyInfo_s
} SDLJoyInfo_t; } SDLJoyInfo_t;
/** \brief SDL info about joysticks /** \brief SDL info about controllers
*/ */
extern SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; 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 /** \brief joystick axis deadzone
*/ */
@ -75,8 +75,8 @@ void I_GetConsoleEvents(void);
// So we can call this from i_video event loop // So we can call this from i_video event loop
void I_ShutdownJoystick(UINT8 index); void I_ShutdownJoystick(UINT8 index);
// Cheat to get the device index for a joystick handle // Cheat to get the device index for a game controller handle
INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev); INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev);
// Quick thing to make SDL_JOYDEVICEADDED events less of an abomination // Quick thing to make SDL_JOYDEVICEADDED events less of an abomination
void I_UpdateJoystickDeviceIndex(UINT8 player); void I_UpdateJoystickDeviceIndex(UINT8 player);