Fix Gamepads

Thanks thanks thanks thanks so much Alug for the time working on this!!!!!
This commit is contained in:
NepDisk 2026-02-14 16:27:53 -05:00
parent 359e30dba6
commit 8a9683542b
28 changed files with 778 additions and 1086 deletions

View file

@ -2106,8 +2106,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
renderdeltatics = FRACUNIT;
R_SetTimeFrac(FRACUNIT);
memset(deviceResponding, false, sizeof (deviceResponding));
if (cl_mode == CL_CONFIRMCONNECT)
{
D_ProcessEvents(); //needed for menu system to receive inputs
@ -2837,7 +2835,7 @@ void CL_Reset(void)
http_source[0] = '\0';
#endif
G_ResetAllDeviceRumbles();
G_ResetAllControllerRumbles();
// D_StartTitle should get done now, but the calling function will handle it
}

View file

@ -221,7 +221,6 @@ void D_ProcessEvents(void)
for (size_t i = 0; i < 4; i++)
gamekeydown[0][KEY_MOUSEMOVE + i] = 0;
memset(deviceResponding, false, sizeof (deviceResponding));
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
{
ev = &events[eventtail];
@ -1105,7 +1104,7 @@ void D_SRB2Loop(void)
if (!dedicated)
{
G_DeviceLEDTick();
G_ControllerLEDTick();
}
// consoleplayer -> displayplayers (hear sounds from viewpoint)
@ -1222,7 +1221,6 @@ void D_StartTitle(void)
// clear cmd building stuff
memset(gamekeydown, 0, sizeof(gamekeydown));
memset(deviceResponding, false, sizeof (deviceResponding));
F_StartTitleScreen();
@ -1230,13 +1228,13 @@ void D_StartTitle(void)
if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");
G_ResetAllDeviceRumbles();
G_ResetAllControllerRumbles();
// The title screen is obviously not a tutorial! (Unless I'm mistaken)
tutorialmode = false;
// map palettes affect this
G_ResetDeviceLED();
G_ResetControllerLED();
}
//

View file

@ -18,6 +18,7 @@
#include "console.h"
#include "command.h"
#include "i_time.h"
#include "i_gamepad.h"
#include "i_system.h"
#include "g_game.h"
#include "hu_stuff.h"
@ -382,31 +383,22 @@ consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "Off", CV_SAVE|CV_CALL,usemouse_
consvar_t cv_laglesscam = CVAR_INIT ("laglesscamera", "Off", CV_SAVE,CV_OnOff, NULL);
consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick1),
CVAR_INIT ("use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2),
CVAR_INIT ("use_joystick3", "3", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick3),
CVAR_INIT ("use_joystick4", "4", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick4)
consvar_t cv_usecontroller[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitController1),
CVAR_INIT ("use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitController2),
CVAR_INIT ("use_joystick3", "3", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitController3),
CVAR_INIT ("use_joystick4", "4", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitController4)
};
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale),
CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2),
CVAR_INIT ("padscale3", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale3),
CVAR_INIT ("padscale4", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale4)
consvar_t cv_controllerscale[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_ControllerScale),
CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_ControllerScale2),
CVAR_INIT ("padscale3", "1", CV_SAVE|CV_CALL, NULL, I_ControllerScale3),
CVAR_INIT ("padscale4", "1", CV_SAVE|CV_CALL, NULL, I_ControllerScale4)
};
#ifdef LJOYSTICK
consvar_t cv_joyport[MAXSPLITSCREENPLAYERS] = { //Alam: for later
CVAR_INIT ("padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL),
CVAR_INIT ("padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL),
CVAR_INIT ("padport3", "/dev/js0", CV_SAVE, joyport_cons_t, NULL),
CVAR_INIT ("padport4", "/dev/js0", CV_SAVE, joyport_cons_t, NULL)
};
#endif
#else
consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = { //Alam: Dummy for save
consvar_t cv_controllerscale[MAXSPLITSCREENPLAYERS] = { //Alam: Dummy for save
CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL),
CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL),
CVAR_INIT ("padscale3", "1", CV_SAVE|CV_HIDEN, NULL, NULL),
@ -1385,9 +1377,9 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_deadzonestyle[i]);
CV_RegisterVar(&cv_litesteer[i]);
CV_RegisterVar(&cv_turnsmooth[i]);
CV_RegisterVar(&cv_rumble[i]);
CV_RegisterVar(&cv_controllerrumble[i]);
CV_RegisterVar(&cv_rumblestrength[i]);
CV_RegisterVar(&cv_gamepadled[i]);
CV_RegisterVar(&cv_controllerled[i]);
}
// filesrch.c
@ -1408,11 +1400,8 @@ void D_RegisterClientCommands(void)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
CV_RegisterVar(&cv_usejoystick[i]);
CV_RegisterVar(&cv_joyscale[i]);
#ifdef LJOYSTICK
CV_RegisterVar(&cv_joyport[i]);
#endif
CV_RegisterVar(&cv_usecontroller[i]);
CV_RegisterVar(&cv_controllerscale[i]);
}
// s_sound.c
@ -4080,7 +4069,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
}
I_UpdateMouseGrab();
G_ResetAllDeviceRumbles();
G_ResetAllControllerRumbles();
}
static void Command_ReplayMarker(void)

View file

@ -37,11 +37,8 @@ extern consvar_t cv_splitplayers;
extern consvar_t cv_seenames;
extern consvar_t cv_usemouse;
extern consvar_t cv_laglesscam;
extern consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS];
#ifdef LJOYSTICK
extern consvar_t cv_joyport[MAXSPLITSCREENPLAYERS];
#endif
extern consvar_t cv_usecontroller[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_controllerscale[MAXSPLITSCREENPLAYERS];
// normally in p_mobj but the .h is not read
extern consvar_t cv_itemrespawntime;

View file

@ -58,20 +58,20 @@ void I_Tactile2(FFType Type, const JoyFF_t *Effect)
(void)Effect;
}
void I_JoyScale(void){}
void I_ControllerScale(void){}
void I_JoyScale2(void){}
void I_ControllerScale2(void){}
void I_InitJoystick(void){}
void I_InitController(void){}
void I_InitJoystick2(void){}
void I_InitController2(void){}
INT32 I_NumJoys(void)
INT32 I_NumControllers(void)
{
return 0;
}
const char *I_GetJoyName(INT32 joyid)
const char *I_GetControllerName(INT32 joyid)
{
(void)joyid;
return NULL;

View file

@ -33,7 +33,7 @@
#include "z_zone.h"
#include "i_video.h"
#include "byteptr.h"
#include "i_joy.h"
#include "i_gamepad.h"
#include "r_local.h"
#include "r_skins.h"
#include "y_inter.h"

View file

@ -41,7 +41,7 @@
#include "z_zone.h"
#include "i_video.h"
#include "byteptr.h"
#include "i_joy.h"
#include "i_gamepad.h"
#include "r_local.h"
#include "r_skins.h"
#include "y_inter.h"
@ -1186,6 +1186,7 @@ boolean G_AxisInDeadzone(UINT8 p, event_t *ev)
// if defaults is true, also check default controls if the gamecontrol has no binds
boolean G_ControlBoundToKey(UINT8 p, INT32 gc, INT32 key, boolean defaults)
{
INT32 deviceID;
INT32 i;
INT32 (*map)[MAXINPUTMAPPING] = &gamecontrol[p][gc];
@ -1194,9 +1195,11 @@ boolean G_ControlBoundToKey(UINT8 p, INT32 gc, INT32 key, boolean defaults)
if (defaults)
{
deviceID = I_GetControllerSlotfromID(I_GetControllerIDForPlayer(p));
for (i = 0; i < MAXINPUTMAPPING; i++)
if (G_KeyIsAvailable((*map)[i], cv_usejoystick[p].value, false))
if (G_KeyIsAvailable((*map)[i], deviceID, false))
goto bound;
map = &gamecontroldefault[gc];
}
bound:
@ -1259,11 +1262,13 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital, SINT8 type)
return 0;
}
fixed_t deadzonetype = G_GetDeadZoneType(p,type);
fixed_t deadzonetype = G_GetDeadZoneType(p, type);
deadzone = (JOYAXISRANGE * deadzonetype) / FRACUNIT;
deviceID = I_GetJoystickIDForPlayer(p) + 1;
deviceID = I_GetControllerSlotfromID(I_GetControllerIDForPlayer(p));
if (deviceID == INVALID_DEVICE)
return 0;
retrygetcontrol:
for (i = 0; i < MAXINPUTMAPPING; i++)
@ -1812,14 +1817,13 @@ void G_DoLoadLevel(boolean resetplayer)
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
memset(deviceResponding, false, sizeof (deviceResponding));
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
server_lagless = cv_lagless.value;
G_ResetAllDeviceRumbles();
G_ResetAllControllerRumbles();
if (doAutomate == true)
{
@ -3783,7 +3787,7 @@ void G_FinishExitLevel(void)
{
if (gamestate == GS_LEVEL)
{
G_ResetAllDeviceRumbles();
G_ResetAllControllerRumbles();
if (g_exit.retry)
{

View file

@ -14,13 +14,12 @@
#include "doomdef.h"
#include "doomstat.h"
#include "g_input.h"
#include "i_system.h"
#include "k_items.h"
#include "keys.h"
#include "hu_stuff.h" // need HUFONT start & end
#include "d_net.h"
#include "console.h"
#include "i_joy.h" // JOYAXISRANGE
#include "i_gamepad.h" // JOYAXISRANGE
#include "m_menu.h" // menustack
#include "i_system.h"
#include "g_game.h"
@ -55,19 +54,19 @@ consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("turnsmoothing4", "Off", CV_SAVE, turnsmooth_cons_t, NULL)
};
static void G_ResetPlayerDeviceRumble(INT32 player);
static void G_ResetPlayerControllerRumble(INT32 player);
static void rumble_off_handle(void);
static void rumble_off_handle2(void);
static void rumble_off_handle3(void);
static void rumble_off_handle4(void);
static void G_ResetPlayerGamepadIndicatorColor(INT32 player);
static void G_ResetPlayerControllerIndicatorColor(INT32 player);
static void led_off_handle(void);
static void led_off_handle2(void);
static void led_off_handle3(void);
static void led_off_handle4(void);
consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = {
consvar_t cv_controllerrumble[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("rumble", "On", CV_SAVE, CV_OnOff, rumble_off_handle),
CVAR_INIT ("rumble2", "On", CV_SAVE, CV_OnOff, rumble_off_handle2),
CVAR_INIT ("rumble3", "On", CV_SAVE, CV_OnOff, rumble_off_handle3),
@ -83,63 +82,62 @@ consvar_t cv_rumblestrength[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("rumblestrength4", "1.0", CV_SAVE|CV_FLOAT, rumblestrength_cons_t, NULL)
};
static CV_PossibleValue_t gamepadled_cons_t[] = {{0, "Off"}, {1, "Skincolor"}, {2, "Mobjcolor"}, {0, NULL}};
consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("gamepadled", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle),
CVAR_INIT ("gamepadled2", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle2),
CVAR_INIT ("gamepadled3", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle3),
CVAR_INIT ("gamepadled4", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle4)
static CV_PossibleValue_t controllerled_cons_t[] = {{0, "Off"}, {1, "Skincolor"}, {2, "Mobjcolor"}, {0, NULL}};
consvar_t cv_controllerled[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("gamepadled", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, controllerled_cons_t, led_off_handle),
CVAR_INIT ("gamepadled2", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, controllerled_cons_t, led_off_handle2),
CVAR_INIT ("gamepadled3", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, controllerled_cons_t, led_off_handle3),
CVAR_INIT ("gamepadled4", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, controllerled_cons_t, led_off_handle4)
};
static void rumble_off_handle(void)
{
if (cv_rumble[0].value == 0)
G_ResetPlayerDeviceRumble(0);
if (cv_controllerrumble[0].value == 0)
G_ResetPlayerControllerRumble(0);
}
static void rumble_off_handle2(void)
{
if (cv_rumble[1].value == 0)
G_ResetPlayerDeviceRumble(1);
if (cv_controllerrumble[1].value == 0)
G_ResetPlayerControllerRumble(1);
}
static void rumble_off_handle3(void)
{
if (cv_rumble[2].value == 0)
G_ResetPlayerDeviceRumble(2);
if (cv_controllerrumble[2].value == 0)
G_ResetPlayerControllerRumble(2);
}
static void rumble_off_handle4(void)
{
if (cv_rumble[3].value == 0)
G_ResetPlayerDeviceRumble(3);
if (cv_controllerrumble[3].value == 0)
G_ResetPlayerControllerRumble(3);
}
static void led_off_handle(void)
{
G_ResetPlayerGamepadIndicatorColor(0);
G_ResetPlayerControllerIndicatorColor(0);
}
static void led_off_handle2(void)
{
G_ResetPlayerGamepadIndicatorColor(1);
G_ResetPlayerControllerIndicatorColor(1);
}
static void led_off_handle3(void)
{
G_ResetPlayerGamepadIndicatorColor(2);
G_ResetPlayerControllerIndicatorColor(2);
}
static void led_off_handle4(void)
{
G_ResetPlayerGamepadIndicatorColor(3);
G_ResetPlayerControllerIndicatorColor(3);
}
// current state of the keys
// JOYAXISRANGE for fully pressed, 0 for not pressed
inputpoll_t gamekeydown = {};
inputpoll_t gamekeydown_msec = {};
boolean deviceResponding[MAXDEVICES] = {false};
// several key codes (or virtual key) per game control
INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING] = {};
@ -202,7 +200,7 @@ INT32 G_GetDevicePlayer(INT32 deviceID)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (deviceID == I_GetJoystickIDForPlayer(i) + 1)
if (deviceID == I_GetControllerIDForPlayer(i) + 1)
{
return i;
}
@ -215,8 +213,8 @@ INT32 G_GetDevicePlayer(INT32 deviceID)
INT32 G_AxisToKey(event_t *ev)
{
return KEY_AXIS1 + (ev->data1 >= JOYANALOGS
? ev->data1 + JOYANALOGS // triggers
: ev->data1*2 + (ev->data2 >= 0)); // analog sticks
? ev->data1 + JOYANALOGS // triggers
: ev->data1*2 + (ev->data2 >= 0)); // analog sticks
}
//
@ -230,32 +228,28 @@ void G_MapEventsToControls(event_t *ev)
{
INT32 i;
if (ev->device >= 0 && ev->device < MAXDEVICES)
{
switch (ev->type)
{
case ev_keydown:
//case ev_keyup:
//case ev_mouse:
//case ev_joystick:
deviceResponding[ev->device] = true;
break;
INT32 device = ev->device;
default:
break;
}
}
else
{
// invalid
if (device < KEYBOARD_MOUSE_DEVICE || device >= UINT32_MAX)
return;
// not a keyboard?
// try to see if its a controller in use
if (device > KEYBOARD_MOUSE_DEVICE)
device = I_GetControllerSlotfromID(device-1);
// nope no controller thats used
// so ignore it
if (device == INVALID_DEVICE)
return;
}
switch (ev->type)
{
case ev_keydown:
if (ev->data1 < NUMINPUTS)
{
gamekeydown[ev->device][ev->data1] = JOYAXISRANGE;
gamekeydown[device][ev->data1] = JOYAXISRANGE;
}
#ifdef PARANOIA
else
@ -268,7 +262,7 @@ void G_MapEventsToControls(event_t *ev)
case ev_keyup:
if (ev->data1 < NUMINPUTS)
{
gamekeydown[ev->device][ev->data1] = 0;
gamekeydown[device][ev->data1] = 0;
}
#ifdef PARANOIA
else
@ -288,28 +282,28 @@ void G_MapEventsToControls(event_t *ev)
if (ev->data2 < 0)
{
// Left
gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = abs(ev->data2);
gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = 0;
gamekeydown[device][KEY_MOUSEMOVE + 2] = abs(ev->data2);
gamekeydown[device][KEY_MOUSEMOVE + 3] = 0;
}
else
{
// Right
gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = 0;
gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = abs(ev->data2);
gamekeydown[device][KEY_MOUSEMOVE + 2] = 0;
gamekeydown[device][KEY_MOUSEMOVE + 3] = abs(ev->data2);
}
// Y axis
if (ev->data3 < 0)
{
// Up
gamekeydown[ev->device][KEY_MOUSEMOVE] = abs(ev->data3);
gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = 0;
gamekeydown[device][KEY_MOUSEMOVE] = abs(ev->data3);
gamekeydown[device][KEY_MOUSEMOVE + 1] = 0;
}
else
{
// Down
gamekeydown[ev->device][KEY_MOUSEMOVE] = 0;
gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = abs(ev->data3);
gamekeydown[device][KEY_MOUSEMOVE] = 0;
gamekeydown[device][KEY_MOUSEMOVE + 1] = abs(ev->data3);
}
break;
@ -327,6 +321,7 @@ void G_MapEventsToControls(event_t *ev)
break;
}
// tf is this for?
if (G_GetDevicePlayer(ev->device) == 0)
{
if (CON_Ready() || chat_on)
@ -338,9 +333,9 @@ void G_MapEventsToControls(event_t *ev)
{
// analog stick axes have a negative and positive keydown
i -= ev->data2 >= 0;
gamekeydown[ev->device][i++] = max(0, -ev->data2);
gamekeydown[device][i++] = max(0, -ev->data2);
}
gamekeydown[ev->device][i] = max(0, ev->data2);
gamekeydown[device][i] = max(0, ev->data2);
break;
@ -520,7 +515,7 @@ static const char *gamecontrolname[num_gamecontrols] =
#define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t))
skincolornum_t G_GetSkinColorForGamepad(INT32 playernum)
skincolornum_t G_GetSkinColorForController(INT32 playernum)
{
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
@ -531,7 +526,7 @@ skincolornum_t G_GetSkinColorForGamepad(INT32 playernum)
if (player)
{
// make rgb rainbow vomit when invul or flash blue when grow
if ((cv_gamepadled[playernum].value == 2) && player->mo && player->mo->color)
if ((cv_controllerled[playernum].value == 2) && player->mo && player->mo->color)
return (skincolornum_t)player->mo->color;
// take actual player skincolour when ingame
@ -546,45 +541,46 @@ skincolornum_t G_GetSkinColorForGamepad(INT32 playernum)
// Sets the Indicator LED on supported gamepads to a desired skincolor
// pass SKINCOLOR_NONE/0 to set the players skin color
void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT16 color)
void G_SetPlayerControllerIndicatorColor(INT32 playernum, UINT16 color)
{
skincolornum_t skincolor;
byteColor_t byte_color;
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
if (cv_gamepadled[playernum].value == 0)
if (cv_controllerled[playernum].value == 0)
{
return;
}
// so we can override this
skincolor = color ? color : G_GetSkinColorForGamepad(playernum);
skincolor = color ? color : G_GetSkinColorForController(playernum);
byte_color = V_GetColor(skincolors[skincolor].ramp[8]).s;
I_SetGamepadIndicatorColor(playernum, byte_color.red, byte_color.green, byte_color.blue);
I_SetControllerIndicatorColor(playernum, byte_color.red, byte_color.green, byte_color.blue);
}
static void G_ResetPlayerGamepadIndicatorColor(INT32 playernum)
static void G_ResetPlayerControllerIndicatorColor(INT32 playernum)
{
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
if (cv_gamepadled[playernum].value == 0)
if (cv_controllerled[playernum].value == 0)
{
I_SetGamepadIndicatorColor(playernum, 0, 0, 255);
I_SetControllerIndicatorColor(playernum, 0, 0, 255);
}
else
{
G_SetPlayerGamepadIndicatorColor(playernum, 0);
G_SetPlayerControllerIndicatorColor(playernum, 0);
}
}
static skincolornum_t curcolor[MAXSPLITSCREENPLAYERS] = {};
void G_DeviceLEDTick(void)
void G_ControllerLEDTick(void)
{
UINT8 i;
static skincolornum_t newcolor = SKINCOLOR_NONE;
const INT32 numcontrollers = I_NumControllers();
if (numcontrollers == 0)
{
@ -593,44 +589,48 @@ void G_DeviceLEDTick(void)
for (i = 0; i <= splitscreen; i++)
{
if (!cv_usejoystick[i].value || !cv_gamepadled[i].value)
if (!cv_usecontroller[i].value || !cv_controllerled[i].value)
continue;
newcolor = G_GetSkinColorForGamepad(i);
// Players controller does not have an addressable rbg light, bummer!
if (!I_ControllerSupportsIndicatorColor(i))
continue;
newcolor = G_GetSkinColorForController(i);
if (curcolor[i] == newcolor) // dont update if same colour
continue;
G_SetPlayerGamepadIndicatorColor(i, newcolor);
G_SetPlayerControllerIndicatorColor(i, newcolor);
curcolor[i] = newcolor;
}
}
void G_ResetDeviceLED(void)
void G_ResetControllerLED(void)
{
memset(curcolor, 0, sizeof(curcolor));
}
static void G_ResetPlayerDeviceRumble(INT32 playernum)
static void G_ResetPlayerControllerRumble(INT32 playernum)
{
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
I_GamepadRumble(playernum, 0, 0, 0);
I_ControllerRumble(playernum, 0, 0, 0);
}
void G_ResetAllDeviceRumbles(void)
void G_ResetAllControllerRumbles(void)
{
for (int i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
I_GamepadRumble(i, 0, 0, 0);
I_ControllerRumble(i, 0, 0, 0);
}
}
void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
void G_PlayerControllerRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
{
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
if (cv_rumble[playernum].value == 0)
if (cv_controllerrumble[playernum].value == 0)
{
return;
}
@ -641,7 +641,7 @@ void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_stre
low_strength = (UINT16)min(FixedMul(low_strength, cv_rumblestrength[playernum].value), UINT16_MAX);
high_strength = (UINT16)min(FixedMul(high_strength, cv_rumblestrength[playernum].value), UINT16_MAX);
I_GamepadRumble(playernum, low_strength, high_strength, duration);
I_ControllerRumble(playernum, low_strength, high_strength, duration);
}
// rumble strengths
@ -657,9 +657,10 @@ enum
// Controller rumble!
// this keeps track of a bunch of things
// and makes your controller rumble accordingly
void G_DeviceRumbleTick(void)
void G_ControllerRumbleTick(void)
{
UINT8 i;
const INT32 numcontrollers = I_NumControllers();
if (dedicated || numcontrollers == 0 || gamestate != GS_LEVEL)
{
@ -668,11 +669,15 @@ void G_DeviceRumbleTick(void)
for (i = 0; i <= splitscreen; i++)
{
if (!cv_usejoystick[i].value || !cv_rumble[i].value)
if (!cv_usecontroller[i].value || !cv_controllerrumble[i].value)
{
continue;
}
// Players controller does not support rumble, bummer!
if (!I_ControllerSupportsRumble(i))
continue;
if (camera[i].freecam)
{
continue;
@ -694,7 +699,7 @@ void G_DeviceRumbleTick(void)
player->playerstate == PST_DEAD ||
player->respawn > 1)
{
G_PlayerDeviceRumble(i, low, high, 0);
G_PlayerControllerRumble(i, low, high, 0);
continue;
}
@ -799,7 +804,7 @@ void G_DeviceRumbleTick(void)
continue;
}
G_PlayerDeviceRumble(i, low, high, lenght);
G_PlayerControllerRumble(i, low, high, lenght);
}
}

View file

@ -29,7 +29,9 @@ extern "C" {
#define MOUSEBUTTONS 8
#define JOYBUTTONS SDL_GAMEPAD_BUTTON_COUNT // 26 buttons, to match SDL_GameControllerButton
#define JOYBUTTONS 26 // 26 buttons, to match SDL_GameControllerButton
#define JOY_DPAD_UP 11
#define JOYANALOGS 4 // 4 analog stick axes (2 sticks * 2 axes)
#define JOYTRIGGERS 2 // 2 trigger axes, positive only
#define JOYAXISES (JOYANALOGS + JOYTRIGGERS)
@ -43,7 +45,7 @@ extern "C" {
typedef enum
{
KEY_JOY1 = NUMKEYS,
KEY_HAT1 = KEY_JOY1 + SDL_GAMEPAD_BUTTON_DPAD_UP, // macro for SDL_CONTROLLER_BUTTON_DPAD_UP
KEY_HAT1 = KEY_JOY1 + JOY_DPAD_UP,
KEY_AXIS1 = KEY_JOY1 + JOYBUTTONS,
JOYINPUTEND = KEY_AXIS1 + JOYAXISKEYS,
@ -98,19 +100,19 @@ extern consvar_t cv_mousesens2, cv_mouseysens2;
extern consvar_t cv_controlperkey;
extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_controllerrumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumblestrength[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_controllerled[MAXSPLITSCREENPLAYERS];
// current state of the keys: JOYAXISRANGE or 0 when boolean.
// Or anything inbetween for analog values
#define MAXDEVICES (MAXGAMEPADS + 1) // Gamepads + keyboard & mouse
#define MAXDEVICES (MAXGAMEPADS + 10) // Gamepads + keyboard & mouse
// the above is horrid since device tracks the gamepad id for whatever godawful reason
// the gamepad instance id may be alot larger than (MAXGAMEPADS + 1)/"9"
typedef INT32 inputpoll_t[MAXDEVICES][NUMINPUTS];
extern inputpoll_t gamekeydown, gamekeydown_msec;
extern boolean deviceResponding[MAXDEVICES];
// several key codes (or virtual key) per game control
extern INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING];
extern INT32 gamecontroldefault[num_gamecontrols][MAXINPUTMAPPING]; // default control storage
@ -134,13 +136,16 @@ extern const INT32 gcl_full[num_gcl_full];
// peace to my little coder fingers!
// check a gamecontrol being active or not
skincolornum_t G_GetSkinColorForGamepad(INT32 playernum);
void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT16 color);
void G_DeviceLEDTick(void);
void G_ResetDeviceLED(void);
void G_ResetAllDeviceRumbles(void);
void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void G_DeviceRumbleTick(void);
#define INVALID_DEVICE -1
#define KEYBOARD_MOUSE_DEVICE 0
skincolornum_t G_GetSkinColorForController(INT32 playernum);
void G_SetPlayerControllerIndicatorColor(INT32 playernum, UINT16 color);
void G_ControllerLEDTick(void);
void G_ResetControllerLED(void);
void G_ResetAllControllerRumbles(void);
void G_PlayerControllerRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void G_ControllerRumbleTick(void);
INT32 G_GetDevicePlayer(INT32 deviceID);

View file

@ -7,11 +7,11 @@
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_joy.h
/// \brief share joystick information with game control code
/// \file i_gamepad.h
/// \brief share gamepad information with game control code
#ifndef __I_JOY_H__
#define __I_JOY_H__
#ifndef __I_GAMEPAD_H__
#define __I_GAMEPAD_H__
#include "g_input.h"
@ -44,9 +44,6 @@ extern "C" {
struct JoyType_t
{
/*! if true, we MUST Poll() to get new joystick data,
that is: we NEED the DIRECTINPUTDEVICE2 ! (watchout NT compatibility) */
INT32 bJoyNeedPoll;
/*! this joystick is a gamepad, read: digital axes
if FALSE, interpret the joystick event data as JOYAXISRANGE (see above) */
INT32 bGamepadStyle;
@ -58,6 +55,64 @@ struct JoyType_t
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
/** \brief to set up the first joystick scale
*/
void I_ControllerScale(void);
/** \brief to set up the second joystick scale
*/
void I_ControllerScale2(void);
/** \brief to set up the third joystick scale
*/
void I_ControllerScale3(void);
/** \brief to set up the fourth joystick scale
*/
void I_ControllerScale4(void);
// Called by D_SRB2Main.
/** \brief to startup a joystick
*/
void I_InitController(UINT8 index);
/** \brief to startup the first joystick
*/
void I_InitController1(void);
/** \brief to startup the second joystick
*/
void I_InitController2(void);
/** \brief to startup the third joystick
*/
void I_InitController3(void);
/** \brief to startup the fourth joystick
*/
void I_InitController4(void);
/** \brief return the number of joystick on the system
*/
INT32 I_NumControllers(void);
/** \brief The *I_GetControllerName function
\param joyid which joystick
\return joystick name
*/
const char *I_GetControllerName(INT32 joyid);
INT32 I_GetControllerSlotfromID(INT32 id);
boolean I_ControllerSupportsRumble(INT32 playernum);
boolean I_ControllerSupportsIndicatorColor(INT32 playernum);
void I_ControllerRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void I_SetControllerIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -118,132 +118,6 @@ ticcmd_t *I_BaseTiccmd4(void);
*/
void I_Quit(void) FUNCNORETURN;
typedef enum
{
EvilForce = -1,
//Constant
ConstantForce = 0,
//Ramp
RampForce,
//Periodics
SquareForce,
SineForce,
TriangleForce,
SawtoothUpForce,
SawtoothDownForce,
//MAX
NumberofForces,
} FFType;
struct JoyFF_t
{
INT32 ForceX; ///< The X of the Force's Vel
INT32 ForceY; ///< The Y of the Force's Vel
//All
UINT32 Duration; ///< The total duration of the effect, in microseconds
INT32 Gain; //< /The gain to be applied to the effect, in the range from 0 through 10,000.
//All, CONSTANTFORCE -10,000 to 10,000
INT32 Magnitude; ///< Magnitude of the effect, in the range from 0 through 10,000.
//RAMPFORCE
INT32 Start; ///< Magnitude at the start of the effect, in the range from -10,000 through 10,000.
INT32 End; ///< Magnitude at the end of the effect, in the range from -10,000 through 10,000.
//PERIODIC
INT32 Offset; ///< Offset of the effect.
UINT32 Phase; ///< Position in the cycle of the periodic effect at which playback begins, in the range from 0 through 35,999
UINT32 Period; ///< Period of the effect, in microseconds.
};
/** \brief Forcefeedback for the first joystick
\param Type what kind of Effect
\param Effect Effect Info
\return void
*/
void I_Tactile(FFType Type, const JoyFF_t *Effect);
/** \brief Forcefeedback for the second joystick
\param Type what kind of Effect
\param Effect Effect Info
\return void
*/
void I_Tactile2(FFType Type, const JoyFF_t *Effect);
/** \brief Forcefeedback for the third joystick
\param Type what kind of Effect
\param Effect Effect Info
\return void
*/
void I_Tactile3(FFType Type, const JoyFF_t *Effect);
/** \brief Forcefeedback for the fourth joystick
\param Type what kind of Effect
\param Effect Effect Info
\return void
*/
void I_Tactile4(FFType Type, const JoyFF_t *Effect);
/** \brief to set up the first joystick scale
*/
void I_JoyScale(void);
/** \brief to set up the second joystick scale
*/
void I_JoyScale2(void);
/** \brief to set up the third joystick scale
*/
void I_JoyScale3(void);
/** \brief to set up the fourth joystick scale
*/
void I_JoyScale4(void);
// Called by D_SRB2Main.
/** \brief to startup a joystick
*/
void I_InitJoystick(UINT8 index);
/** \brief to startup the first joystick
*/
void I_InitJoystick1(void);
/** \brief to startup the second joystick
*/
void I_InitJoystick2(void);
/** \brief to startup the third joystick
*/
void I_InitJoystick3(void);
/** \brief to startup the fourth joystick
*/
void I_InitJoystick4(void);
/** \brief return the number of joystick on the system
*/
INT32 I_NumJoys(void);
extern INT32 numcontrollers;
/** \brief The *I_GetJoyName function
\param joyid which joystick
\return joystick name
*/
const char *I_GetJoyName(INT32 joyid);
void I_GamepadRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void I_SetGamepadIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue);
#ifndef NOMUMBLE
#include "p_mobj.h" // mobj_t
#include "s_sound.h" // listener_t
@ -320,7 +194,7 @@ const char *I_LocateWad(void);
*/
void I_GetJoystickEvents(UINT8 index);
INT32 I_GetJoystickIDForPlayer(UINT8 pnum);
INT32 I_GetControllerIDForPlayer(UINT8 pnum);
/** \brief Checks if the mouse needs to be grabbed
*/

View file

@ -3866,7 +3866,7 @@ msgid "Set the use_joystick variable to one of the enumerated joystick numbers\n
msgstr ""
#: win32/win_sys.c:2002
msgid "I_InitJoystick: SetCooperativeLevel FAILED"
msgid "I_InitController: SetCooperativeLevel FAILED"
msgstr ""
#: win32/win_sys.c:2006 win32/win_sys.c:2373
@ -3882,7 +3882,7 @@ msgid "Set the use_joystick2 variable to one of the enumerated joysticks number\
msgstr ""
#: win32/win_sys.c:2364
msgid "I_InitJoystick2: SetCooperativeLevel FAILED"
msgid "I_InitController2: SetCooperativeLevel FAILED"
msgstr ""
#: win32/win_sys.c:3466

View file

@ -4062,7 +4062,7 @@ msgid "Set the use_joystick variable to one of the enumerated joystick numbers\n
msgstr ""
#: win32/win_sys.c:2004
msgid "I_InitJoystick: SetCooperativeLevel FAILED"
msgid "I_InitController: SetCooperativeLevel FAILED"
msgstr ""
#: win32/win_sys.c:2008 win32/win_sys.c:2375
@ -4078,7 +4078,7 @@ msgid "Set the use_joystick2 variable to one of the enumerated joysticks number\
msgstr ""
#: win32/win_sys.c:2366
msgid "I_InitJoystick2: SetCooperativeLevel FAILED"
msgid "I_InitController2: SetCooperativeLevel FAILED"
msgstr ""
#: win32/win_sys.c:3468

View file

@ -5392,7 +5392,7 @@ static int lib_kGetItemListEntry(lua_State *L)
// G_INPUT
////////////
static int lib_gSetPlayerGamepadIndicatorColor(lua_State *L)
static int lib_gSetPlayerControllerIndicatorColor(lua_State *L)
{
INT32 player = -1;
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
@ -5417,12 +5417,12 @@ static int lib_gSetPlayerGamepadIndicatorColor(lua_State *L)
if (player == -1) return 0;
// pls update with color 0 when youre done with changing led stuff so it can get player color again
G_SetPlayerGamepadIndicatorColor(player, color);
G_SetPlayerControllerIndicatorColor(player, color);
return 0;
}
static int lib_gPlayerDeviceRumble(lua_State *L)
static int lib_gPlayerControllerRumble(lua_State *L)
{
INT32 player = -1;
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
@ -5445,7 +5445,7 @@ static int lib_gPlayerDeviceRumble(lua_State *L)
// Not a local player
if (player == -1) return 0;
G_PlayerDeviceRumble(player, low_strength, high_strength, duration);
G_PlayerControllerRumble(player, low_strength, high_strength, duration);
return 0;
}
@ -5862,8 +5862,11 @@ static luaL_Reg lib[] = {
{"K_GetItemListEntry", lib_kGetItemListEntry},
//g_input
{"G_SetPlayerGamepadIndicatorColor",lib_gSetPlayerGamepadIndicatorColor},
{"G_PlayerDeviceRumble",lib_gPlayerDeviceRumble},
//{"G_SetPlayerControllerIndicatorColor", lib_gSetPlayerControllerIndicatorColor},
//{"G_PlayerControllerRumble", lib_gPlayerControllerRumble},
// gotta keep backwards compat :chaosleep:
{"G_SetPlayerGamepadIndicatorColor", lib_gSetPlayerControllerIndicatorColor},
{"G_PlayerDeviceRumble", lib_gPlayerControllerRumble},
{NULL, NULL}
};

View file

@ -78,7 +78,7 @@
#include "r_fps.h"
#include "m_easing.h"
#include "i_joy.h" // for joystick menu controls
#include "i_gamepad.h" // for joystick menu controls
// Condition Sets
#include "m_cond.h"
@ -531,7 +531,7 @@ consvar_t cv_dummyfollower = CVAR_INIT ("dummyfollower", "-1", CV_HIDEN, dummyfo
SINT8 dummycolorplayer = 0;
static void SetDummyColorPlayer(void)
{
G_SetPlayerGamepadIndicatorColor(dummycolorplayer, (UINT16)cv_dummycolor.value);
G_SetPlayerControllerIndicatorColor(dummycolorplayer, (UINT16)cv_dummycolor.value);
}
consvar_t cv_dummycolor = CVAR_INIT ("dummycolor", "0", CV_HIDEN|CV_CALL|CV_NOINIT, dummycolor_cons_t, SetDummyColorPlayer);
@ -2617,8 +2617,8 @@ static void M_DrawRightString(menuitem_t *item, INT16 x, INT16 y, INT32 vflags,
}
else if (item->submenu == MN_OP_JOYSTICKSET) // gamepad select
{
INT32 stick = cv_usejoystick[setupcontrolplayer-1].value;
const char *name = stick == 0 ? "None" : I_GetJoyName(stick);
INT32 stick = cv_usecontroller[setupcontrolplayer-1].value;
const char *name = stick == 0 ? "None" : I_GetControllerName(stick);
if (!name) name = "?";
w = V_StringWidth(name, vflags);
(w > BASEVIDWIDTH/2 - 4 ? V_DrawRightAlignedThinString : V_DrawRightAlignedString)
@ -8148,7 +8148,7 @@ INT32 MR_SetupMultiPlayer(INT32 arg)
gridcss_skinmemory = cv_chooseskin.value;
CV_SetValue(&cv_dummyfollower, cv_follower[arg].value);
CV_SetValue(&cv_dummycolor, cv_playercolor[arg].value);
G_SetPlayerGamepadIndicatorColor(arg, cv_playercolor[arg].value);
G_SetPlayerControllerIndicatorColor(arg, cv_playercolor[arg].value);
dummycolorplayer = arg;
Skinsort_option_Onchange();
@ -8419,17 +8419,19 @@ void MD_DrawJoystick(void)
{
INT32 i;
INT32 compareval;
#ifdef JOYSTICK_HOTPLUG
const INT32 numcontrollers = I_NumControllers();
#endif
MD_DrawGenericMenu();
for (i = 0; i <= MAXGAMEPADS; i++)
{
#ifdef JOYSTICK_HOTPLUG
if (atoi(cv_usejoystick[setupcontrolplayer-1].string) > numcontrollers)
compareval = atoi(cv_usejoystick[setupcontrolplayer-1].string);
if (atoi(cv_usecontroller[setupcontrolplayer-1].string) > numcontrollers)
compareval = atoi(cv_usecontroller[setupcontrolplayer-1].string);
else
#endif
compareval = cv_usejoystick[setupcontrolplayer-1].value;
compareval = cv_usecontroller[setupcontrolplayer-1].value;
V_DrawString(menudefs[MN_OP_JOYSTICKSET].x, menudefs[MN_OP_JOYSTICKSET].y + 16*i, ((i == compareval) ? V_GREENMAP : 0)|MENUCAPS, joystickInfo[i]);
}
@ -8438,7 +8440,7 @@ void MD_DrawJoystick(void)
INT32 MR_SetupJoystickMenu(INT32 arg)
{
const char *joyNA = "Unavailable";
const INT32 n = numcontrollers;
const INT32 numcontrollers = I_NumControllers();
INT32 i = 0;
INT32 j;
@ -8452,24 +8454,24 @@ INT32 MR_SetupJoystickMenu(INT32 arg)
for (i = 1; i <= MAXGAMEPADS; i++)
{
if (i <= n && (I_GetJoyName(i)) != NULL)
strncpy(joystickInfo[i], I_GetJoyName(i), 28);
if (i <= numcontrollers && (I_GetControllerName(i)) != NULL)
strncpy(joystickInfo[i], I_GetControllerName(i), 28);
else
strcpy(joystickInfo[i], joyNA);
#ifdef JOYSTICK_HOTPLUG
// We use cv_usejoystick.string as the USER-SET var
// and cv_usejoystick.value as the INTERNAL var
// We use cv_usecontroller.string as the USER-SET var
// and cv_usecontroller.value as the INTERNAL var
//
// In practice, if cv_usejoystick.string == 0, this overrides
// cv_usejoystick.value and always disables
// In practice, if cv_usecontroller.string == 0, this overrides
// cv_usecontroller.value and always disables
//
// Update cv_usejoystick.string here so that the user can
// Update cv_usecontroller.string here so that the user can
// properly change this value.
for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
{
if (i == cv_usejoystick[j].value)
CV_SetValue(&cv_usejoystick[j], i);
if (i == cv_usecontroller[j].value)
CV_SetValue(&cv_usecontroller[j], i);
}
#endif
}
@ -8483,29 +8485,29 @@ INT32 MR_AssignJoystick(INT32 arg)
#ifdef JOYSTICK_HOTPLUG
INT32 oldchoice, oldstringchoice;
INT32 numjoys = numcontrollers;
const INT32 numcontrollers = I_NumControllers();
oldchoice = oldstringchoice = atoi(cv_usejoystick[p].string) > numjoys ? atoi(cv_usejoystick[p].string) : cv_usejoystick[p].value;
CV_SetValue(&cv_usejoystick[p], arg);
oldchoice = oldstringchoice = atoi(cv_usecontroller[p].string) > numcontrollers ? atoi(cv_usecontroller[p].string) : cv_usecontroller[p].value;
CV_SetValue(&cv_usecontroller[p], arg);
// Just in case last-minute changes were made to cv_usejoystick.value,
// Just in case last-minute changes were made to cv_usecontroller.value,
// update the string too
// But don't do this if we're intentionally setting higher than numjoys
if (arg <= numjoys)
// But don't do this if we're intentionally setting higher than numcontrollers
if (arg <= numcontrollers)
{
CV_SetValue(&cv_usejoystick[p], cv_usejoystick[p].value);
CV_SetValue(&cv_usecontroller[p], cv_usecontroller[p].value);
// reset this so the comparison is valid
if (oldchoice > numjoys)
oldchoice = cv_usejoystick[p].value;
if (oldchoice > numcontrollers)
oldchoice = cv_usecontroller[p].value;
if (oldchoice != arg)
{
if (arg && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device
CV_SetValue(&cv_usejoystick[p], (oldstringchoice > numjoys ? oldstringchoice : oldchoice));
if (arg && oldstringchoice > numcontrollers) // if we did not select "None", we likely selected a used device
CV_SetValue(&cv_usecontroller[p], (oldstringchoice > numcontrollers ? oldstringchoice : oldchoice));
if (oldstringchoice ==
(atoi(cv_usejoystick[p].string) > numjoys ? atoi(cv_usejoystick[p].string) : cv_usejoystick[p].value))
(atoi(cv_usecontroller[p].string) > numcontrollers ? atoi(cv_usecontroller[p].string) : cv_usecontroller[p].value))
M_StartMessage("This joystick is used by another\n"
"player. Reset the joystick\n"
"for that player first.\n\n"
@ -8513,7 +8515,7 @@ INT32 MR_AssignJoystick(INT32 arg)
}
}
#else
CV_SetValue(&cv_usejoystick[p], arg);
CV_SetValue(&cv_usecontroller[p], arg);
#endif
return true;
}
@ -8540,8 +8542,8 @@ INT32 MR_SetupControlsMenu(INT32 arg)
M_SetItemCvar(MN_OP_CHANGECONTROLS, "DEAZS", &cv_deadzonestyle[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "TURNSMOOTHING", &cv_turnsmooth[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "LITESTEER", &cv_litesteer[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "LEDCOLOR", &cv_gamepadled[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "RUMBLE", &cv_rumble[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "LEDCOLOR", &cv_controllerled[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "RUMBLE", &cv_controllerrumble[arg]);
M_SetItemCvar(MN_OP_CHANGECONTROLS, "RUMBLESTR", &cv_rumblestrength[arg]);
M_SetItemVisible(MN_OP_CHANGECONTROLS, "TALK", player1); // Chat
@ -8683,7 +8685,7 @@ static void M_ResetControlsResponse(INT32 ch)
G_ResetControls(p);
// Setup gamepad option defaults (yucky)
CV_StealthSet(&cv_usejoystick[p], cv_usejoystick[p].defaultvalue);
CV_StealthSet(&cv_usecontroller[p], cv_usecontroller[p].defaultvalue);
S_StartSound(NULL, sfx_s224);
}

View file

@ -47,62 +47,6 @@
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
#define CTFTEAMENDCODE(pl) pl->ctfteam ? "\x80" : ""
void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period)
{
BasicFF_t Basicfeed;
if (!player)
return;
Basicfeed.Duration = (UINT32)(duration * (100L/TICRATE));
Basicfeed.ForceX = Basicfeed.ForceY = 1;
Basicfeed.Gain = 25000;
Basicfeed.Magnitude = period*10;
Basicfeed.player = player;
/// \todo test FFB
P_RampConstant(&Basicfeed, attack, fade);
}
void P_ForceConstant(const BasicFF_t *FFInfo)
{
JoyFF_t ConstantQuake;
if (!FFInfo || !FFInfo->player)
return;
ConstantQuake.ForceX = FFInfo->ForceX;
ConstantQuake.ForceY = FFInfo->ForceY;
ConstantQuake.Duration = FFInfo->Duration;
ConstantQuake.Gain = FFInfo->Gain;
ConstantQuake.Magnitude = FFInfo->Magnitude;
if (FFInfo->player == &players[consoleplayer])
I_Tactile(ConstantForce, &ConstantQuake);
else if (splitscreen && FFInfo->player == &players[g_localplayers[1]])
I_Tactile2(ConstantForce, &ConstantQuake);
else if (splitscreen > 1 && FFInfo->player == &players[g_localplayers[2]])
I_Tactile3(ConstantForce, &ConstantQuake);
else if (splitscreen > 2 && FFInfo->player == &players[g_localplayers[3]])
I_Tactile4(ConstantForce, &ConstantQuake);
}
void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
{
JoyFF_t RampQuake;
if (!FFInfo || !FFInfo->player)
return;
RampQuake.ForceX = FFInfo->ForceX;
RampQuake.ForceY = FFInfo->ForceY;
RampQuake.Duration = FFInfo->Duration;
RampQuake.Gain = FFInfo->Gain;
RampQuake.Magnitude = FFInfo->Magnitude;
RampQuake.Start = Start;
RampQuake.End = End;
if (FFInfo->player == &players[consoleplayer])
I_Tactile(ConstantForce, &RampQuake);
else if (splitscreen && FFInfo->player == &players[g_localplayers[1]])
I_Tactile2(ConstantForce, &RampQuake);
else if (splitscreen > 1 && FFInfo->player == &players[g_localplayers[2]])
I_Tactile3(ConstantForce, &RampQuake);
else if (splitscreen > 2 && FFInfo->player == &players[g_localplayers[3]])
I_Tactile4(ConstantForce, &RampQuake);
}
//
// GET STUFF
//

View file

@ -570,17 +570,6 @@ extern struct minimapinfo
//
// P_INTER
//
struct BasicFF_t
{
INT32 ForceX; ///< The X of the Force's Vel
INT32 ForceY; ///< The Y of the Force's Vel
const player_t *player; ///< Player of Rumble
//All
UINT32 Duration; ///< The total duration of the effect, in microseconds
INT32 Gain; ///< /The gain to be applied to the effect, in the range from 0 through 10,000.
//All, CONSTANTFORCE <20>10,000 to 10,000
INT32 Magnitude; ///< Magnitude of the effect, in the range from 0 through 10,000.
};
/* Damage/death types, for P_DamageMobj and related */
//// Damage types
@ -604,9 +593,6 @@ struct BasicFF_t
#define DMG_DEATHMASK DMG_INSTAKILL // if bit 7 is set, this is a death type instead of a damage type
#define DMG_TYPEMASK 0x0F // Get type without any flags
void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period);
void P_ForceConstant(const BasicFF_t *FFInfo);
void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End);
void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source);
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype);

View file

@ -9118,7 +9118,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
G_AddMapToBuffer(gamemap-1);
G_ResetDeviceLED();
G_ResetControllerLED();
P_MapEnd(); // g_tm.thing is no longer needed from this point onwards

View file

@ -796,7 +796,7 @@ void P_Ticker(boolean run)
// Apply rumble to local players
if (!demo.playback)
{
G_DeviceRumbleTick();
G_ControllerRumbleTick();
}
// run all the bot tickers

View file

@ -34,7 +34,7 @@
#include "m_random.h"
#include "m_misc.h"
#include "i_video.h"
#include "i_joy.h"
#include "i_gamepad.h"
#include "p_slopes.h"
#include "p_spec.h"
#include "r_splats.h"

View file

@ -4,6 +4,7 @@ target_sources(BLANKART PRIVATE
ogl_sdl.c
i_threads.c
i_net.c
i_gamepad.c
i_system.cpp
i_main.c
i_video.cpp

406
src/sdl/i_gamepad.c Normal file
View file

@ -0,0 +1,406 @@
// Emacs style mode select -*- C++ -*-
// BLANKART
//-----------------------------------------------------------------------------
//
// Copyright (C) 1993-1996 by id Software, Inc.
// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 2014-2020 by Sonic Team Junior.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//-----------------------------------------------------------------------------
/// \file i_gamepad.c
/// \brief Blankart Gamepad Handling
#ifdef HAVE_SDL
#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_gamepad.h>
#include <SDL3/SDL_video.h>
#include "../doomdef.h"
#include "../d_main.h"
#include "../d_netcmd.h"
#include "../m_argv.h"
#include "../i_gamepad.h"
#include "../i_system.h"
#include "sdlmain.h"
// information on the Controller a player uses
controllerinfo_t controllerInfo[MAXSPLITSCREENPLAYERS] = {};
static INT32 numcontrollers = 0;
//
// I_ControllerReset
//
static void I_ControllerReset(controllerinfo_t *controller)
{
if (controller->dev)
{
SDL_CloseGamepad(controller->dev);
}
controller->dev = NULL;
//controller->joydev = NULL;
controller->id = -1;
//controller->name = NULL;
controller->hasrumble = false;
controller->hasrgbled = false;
}
//
// I_ShutdownController
//
void I_ShutdownController(UINT8 index)
{
INT32 i;
event_t event;
event.device = index+1;
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_JOY1+i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick;
for (i = 0; i < JOYAXISES; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
I_ControllerReset(&controllerInfo[index]);
}
void I_ShutdownControllerSystem(void)
{
UINT8 i;
// Yes, the name is misleading: these send neutral events to
// clean up the unplugged joystick's input
// Note these methods are internal to this file, not called elsewhere.
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
I_ShutdownController(i);
// reset this just in case
numcontrollers = 0;
if (SDL_WasInit(SDL_INIT_GAMEPAD) == SDL_INIT_GAMEPAD)
{
CONS_Printf("Shutting down gamecontroller system\n");
SDL_QuitSubSystem(SDL_INIT_GAMEPAD);
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");
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
I_OutputMsg("I_Joystick: SDL's Joystick system has been shutdown\n");
}
}
//
// I_InitController
//
void I_InitController(UINT8 playernum)
{
SDL_Gamepad *newcontroller = NULL;
SDL_JoystickID *controller_list = NULL;
int num_joy = 0;
if (M_CheckParm("-nojoy"))
return;
{
char dbpath[1024];
sprintf(dbpath, "%s" PATHSEP "gamecontrollerdb.txt", srb2path);
SDL_AddGamepadMappingsFromFile(dbpath);
}
{
char dbpath[1024];
sprintf(dbpath, "%s" PATHSEP "gamecontrollerdb_user.txt", srb2home);
SDL_AddGamepadMappingsFromFile(dbpath);
}
if (M_CheckParm("-noxinput"))
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nohidapi"))
SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nolibusb"))
SDL_SetHintWithPriority("SDL_HIDAPI_LIBUSB", "0", SDL_HINT_OVERRIDE);
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf("I_InitController()...\n");
if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return;
}
}
if (SDL_WasInit(SDL_INIT_GAMEPAD) == 0)
{
if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD))
{
CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
return;
}
}
I_ControllerReset(&controllerInfo[playernum]);
// dont need to do any of this if we dont want to use a controller
if (cv_usecontroller[playernum].value <= 0)
return;
controller_list = SDL_GetGamepads(&num_joy);
if (!controller_list)
{
CONS_Debug(DBG_GAMELOGIC, "Failed to fetch Controller list: %s\n", SDL_GetError());
return;
}
if (cv_usecontroller[playernum].value > num_joy)
{
SDL_free(controller_list);
return;
}
SDL_JoystickID joystick_id = controller_list[cv_usecontroller[playernum].value - 1];
if (joystick_id == 0)
{
CONS_Debug(DBG_GAMELOGIC, "Failed to get Controller instance id for Player %d: %s\n", playernum+1, SDL_GetError());
SDL_free(controller_list);
return;
}
// dont need this anymore
SDL_free(controller_list);
newcontroller = SDL_OpenGamepad(joystick_id);
if (!newcontroller)
{
CONS_Debug(DBG_GAMELOGIC, "Failed to open Controller with id %d for Player %d: %s\n", joystick_id, playernum+1, SDL_GetError());
return;
}
// fill in our controller info
controllerinfo_t *controller = &controllerInfo[playernum];
controller->dev = newcontroller;
//controller->joydev = SDL_GetGamepadJoystick(newcontroller);
controller->id = joystick_id;
//controller->name = SDL_GetGamepadNameForID(joystick_id);
SDL_PropertiesID controllerproperties = SDL_GetGamepadProperties(newcontroller);
controller->hasrumble = SDL_GetBooleanProperty(controllerproperties, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false);
controller->hasrgbled = SDL_GetBooleanProperty(controllerproperties, SDL_PROP_GAMEPAD_CAP_RGB_LED_BOOLEAN, false);
}
void I_InitController1(void)
{
I_InitController(0);
}
void I_InitController2(void)
{
I_InitController(1);
}
void I_InitController3(void)
{
I_InitController(2);
}
void I_InitController4(void)
{
I_InitController(3);
}
//
// I_ControllerScale
//
void I_ControllerScale(void)
{
Joystick[0].bGamepadStyle = cv_controllerscale[0].value == 0;
controllerInfo[0].scale = Joystick[0].bGamepadStyle ? 1 : cv_controllerscale[0].value;
}
void I_ControllerScale2(void)
{
Joystick[1].bGamepadStyle = cv_controllerscale[1].value == 0;
controllerInfo[1].scale = Joystick[1].bGamepadStyle ? 1 : cv_controllerscale[1].value;
}
void I_ControllerScale3(void)
{
Joystick[2].bGamepadStyle = cv_controllerscale[2].value == 0;
controllerInfo[2].scale = Joystick[2].bGamepadStyle ? 1 : cv_controllerscale[2].value;
}
void I_ControllerScale4(void)
{
Joystick[3].bGamepadStyle = cv_controllerscale[3].value == 0;
controllerInfo[3].scale = Joystick[3].bGamepadStyle ? 1 : cv_controllerscale[3].value;
}
static SDL_JoystickID *controllerlist = NULL;
void I_UpdateControllerList(void)
{
int num_joy = 0;
if (controllerlist)
SDL_free(controllerlist);
controllerlist = SDL_GetGamepads(&num_joy);
if (!controllerlist)
{
CONS_Debug(DBG_GAMELOGIC, "Failed to fetch Controller list: %s\n", SDL_GetError());
numcontrollers = 0;
return;
}
numcontrollers = num_joy;
}
//
// I_GetControllerID
// Cheat to get the device index for a game controller handle
//
INT32 I_GetControllerID(SDL_Gamepad *dev)
{
if (dev)
{
return (INT32)SDL_GetGamepadID(dev);
}
return -1;
}
INT32 I_GetControllerSlotfromID(INT32 id)
{
if (!controllerlist)
{
CONS_Debug(DBG_GAMELOGIC, "Failed to fetch Controller list: %s\n", SDL_GetError());
return -1;
}
for (int i = 0; i < numcontrollers; i++)
{
if (controllerlist[i] == (SDL_JoystickID)id)
{
return i+1;
}
}
return -1;
}
//
// I_GetControllerIDForPlayer
// Cheat to get the device index for a specified player
//
INT32 I_GetControllerIDForPlayer(UINT8 pnum)
{
if (controllerInfo[pnum].dev)
{
return (INT32)controllerInfo[pnum].id;
}
return -1;
}
//
// I_NumControllers
// Updates the number of connected controllers
//
INT32 I_NumControllers(void)
{
return numcontrollers;
}
//
// I_GetControllerName
// joystick name is straight from the driver
//
const char *I_GetControllerName(INT32 joyid)
{
if (SDL_WasInit(SDL_INIT_GAMEPAD) == SDL_INIT_GAMEPAD)
{
if (joyid <= 0)
return NULL;
if (!controllerlist)
return NULL;
SDL_JoystickID joystick_id = controllerlist[joyid - 1];
return SDL_GetGamepadNameForID(joystick_id);
}
return NULL;
}
//
// Controller Rumble and RGB LED stuff
//
boolean I_ControllerSupportsRumble(INT32 playernum)
{
return (controllerInfo[playernum].dev && controllerInfo[playernum].hasrumble);
}
boolean I_ControllerSupportsIndicatorColor(INT32 playernum)
{
return (controllerInfo[playernum].dev && controllerInfo[playernum].hasrgbled);
}
void I_ControllerRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
{
SDL_Gamepad *controller = controllerInfo[playernum].dev;
if (controller == NULL || !I_ControllerSupportsRumble(playernum))
{
return;
}
SDL_RumbleGamepad(controller, low_strength, high_strength, duration);
}
void I_SetControllerIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue)
{
SDL_Gamepad *controller = controllerInfo[playernum].dev;
if (controller == NULL || !I_ControllerSupportsIndicatorColor(playernum))
{
return;
}
SDL_SetGamepadLED(controller, red, green, blue);
}
#endif

View file

@ -23,8 +23,6 @@
/// \file
/// \brief SRB2 system stuff for SDL
#include <SDL3/SDL_gamepad.h>
#include <SDL3/SDL_joystick.h>
#include <thread>
#ifdef CMAKECONFIG
@ -195,7 +193,7 @@ static char returnWadPath[256];
#include "endtxt.h"
#include "sdlmain.h"
#include "../i_joy.h"
#include "../i_gamepad.h"
#include "../m_argv.h"
@ -218,34 +216,6 @@ static char returnWadPath[256];
static std::thread::id g_main_thread_id;
/** \brief The JoyReset function
\param JoySet Joystick info to reset
\return void
*/
static void JoyReset(SDLJoyInfo_t *JoySet)
{
if (JoySet->dev)
{
SDL_CloseGamepad(JoySet->dev);
}
JoySet->dev = NULL;
JoySet->id = -1;
JoySet->oldjoy = -1;
//JoySet->scale
}
/** \brief First joystick up and running
*/
static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0};
/** \brief SDL info about joystick 1
*/
SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
INT32 numcontrollers = 0;
SDL_Gamepad *ExJoystick[MAXGAMEPADS];
bool consolevent = false;
bool framebuffer = false;
@ -1037,480 +1007,6 @@ INT32 I_GetKey (void)
return rc;
}
//
// I_JoyScale
//
void I_JoyScale(void)
{
Joystick[0].bGamepadStyle = cv_joyscale[0].value==0;
JoyInfo[0].scale = Joystick[0].bGamepadStyle?1:cv_joyscale[0].value;
}
void I_JoyScale2(void)
{
Joystick[1].bGamepadStyle = cv_joyscale[1].value==0;
JoyInfo[1].scale = Joystick[1].bGamepadStyle?1:cv_joyscale[1].value;
}
void I_JoyScale3(void)
{
Joystick[2].bGamepadStyle = cv_joyscale[2].value==0;
JoyInfo[2].scale = Joystick[2].bGamepadStyle?1:cv_joyscale[2].value;
}
void I_JoyScale4(void)
{
Joystick[3].bGamepadStyle = cv_joyscale[3].value==0;
JoyInfo[3].scale = Joystick[3].bGamepadStyle?1:cv_joyscale[1].value;
}
// Cheat to get the device index for a game controller handle
INT32 I_GetJoystickID(SDL_Gamepad *dev)
{
if (dev)
{
return SDL_GetGamepadID(dev);
}
return -1;
}
INT32 I_GetJoystickIDForPlayer(UINT8 pnum)
{
if (JoyInfo[pnum].dev)
{
return SDL_GetGamepadID(JoyInfo[pnum].dev);
}
return -1;
}
void I_UpdateJoystickDeviceIndex(UINT8 player)
{
///////////////////////////////////////////////
// update this joystick's device index (wow) //
///////////////////////////////////////////////
if (JoyInfo[player].dev)
{
cv_usejoystick[player].value = JoyInfo[player].id + 1;
}
else
{
UINT8 joystickID, compareJoystick;
for (joystickID = 0; joystickID < MAXSPLITSCREENPLAYERS; joystickID++)
{
// is this cv_usejoystick used?
const INT32 value = atoi(cv_usejoystick[joystickID].string);
for (compareJoystick = 0; compareJoystick < MAXSPLITSCREENPLAYERS; compareJoystick++)
{
if (compareJoystick == player)
continue;
if (value == JoyInfo[compareJoystick].oldjoy || value == cv_usejoystick[compareJoystick].value)
break;
}
if (compareJoystick == MAXSPLITSCREENPLAYERS)
{
// We DID make it through the whole loop, so we can use this one!
cv_usejoystick[player].value = value;
break;
}
}
if (joystickID == MAXSPLITSCREENPLAYERS)
{
// We DID NOT make it through the whole loop, so we can't assign this joystick to anything.
// When you try your best, but you don't succeed...
cv_usejoystick[player].value = 0;
}
}
}
// Misleading function: updates device indices for all players BUT the one specified.
// Necessary for SDL_JOYDEVICEADDED events
void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer)
{
UINT8 player;
for (player = 0; player < MAXSPLITSCREENPLAYERS; player++)
{
if (player == excludePlayer)
continue;
I_UpdateJoystickDeviceIndex(player);
}
}
/** \brief Shuts down joystick
\return void
*/
void I_ShutdownJoystick(UINT8 index)
{
INT32 i;
event_t event;
event.device = I_GetJoystickID(JoyInfo[index].dev);
event.type = ev_keyup;
event.data2 = 0;
event.data3 = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.data1 = KEY_JOY1+i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick;
for (i = 0; i < JOYAXISES; i++)
{
event.data1 = i;
D_PostEvent(&event);
}
joystick_started[index] = 0;
JoyReset(&JoyInfo[index]);
// don't shut down the subsystem here, because hotplugging
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open(int playerIndex, int joyID)
{
SDL_Gamepad *newdev = NULL;
SDL_JoystickID *joystick_list = NULL;
int num_joy = 0;
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf(M_GetText("Joystick subsystem not started\n"));
return -1;
}
if (SDL_WasInit(SDL_INIT_GAMEPAD) == 0)
{
CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
return -1;
}
if (joyID <= 0)
return -1;
joystick_list = SDL_GetGamepads(&num_joy);
if (!joystick_list || num_joy == 0)
{
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
return -1;
}
if (joyID > num_joy)
{
SDL_free(joystick_list);
return -1;
}
SDL_JoystickID joystick_id = joystick_list[joyID - 1];
SDL_free(joystick_list);
newdev = SDL_OpenGamepad(joystick_id);
// 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.
//
// Example:
// 1. Plug Controller A -> Index 0 opened
// 2. Plug Controller B -> Index 1 opened
// 3. Unplug Controller A -> Index 0 closed, Index 1 active
// 4. Unplug Controller B -> Index 0 inactive, Index 1 closed
// 5. Plug Controller B -> Index 0 opened
// 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B
if (JoyInfo[playerIndex].dev)
{
if (JoyInfo[playerIndex].dev == newdev // same device, nothing to do
|| (newdev == NULL && SDL_GamepadConnected(JoyInfo[playerIndex].dev))) // we failed, but already have a working device
{
return SDL_GAMEPAD_AXIS_COUNT;
}
// Else, we're changing devices, so send neutral joy events
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device is changing; resetting events...\n", playerIndex+1);
I_ShutdownJoystick(playerIndex);
}
JoyInfo[playerIndex].dev = newdev;
JoyInfo[playerIndex].id = joystick_id;;
if (JoyInfo[playerIndex].dev == NULL)
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: Couldn't open device - %s\n"), playerIndex+1, SDL_GetError());
return -1;
}
else
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: %s\n"), playerIndex+1, SDL_GetGamepadName(JoyInfo[playerIndex].dev));
JoyInfo[playerIndex].axises = SDL_GAMEPAD_AXIS_COUNT;
JoyInfo[playerIndex].buttons = SDL_GAMEPAD_BUTTON_COUNT;
JoyInfo[playerIndex].hats = 1;
JoyInfo[playerIndex].balls = 0;
//JoyInfo[playerIndex].bGamepadStyle = fasticmp(SDL_JoystickName(JoyInfo[playerIndex].dev), "pad");
return JoyInfo[playerIndex].axises;
}
}
//
// I_InitJoystick
//
void I_InitJoystick(UINT8 index)
{
SDL_Gamepad *newcontroller = NULL;
SDL_JoystickID *joystick_list = NULL;
int num_joy = 0;
UINT8 i;
//I_ShutdownJoystick();
//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nojoy"))
return;
{
char dbpath[1024];
sprintf(dbpath, "%s" PATHSEP "gamecontrollerdb.txt", srb2path);
SDL_AddGamepadMappingsFromFile(dbpath);
}
{
char dbpath[1024];
sprintf(dbpath, "%s" PATHSEP "gamecontrollerdb_user.txt", srb2home);
SDL_AddGamepadMappingsFromFile(dbpath);
}
if (M_CheckParm("-noxinput"))
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nohidapi"))
SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nolibusb"))
SDL_SetHintWithPriority("SDL_HIDAPI_LIBUSB", "0", SDL_HINT_OVERRIDE);
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf("I_InitJoystick()...\n");
if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return;
}
}
if (SDL_WasInit(SDL_INIT_GAMEPAD) == 0)
{
if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD))
{
CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
return;
}
}
joystick_list = SDL_GetGamepads(&num_joy);
if (joystick_list && cv_usejoystick[index].value > 0 && cv_usejoystick[index].value <= num_joy)
{
SDL_JoystickID joystick_id = joystick_list[cv_usejoystick[index].value - 1];
newcontroller = SDL_OpenGamepad(joystick_id);
}
if (joystick_list)
SDL_free(joystick_list);
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (i == index)
continue;
if (JoyInfo[i].dev == newcontroller)
break;
}
JoyInfo[index].id = I_GetJoystickID(JoyInfo[index].dev);
if (newcontroller && i < MAXSPLITSCREENPLAYERS) // don't override an active device
{
cv_usejoystick[index].value = JoyInfo[index].id + 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.
JoyInfo[index].oldjoy = JoyInfo[index].id + 1;
joystick_started[index] = 1;
}
else
{
if (JoyInfo[index].oldjoy)
I_ShutdownJoystick(index);
cv_usejoystick[index].value = 0;
joystick_started[index] = 0;
}
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (JoyInfo[i].dev == newcontroller)
break;
}
if (i == MAXSPLITSCREENPLAYERS)
{
// Joystick didn't end up being used
SDL_CloseGamepad(newcontroller);
}
}
void I_InitJoystick1(void)
{
I_InitJoystick(0);
}
void I_InitJoystick2(void)
{
I_InitJoystick(1);
}
void I_InitJoystick3(void)
{
I_InitJoystick(2);
}
void I_InitJoystick4(void)
{
I_InitJoystick(3);
}
static void I_ShutdownInput(void)
{
UINT8 i;
// Yes, the name is misleading: these send neutral events to
// clean up the unplugged joystick's input
// Note these methods are internal to this file, not called elsewhere.
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
I_ShutdownJoystick(i);
if (SDL_WasInit(SDL_INIT_GAMEPAD) == SDL_INIT_GAMEPAD)
{
CONS_Printf("Shutting down gamecontroller system\n");
SDL_QuitSubSystem(SDL_INIT_GAMEPAD);
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");
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
I_OutputMsg("I_Joystick: SDL's Joystick system has been shutdown\n");
}
}
INT32 I_NumJoys(void)
{
INT32 num_joy = 0;
if (SDL_WasInit(SDL_INIT_GAMEPAD) == SDL_INIT_GAMEPAD)
SDL_GetGamepads(&num_joy);
return num_joy;
}
static char joyname[255]; // joystick name is straight from the driver
const char *I_GetJoyName(INT32 joyid)
{
const char *tempname = NULL;
SDL_JoystickID *joystick_list = NULL;
int num_joy = 0;
joyname[0] = 0;
if (SDL_WasInit(SDL_INIT_GAMEPAD) == SDL_INIT_GAMEPAD)
{
if (joyid <= 0)
return joyname;
joystick_list = SDL_GetGamepads(&num_joy);
if (!joystick_list || joyid > num_joy)
{
if (joystick_list)
SDL_free(joystick_list);
return joyname;
}
SDL_JoystickID joystick_id = joystick_list[joyid - 1];
SDL_free(joystick_list);
tempname = SDL_GetGamepadNameForID(joystick_id);
if (tempname)
{
strncpy(joyname, tempname, 254);
joyname[254] = 0;
}
}
return joyname;
}
void I_GamepadRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
{
#if !(SDL_VERSION_ATLEAST(2,0,14))
(void)playernum;
(void)low_strength;
(void)high_strength;
(void)duration;
#else
SDL_Gamepad *controller = JoyInfo[playernum].dev;
if (controller == NULL)
{
return;
}
SDL_RumbleGamepad(controller, low_strength, high_strength, duration);
#endif
}
void I_SetGamepadIndicatorColor(INT32 playernum, UINT8 red, UINT8 green, UINT8 blue)
{
#if !(SDL_VERSION_ATLEAST(2,0,14))
(void)playernum;
(void)red;
(void)green;
(void)blue;
#else
SDL_Gamepad *controller = JoyInfo[playernum].dev;
if (controller == NULL)
{
return;
}
SDL_SetGamepadLED(controller, red, green, blue);
#endif
}
#ifndef NOMUMBLE
#ifdef HAVE_MUMBLE
// Best Mumble positional audio settings:
@ -1639,37 +1135,6 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener)
#undef WINMUMBLE
#endif // NOMUMBLE
//
// I_Tactile
//
void I_Tactile(FFType pFFType, const JoyFF_t *FFEffect)
{
// UNUSED.
(void)pFFType;
(void)FFEffect;
}
void I_Tactile2(FFType pFFType, const JoyFF_t *FFEffect)
{
// UNUSED.
(void)pFFType;
(void)FFEffect;
}
void I_Tactile3(FFType pFFType, const JoyFF_t *FFEffect)
{
// UNUSED.
(void)pFFType;
(void)FFEffect;
}
void I_Tactile4(FFType pFFType, const JoyFF_t *FFEffect)
{
// UNUSED.
(void)pFFType;
(void)FFEffect;
}
static ticcmd_t emptycmd[MAXSPLITSCREENPLAYERS];
/** \brief empty ticcmd for player 1
@ -1970,7 +1435,7 @@ void I_Quit(void)
I_ShutdownSound();
// use this for 1.28 19990220 by Kin
I_ShutdownGraphics();
I_ShutdownInput();
I_ShutdownControllerSystem();
I_ShutdownSystem();
SDL_Quit();
/* if option -noendtxt is set, don't print the text */
@ -2036,7 +1501,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...)
if (errorcount == 4)
I_ShutdownGraphics();
if (errorcount == 5)
I_ShutdownInput();
I_ShutdownControllerSystem();
if (errorcount == 6)
I_ShutdownSystem();
if (errorcount == 7)
@ -2096,7 +1561,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...)
I_ShutdownMusic();
I_ShutdownGraphics();
I_ShutdownInput();
I_ShutdownControllerSystem();
I_ShowErrorMessageBox(buffer, false);

View file

@ -58,7 +58,7 @@
#include "../d_main.h"
#include "../s_sound.h"
#include "../i_sound.h" // midi pause/unpause
#include "../i_joy.h"
#include "../i_gamepad.h"
#include "../st_stuff.h"
#include "../hu_stuff.h"
#include "../g_game.h"
@ -601,11 +601,6 @@ static void Impl_SetFocused(boolean focused)
}
}
static inline void SDLJoyRemap(event_t *event)
{
(void)event;
}
static INT32 SDLJoyAxis(const Sint16 axis, UINT8 pid)
{
// -32768 to 32767
@ -623,12 +618,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, UINT8 pid)
}
else
{
raxis = (abs(JoyInfo[pid].scale) > 1) ? ((raxis / JoyInfo[pid].scale) * JoyInfo[pid].scale) : raxis;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE)
raxis = 0;
#endif
raxis = (abs(controllerInfo[pid].scale) > 1) ? ((raxis / controllerInfo[pid].scale) * controllerInfo[pid].scale) : raxis;
}
return raxis;
@ -844,6 +834,61 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
}
}
// ill put this here if blan wants this
// allows controller dpads to scroll through menus
/*
static UINT8 hatrepeattimer[MAXSPLITSCREENPLAYERS];
#define HATREPEATDELAY 19
void I_HandleControllerHatRepeat(void)
{
// why bother if theres no controllers?
if (numcontrollers == 0)
return;
event_t event = {ev_keydown, 0, 0, 0};
static const SDL_GameControllerButton hatbutt[4] =
{
SDL_CONTROLLER_BUTTON_DPAD_UP,
SDL_CONTROLLER_BUTTON_DPAD_DOWN,
SDL_CONTROLLER_BUTTON_DPAD_LEFT,
SDL_CONTROLLER_BUTTON_DPAD_RIGHT
};
for (int i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (!cv_usejoystick[i].value)
continue;
SDL_GameController *controller = JoyInfo[i].dev;
if (!controller)
continue;
for (UINT8 h = 0; h < JOYHATS; h++)
{
if (SDL_GameControllerGetButton(controller, hatbutt[h]))
{
if (hatrepeattimer[i] < HATREPEATDELAY)
{
hatrepeattimer[i]++;
}
else if (hatrepeattimer[i] == HATREPEATDELAY)
{
event.data1 = KEY_HAT1 + (i * JOYHATS) + h;
D_PostEvent(&event);
}
return;
}
}
hatrepeattimer[i] = 0;
}
}
*/
static void Impl_HandleControllerAxisEvent(SDL_GamepadAxisEvent evt)
{
event_t event;
@ -884,7 +929,7 @@ static void Impl_HandleControllerAxisEvent(SDL_GamepadAxisEvent evt)
}
//value
event.data2 = SDLJoyAxis(evt.value, evt.which);
event.data2 = SDLJoyAxis(evt.value, G_GetDevicePlayer(event.device));
D_PostEvent(&event);
}
@ -924,8 +969,6 @@ static void Impl_HandleControllerButtonEvent(SDL_GamepadButtonEvent evt, Uint32
return;
}
SDLJoyRemap(&event);
if (event.type != ev_console)
{
D_PostEvent(&event);
@ -937,79 +980,25 @@ static void Impl_HandleControllerAddEvent(SDL_Event evt)
UINT8 i;
SDL_JoystickID joystick_id = evt.gdevice.which;
SDL_Gamepad *newcontroller = SDL_OpenGamepad(joystick_id);
CONS_Debug(DBG_GAMELOGIC, "Controller device index %d added\n", joystick_id + 1);
// Because SDL's device index is unstable, we're going to cheat here a bit:
// For the first joystick setting that is NOT active:
//
// 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg)
//
// 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed
// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
// * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
if (joystick_id == 0)
{
if (newcontroller && (!JoyInfo[i].dev || !SDL_GamepadConnected(JoyInfo[i].dev)))
{
UINT8 j;
for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
{
if (i == j)
continue;
if (JoyInfo[j].dev == newcontroller)
break;
}
if (j == MAXSPLITSCREENPLAYERS)
{
// ensures we aren't overriding a currently active device
cv_usejoystick[i].value = joystick_id + 1;
I_UpdateJoystickDeviceIndices(0);
}
}
}
// Was cv_usejoystick disabled in settings?
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (fastcmp(cv_usejoystick[i].string, "0") || !cv_usejoystick[i].value)
cv_usejoystick[i].value = 0;
else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
&& cv_usejoystick[i].value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value);
}
// Update all joysticks' init states
// This is a little wasteful since cv_usejoystick already calls this, but
// we need to do this in case CV_SetValue did nothing because the string was already same.
// if the device is already active, this should do nothing, effectively.
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
I_InitJoystick(i);
G_SetPlayerGamepadIndicatorColor(i, SKINCOLOR_NONE); // gotta update the controller led again on reconnect
CONS_Debug(DBG_GAMELOGIC, "Invalid Controller: %s\n", SDL_GetError());
return;
}
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
{
I_InitController(i);
G_SetPlayerControllerIndicatorColor(i, SKINCOLOR_NONE); // gotta update the controller led again on reconnect
}
I_UpdateControllerList();
// update the menu
if (menustack[0] == MN_OP_JOYSTICKSET)
MR_SetupJoystickMenu(0);
numcontrollers = I_NumJoys();
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (JoyInfo[i].dev == newcontroller)
break;
}
if (i == MAXSPLITSCREENPLAYERS)
SDL_CloseGamepad(newcontroller);
CONS_Debug(DBG_GAMELOGIC, "Controller device index %d added\n", joystick_id);
}
static void Impl_HandleControllerRemoveEvent(SDL_Event evt)
@ -1017,44 +1006,26 @@ static void Impl_HandleControllerRemoveEvent(SDL_Event evt)
UINT8 i;
SDL_JoystickID joystick_id = evt.gdevice.which;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
if (joystick_id == 0)
{
if (JoyInfo[i].dev && JoyInfo[i].id == joystick_id && !SDL_GamepadConnected(JoyInfo[i].dev))
{
CONS_Debug(DBG_GAMELOGIC, "Joystick%d removed, device index: %d\n", i+1, joystick_id);
I_ShutdownJoystick(i);
}
}
// Update the device indexes, because they likely changed
// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
// * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
I_UpdateJoystickDeviceIndex(i);
}
// Was cv_usejoystick disabled in settings?
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (fastcmp(cv_usejoystick[i].string, "0"))
{
cv_usejoystick[i].value = 0;
}
else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
&& cv_usejoystick[i].value) // update the cvar ONLY if a device exists
{
CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value);
}
CONS_Debug(DBG_GAMELOGIC, "Invalid Controller: %s\n", SDL_GetError());
return;
}
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
{
if (controllerInfo[i].dev && (controllerInfo[i].id == (INT32)joystick_id) && !SDL_GamepadConnected(controllerInfo[i].dev))
{
CONS_Debug(DBG_GAMELOGIC, "Controller for Player %d removed, device index: %d\n", i+1, joystick_id);
I_ShutdownController(i);
}
}
I_UpdateControllerList();
// update the menu
if (menustack[0] == MN_OP_JOYSTICKSET)
MR_SetupJoystickMenu(0);
numcontrollers = I_NumJoys();
}
void I_GetEvent(void)

View file

@ -1793,8 +1793,8 @@
841777A5085A1200000C01D8 = {
fileEncoding = 30;
isa = PBXFileReference;
name = i_joy.h;
path = ../../i_joy.h;
name = i_gamepad.h;
path = ../../i_gamepad.h;
refType = 2;
};
841777A6085A1200000C01D8 = {

View file

@ -228,7 +228,7 @@
1E44AED60B67CD1200BAD059 /* i_tcp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i_tcp.h; path = ../../i_tcp.h; sourceTree = SOURCE_ROOT; };
1E44AED70B67CD1200BAD059 /* i_system.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i_system.h; path = ../../i_system.h; sourceTree = SOURCE_ROOT; };
1E44AED80B67CD1200BAD059 /* i_video.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i_video.h; path = ../../i_video.h; sourceTree = SOURCE_ROOT; };
1E44AED90B67CD1300BAD059 /* i_joy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i_joy.h; path = ../../i_joy.h; sourceTree = SOURCE_ROOT; };
1E44AED90B67CD1300BAD059 /* i_gamepad.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i_gamepad.h; path = ../../i_gamepad.h; sourceTree = SOURCE_ROOT; };
1E44AEE10B67CD2B00BAD059 /* am_map.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = am_map.c; path = ../../am_map.c; sourceTree = SOURCE_ROOT; };
1E44AEE20B67CD2B00BAD059 /* am_map.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = am_map.h; path = ../../am_map.h; sourceTree = SOURCE_ROOT; };
1E44AEE50B67CD3200BAD059 /* byteptr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = byteptr.h; path = ../../byteptr.h; sourceTree = SOURCE_ROOT; };
@ -651,7 +651,7 @@
1E44AED60B67CD1200BAD059 /* i_tcp.h */,
1E44AED70B67CD1200BAD059 /* i_system.h */,
1E44AED80B67CD1200BAD059 /* i_video.h */,
1E44AED90B67CD1300BAD059 /* i_joy.h */,
1E44AED90B67CD1300BAD059 /* i_gamepad.h */,
1E44AEF50B67CD9F00BAD059 /* keys.h */,
1E44AF200B67CE4100BAD059 /* mserv.c */,
1E44AF210B67CE4100BAD059 /* mserv.h */,

View file

@ -32,7 +32,8 @@ extern "C" {
// SDL3 stub macro
#define SDL3STUB() CONS_Printf("SDL3: stubbed: %s:%d\n", __func__, __LINE__)
// So m_menu knows whether to store cv_usejoystick value or string
// So m_menu knows whether to store cv_usecontroller value or string
#define JOYSTICK_HOTPLUG
/** \brief The JoyInfo_s struct
@ -41,48 +42,36 @@ extern "C" {
*/
typedef struct SDLJoyInfo_s
{
/// Controller handle
/// Gamepad handle
SDL_Gamepad *dev;
/// Joystick handle
//SDL_Joystick *joydev;
/// Controller index
INT32 id;
/// number of old joystick
int oldjoy;
/// number of axies
int axises;
INT32 id; // SDL_JoystickID
/// name of controller
//const char *name;
/// scale of axises
INT32 scale;
/// number of buttons
int buttons;
/// number of hats
int hats;
/// number of balls
int balls;
} SDLJoyInfo_t;
// Rumble Support
boolean hasrumble;
// RGB LED Support
boolean hasrgbled;
} controllerinfo_t;
/** \brief SDL info about controllers
*/
extern SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
extern SDL_Gamepad *ExJoystick[MAXGAMEPADS];
extern controllerinfo_t controllerInfo[MAXSPLITSCREENPLAYERS];
void I_StoreExJoystick(SDL_Gamepad *dev);
/** \brief joystick axis deadzone
*/
#define SDL_JDEADZONE 153
#undef SDL_JDEADZONE
void I_GetConsoleEvents(void);
void I_ShutdownControllerSystem(void);
// So we can call this from i_video event loop
void I_ShutdownJoystick(UINT8 index);
void I_ShutdownController(UINT8 index);
// Cheat to get the device index for a game controller handle
INT32 I_GetJoystickID(SDL_Gamepad *dev);
INT32 I_GetControllerID(SDL_Gamepad *dev);
void I_UpdateControllerList(void);
// Quick thing to make SDL_JOYDEVICEADDED events less of an abomination
void I_UpdateJoystickDeviceIndex(UINT8 player);
void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer);
void I_GetConsoleEvents(void);

View file

@ -138,7 +138,7 @@ TYPEDEF (mapsearchfreq_t);
// hu_stuff.h
TYPEDEF (playersort_t);
// i_joy.h
// i_gamepad.h
TYPEDEF (JoyType_t);
// i_net.h