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;
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] =

View file

@ -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,

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.
// 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

View file

@ -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");

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;
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();

View file

@ -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);