Revert "Merge branch 'gamepad-refactor' into next"

This reverts commit 696e2ab909, reversing
changes made to d98d59494f.
This commit is contained in:
Eidolon 2023-01-26 19:26:28 -06:00
parent 366ee4ad92
commit e5dea805fa
34 changed files with 2663 additions and 3556 deletions

View file

@ -51,7 +51,6 @@ p_spec.c
p_telept.c
p_tick.c
p_user.c
p_haptic.c
p_slopes.c
tables.c
r_bsp.c

View file

@ -77,6 +77,7 @@ CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
// Filter consvars by EXECVERSION
// First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
// Also set CV_HIDEN during runtime, after config is loaded
static boolean execversion_enabled = false;
consvar_t cv_execversion = CVAR_INIT ("execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion);
@ -2233,12 +2234,12 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
// reset all axis settings to defaults
if (joyaxis_count == 6)
{
COM_BufInsertText(va("%s \"%s\"\n", cv_turnaxis[0].name, cv_turnaxis[0].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_moveaxis[0].name, cv_moveaxis[0].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_sideaxis[0].name, cv_sideaxis[0].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_lookaxis[0].name, cv_lookaxis[0].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_fireaxis[0].name, cv_fireaxis[0].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_firenaxis[0].name, cv_firenaxis[0].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_turnaxis.name, cv_turnaxis.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_moveaxis.name, cv_moveaxis.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_sideaxis.name, cv_sideaxis.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_lookaxis.name, cv_lookaxis.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_fireaxis.name, cv_fireaxis.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_firenaxis.name, cv_firenaxis.defaultvalue));
joyaxis_count++;
return false;
}
@ -2292,12 +2293,12 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
// reset all axis settings to defaults
if (joyaxis2_count == 6)
{
COM_BufInsertText(va("%s \"%s\"\n", cv_turnaxis[1].name, cv_turnaxis[1].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_moveaxis[1].name, cv_moveaxis[1].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_sideaxis[1].name, cv_sideaxis[1].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_lookaxis[1].name, cv_lookaxis[1].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_fireaxis[1].name, cv_fireaxis[1].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_firenaxis[1].name, cv_firenaxis[1].defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_turnaxis2.name, cv_turnaxis2.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_moveaxis2.name, cv_moveaxis2.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_sideaxis2.name, cv_sideaxis2.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_lookaxis2.name, cv_lookaxis2.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_fireaxis2.name, cv_fireaxis2.defaultvalue));
COM_BufInsertText(va("%s \"%s\"\n", cv_firenaxis2.name, cv_firenaxis2.defaultvalue));
joyaxis2_count++;
return false;
}
@ -2307,49 +2308,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
return true;
}
#ifndef OLD_GAMEPAD_AXES
static boolean CV_ConvertOldJoyAxisVars(consvar_t *v, const char *valstr)
{
static struct {
const char *old;
const char *new;
} axis_names[] = {
{"X-Axis", "Left Stick X"},
{"Y-Axis", "Left Stick Y"},
{"X-Axis-", "Left Stick X-"},
{"Y-Axis-", "Left Stick Y-"},
{"X-Rudder", "Right Stick X"},
{"Y-Rudder", "Right Stick Y"},
{"X-Rudder-", "Right Stick X-"},
{"Y-Rudder-", "Right Stick Y-"},
{"Z-Axis", "Left Trigger"},
{"Z-Rudder", "Right Trigger"},
{"Z-Axis-", "Left Trigger"},
{"Z-Rudder-", "Right Trigger"},
{NULL, NULL}
};
if (v->PossibleValue != joyaxis_cons_t)
return true;
for (unsigned i = 0;; i++)
{
if (axis_names[i].old == NULL)
{
CV_SetCVar(v, "None", false);
return false;
}
else if (!stricmp(valstr, axis_names[i].old))
{
CV_SetCVar(v, axis_names[i].new, false);
return false;
}
}
return true;
}
#endif
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
{
// True means allow the CV change, False means block it
@ -2378,8 +2336,8 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
&& atoi(valstr) == 35)
return false;
// GAMEPAD DEFAULTS
// use_gamepad was changed from 0 to 1 to automatically use a gamepad if available
// JOYSTICK DEFAULTS
// use_joystick was changed from 0 to 1 to automatically use a joystick if available
#if defined(HAVE_SDL) || defined(_WINDOWS)
if ((!stricmp(v->name, "use_joystick")
|| !stricmp(v->name, "use_joystick2"))
@ -2392,15 +2350,6 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
if (!CV_FilterJoyAxisVars(v, valstr))
return false;
}
#ifndef OLD_GAMEPAD_AXES
if (GETMAJOREXECVERSION(cv_execversion.value) <= 51 && GETMINOREXECVERSION(cv_execversion.value) < 1)
{
if (!CV_ConvertOldJoyAxisVars(v, valstr))
return false;
}
#endif
return true;
}

View file

@ -918,8 +918,7 @@ boolean CON_Responder(event_t *ev)
static INT32 alias_skips;
const char *cmd = NULL;
INT32 key = ev->key;
boolean key_is_console = (key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]);
INT32 key;
if (chat_on)
return false;
@ -927,18 +926,20 @@ boolean CON_Responder(event_t *ev)
// let go keyup events, don't eat them
if (ev->type != ev_keydown && ev->type != ev_console)
{
if (key_is_console)
if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1])
consdown = false;
return false;
}
key = ev->key;
// check for console toggle key
if (ev->type != ev_console)
{
if (modeattacking || metalrecording || marathonmode)
return false;
if (key_is_console)
if (key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1])
{
if (consdown) // ignore repeat
return true;

View file

@ -25,8 +25,7 @@
#include "st_stuff.h"
#include "hu_stuff.h"
#include "keys.h"
#include "g_input.h"
#include "i_gamepad.h"
#include "g_input.h" // JOY1
#include "m_menu.h"
#include "console.h"
#include "d_netfil.h"
@ -34,7 +33,6 @@
#include "p_saveg.h"
#include "z_zone.h"
#include "p_local.h"
#include "p_haptic.h"
#include "m_misc.h"
#include "am_map.h"
#include "m_random.h"
@ -51,7 +49,7 @@
#include "m_perfstats.h"
// aaaaaa
#include "i_gamepad.h"
#include "i_joy.h"
#ifndef NONET
// cl loading screen
@ -655,6 +653,22 @@ static UINT8 Snake_GetOppositeDir(UINT8 dir)
return 12 + 5 - dir;
}
event_t *snakejoyevents[MAXEVENTS];
UINT16 joyeventcount = 0;
// I'm screaming the hack is clean - ashi
static boolean Snake_Joy_Grabber(event_t *ev)
{
if (ev->type == ev_joystick && ev->key == 0)
{
snakejoyevents[joyeventcount] = ev;
joyeventcount++;
return true;
}
else
return false;
}
static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady)
{
UINT8 x, y;
@ -681,17 +695,19 @@ static void Snake_Handle(void)
UINT8 x, y;
UINT8 oldx, oldy;
UINT16 i;
UINT16 j;
UINT16 joystate = 0;
static INT32 pjoyx = 0, pjoyy = 0;
// Handle retry
if (snake->gameover && (G_PlayerInputDown(0, GC_JUMP) || gamekeydown[KEY_ENTER]))
if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER]))
{
Snake_Initialise();
snake->pausepressed = true; // Avoid accidental pause on respawn
}
// Handle pause
if (G_PlayerInputDown(0, GC_PAUSE) || gamekeydown[KEY_ENTER])
if (PLAYER1INPUTDOWN(GC_PAUSE) || gamekeydown[KEY_ENTER])
{
if (!snake->pausepressed)
snake->paused = !snake->paused;
@ -710,23 +726,58 @@ static void Snake_Handle(void)
oldx = snake->snakex[1];
oldy = snake->snakey[1];
// process the input events in here dear lord
for (j = 0; j < joyeventcount; j++)
{
event_t *ev = snakejoyevents[j];
const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT;
if (ev->y != INT32_MAX)
{
if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone)
{
if (ev->y < 0 && pjoyy >= 0)
joystate = 1;
else if (ev->y > 0 && pjoyy <= 0)
joystate = 2;
pjoyy = ev->y;
}
else
pjoyy = 0;
}
if (ev->x != INT32_MAX)
{
if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone)
{
if (ev->x < 0 && pjoyx >= 0)
joystate = 3;
else if (ev->x > 0 && pjoyx <= 0)
joystate = 4;
pjoyx = ev->x;
}
else
pjoyx = 0;
}
}
joyeventcount = 0;
// Update direction
if (G_PlayerInputDown(0, GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3)
if (PLAYER1INPUTDOWN(GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3)
{
if (snake->snakelength < 2 || x <= oldx)
snake->snakedir[0] = 1;
}
else if (G_PlayerInputDown(0, GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4)
else if (PLAYER1INPUTDOWN(GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4)
{
if (snake->snakelength < 2 || x >= oldx)
snake->snakedir[0] = 2;
}
else if (G_PlayerInputDown(0, GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1)
else if (PLAYER1INPUTDOWN(GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1)
{
if (snake->snakelength < 2 || y <= oldy)
snake->snakedir[0] = 3;
}
else if (G_PlayerInputDown(0, GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2)
else if (PLAYER1INPUTDOWN(GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2)
{
if (snake->snakelength < 2 || y >= oldy)
snake->snakedir[0] = 4;
@ -1652,8 +1703,6 @@ static void CL_LoadReceivedSavegame(boolean reloading)
titledemo = false;
automapactive = false;
P_StopRumble(NULL);
// load a base level
if (P_LoadNetGame(reloading))
{
@ -1940,10 +1989,9 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
static void M_ConfirmConnect(event_t *ev)
{
#ifndef NONET
if (ev->type == ev_keydown || ev->type == ev_gamepad_down)
if (ev->type == ev_keydown)
{
if ((ev->type == ev_keydown && (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_A))
if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER || ev->key == KEY_JOY1)
{
if (totalfilesrequestednum > 0)
{
@ -1958,7 +2006,7 @@ static void M_ConfirmConnect(event_t *ev)
M_ClearMenus(true);
}
else if ((ev->type == ev_keydown && (ev->key == 'n' || ev->key == KEY_ESCAPE)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_B))
else if (ev->key == 'n' || ev->key == KEY_ESCAPE || ev->key == KEY_JOY1 + 3)
{
cl_mode = CL_ABORTED;
M_ClearMenus(true);
@ -2392,11 +2440,14 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
// my hand has been forced and I am dearly sorry for this awful hack :vomit:
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
{
G_MapEventsToControls(&events[eventtail]);
#ifndef NONET
if (!Snake_Joy_Grabber(&events[eventtail]))
#endif
G_MapEventsToControls(&events[eventtail]);
}
}
if (gamekeydown[KEY_ESCAPE] || gamepads[0].buttons[GAMEPAD_BUTTON_B] || cl_mode == CL_ABORTED)
if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED)
{
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
@ -5179,7 +5230,7 @@ static void Local_Maketic(INT32 realtics)
// game responder calls HU_Responder, AM_Responder,
// and G_MapEventsToControls
if (!dedicated) rendergametic = gametic;
// translate inputs (keyboard/mouse/gamepad) into game controls
// translate inputs (keyboard/mouse/joystick) into game controls
G_BuildTiccmd(&localcmds, realtics, 1);
if (splitscreen || botingame)
G_BuildTiccmd(&localcmds2, realtics, 2);

View file

@ -24,21 +24,19 @@ typedef enum
ev_keyup,
ev_console,
ev_mouse,
ev_joystick,
ev_mouse2,
ev_gamepad_up,
ev_gamepad_down,
ev_gamepad_axis
ev_joystick2,
} evtype_t;
// Event structure.
typedef struct
{
evtype_t type;
INT32 key; // key, mouse button, or gamepad button/axis type
INT32 x; // mouse x move, or gamepad axis value
INT32 y; // mouse y move
UINT8 which; // which gamepad or mouse ID
boolean repeated; // is the event repeated?
INT32 key; // keys/mouse/joystick buttons
INT32 x; // mouse/joystick x move
INT32 y; // mouse/joystick y move
boolean repeated; // key repeat
} event_t;
//

View file

@ -43,7 +43,6 @@
#include "i_time.h"
#include "i_threads.h"
#include "i_video.h"
#include "i_gamepad.h"
#include "m_argv.h"
#include "m_menu.h"
#include "m_misc.h"
@ -987,7 +986,6 @@ void D_StartTitle(void)
G_SetGametype(GT_COOP);
paused = false;
advancedemo = false;
P_StopRumble(NULL);
F_InitMenuPresValues();
F_StartTitleScreen();
@ -1398,9 +1396,6 @@ void D_SRB2Main(void)
CONS_Printf("I_InitializeTime()...\n");
I_InitializeTime();
// Initializes the game logic side of gamepads
G_InitGamepads();
// Make backups of some SOCcable tables.
P_BackupTables();
@ -1456,9 +1451,6 @@ void D_SRB2Main(void)
D_RegisterServerCommands();
D_RegisterClientCommands(); // be sure that this is called before D_CheckNetGame
I_InitGamepads();
R_RegisterEngineStuff();
S_RegisterSoundStuff();

View file

@ -21,7 +21,6 @@
#include "g_game.h"
#include "hu_stuff.h"
#include "g_input.h"
#include "i_gamepad.h"
#include "m_menu.h"
#include "r_local.h"
#include "r_skins.h"
@ -183,6 +182,14 @@ static CV_PossibleValue_t mouse2port_cons_t[] = {{1, "COM1"}, {2, "COM2"}, {3, "
{0, NULL}};
#endif
#ifdef LJOYSTICK
static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, {3, "/dev/js2"},
{4, "/dev/js3"}, {0, NULL}};
#else
// accept whatever value - it is in fact the joystick device number
#define usejoystick_cons_t NULL
#endif
static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}};
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
@ -241,61 +248,19 @@ INT32 cv_debug;
consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse);
consvar_t cv_usemouse2 = CVAR_INIT ("use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2);
// We use cv_usegamepad.string as the USER-SET var
// and cv_usegamepad.value as the INTERNAL var
//
// In practice, if cv_usegamepad.string == 0, this overrides
// cv_usegamepad.value and always disables
static void UseGamepad_OnChange(void)
{
I_ChangeGamepad(0);
}
static void UseGamepad2_OnChange(void)
{
I_ChangeGamepad(1);
}
consvar_t cv_usegamepad[2] = {
CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, NULL, UseGamepad_OnChange),
CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, NULL, UseGamepad2_OnChange)
};
static void PadScale_OnChange(void)
{
I_SetGamepadDigital(0, cv_gamepad_scale[0].value == 0);
}
static void PadScale2_OnChange(void)
{
I_SetGamepadDigital(1, cv_gamepad_scale[1].value == 0);
}
consvar_t cv_gamepad_scale[2] = {
CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, PadScale_OnChange),
CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, PadScale2_OnChange)
};
static void PadRumble_OnChange(void)
{
if (!cv_gamepad_rumble[0].value)
I_StopGamepadRumble(0);
}
static void PadRumble2_OnChange(void)
{
if (!cv_gamepad_rumble[1].value)
I_StopGamepadRumble(1);
}
consvar_t cv_gamepad_rumble[2] = {
CVAR_INIT ("padrumble", "Off", CV_SAVE|CV_CALL, CV_OnOff, PadRumble_OnChange),
CVAR_INIT ("padrumble2", "Off", CV_SAVE|CV_CALL, CV_OnOff, PadRumble2_OnChange)
};
consvar_t cv_gamepad_autopause = CVAR_INIT ("pauseongamepaddisconnect", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_usejoystick = CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick);
consvar_t cv_usejoystick2 = CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2);
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
#ifdef LJOYSTICK
consvar_t cv_joyport = CVAR_INIT ("padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL);
consvar_t cv_joyport2 = CVAR_INIT ("padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); //Alam: for later
#endif
consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale);
consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2);
#else
consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save
consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save
#endif
#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)
consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL);
consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL);
@ -807,26 +772,26 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_pauseifunfocused);
// g_input.c
CV_RegisterVar(&cv_sideaxis[0]);
CV_RegisterVar(&cv_sideaxis[1]);
CV_RegisterVar(&cv_turnaxis[0]);
CV_RegisterVar(&cv_turnaxis[1]);
CV_RegisterVar(&cv_moveaxis[0]);
CV_RegisterVar(&cv_moveaxis[1]);
CV_RegisterVar(&cv_lookaxis[0]);
CV_RegisterVar(&cv_lookaxis[1]);
CV_RegisterVar(&cv_jumpaxis[0]);
CV_RegisterVar(&cv_jumpaxis[1]);
CV_RegisterVar(&cv_spinaxis[0]);
CV_RegisterVar(&cv_spinaxis[1]);
CV_RegisterVar(&cv_fireaxis[0]);
CV_RegisterVar(&cv_fireaxis[1]);
CV_RegisterVar(&cv_firenaxis[0]);
CV_RegisterVar(&cv_firenaxis[1]);
CV_RegisterVar(&cv_deadzone[0]);
CV_RegisterVar(&cv_deadzone[1]);
CV_RegisterVar(&cv_digitaldeadzone[0]);
CV_RegisterVar(&cv_digitaldeadzone[1]);
CV_RegisterVar(&cv_sideaxis);
CV_RegisterVar(&cv_sideaxis2);
CV_RegisterVar(&cv_turnaxis);
CV_RegisterVar(&cv_turnaxis2);
CV_RegisterVar(&cv_moveaxis);
CV_RegisterVar(&cv_moveaxis2);
CV_RegisterVar(&cv_lookaxis);
CV_RegisterVar(&cv_lookaxis2);
CV_RegisterVar(&cv_jumpaxis);
CV_RegisterVar(&cv_jumpaxis2);
CV_RegisterVar(&cv_spinaxis);
CV_RegisterVar(&cv_spinaxis2);
CV_RegisterVar(&cv_fireaxis);
CV_RegisterVar(&cv_fireaxis2);
CV_RegisterVar(&cv_firenaxis);
CV_RegisterVar(&cv_firenaxis2);
CV_RegisterVar(&cv_deadzone);
CV_RegisterVar(&cv_deadzone2);
CV_RegisterVar(&cv_digitaldeadzone);
CV_RegisterVar(&cv_digitaldeadzone2);
// filesrch.c
CV_RegisterVar(&cv_addons_option);
@ -855,14 +820,14 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_mousemove);
CV_RegisterVar(&cv_mousemove2);
for (i = 0; i < 2; i++)
{
CV_RegisterVar(&cv_usegamepad[i]);
CV_RegisterVar(&cv_gamepad_scale[i]);
CV_RegisterVar(&cv_gamepad_rumble[i]);
}
CV_RegisterVar(&cv_gamepad_autopause);
CV_RegisterVar(&cv_usejoystick);
CV_RegisterVar(&cv_usejoystick2);
#ifdef LJOYSTICK
CV_RegisterVar(&cv_joyport);
CV_RegisterVar(&cv_joyport2);
#endif
CV_RegisterVar(&cv_joyscale);
CV_RegisterVar(&cv_joyscale2);
// Analog Control
CV_RegisterVar(&cv_analog[0]);
@ -2251,14 +2216,9 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
{
if (!menuactive || netgame)
S_PauseAudio();
P_PauseRumble(NULL);
}
else
{
S_ResumeAudio();
P_UnpauseRumble(NULL);
}
}
I_UpdateMouseGrab();
@ -4653,8 +4613,6 @@ void Command_ExitGame_f(void)
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
P_StopRumble(NULL);
if (dirmenu)
closefilemenu(true);

View file

@ -33,10 +33,14 @@ extern consvar_t cv_defaultskin2;
extern consvar_t cv_seenames, cv_allowseenames;
extern consvar_t cv_usemouse;
extern consvar_t cv_usegamepad[2];
extern consvar_t cv_gamepad_scale[2];
extern consvar_t cv_gamepad_rumble[2];
extern consvar_t cv_gamepad_autopause;
extern consvar_t cv_usejoystick;
extern consvar_t cv_usejoystick2;
#ifdef LJOYSTICK
extern consvar_t cv_joyport;
extern consvar_t cv_joyport2;
#endif
extern consvar_t cv_joyscale;
extern consvar_t cv_joyscale2;
// splitscreen with second mouse
extern consvar_t cv_mouse2port;

View file

@ -22,9 +22,9 @@
#include "v_video.h" // video flags (for lua)
#include "i_sound.h" // musictype_t (for lua)
#include "g_state.h" // gamestate_t (for lua)
#include "g_game.h" // Gamepad axes (for lua)
#include "g_game.h" // Joystick axes (for lua)
#include "i_joy.h"
#include "g_input.h" // Game controls (for lua)
#include "i_gamepad.h"
#include "deh_tables.h"
@ -4841,7 +4841,7 @@ const char *const MENUTYPES_LIST[] = {
"OP_CHANGECONTROLS", // OP_ChangeControlsDef shared with P2
"OP_P1MOUSE",
"OP_P1JOYSTICK",
"OP_JOYSTICKSET", // OP_GamepadSetDef shared with P2
"OP_JOYSTICKSET", // OP_JoystickSetDef shared with P2
"OP_P1CAMERA",
"OP_P2CONTROLS",
@ -5642,7 +5642,7 @@ struct int_const_s const INT_CONST[] = {
{"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER},
{"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS},
// Gamepad axes
// Joystick axes
{"JA_NONE",JA_NONE},
{"JA_TURN",JA_TURN},
{"JA_MOVE",JA_MOVE},
@ -5653,7 +5653,7 @@ struct int_const_s const INT_CONST[] = {
{"JA_SPIN",JA_SPIN},
{"JA_FIRE",JA_FIRE},
{"JA_FIRENORMAL",JA_FIRENORMAL},
{"JOYAXISRANGE",OLDJOYAXISRANGE},
{"JOYAXISRANGE",JOYAXISRANGE},
// Game controls
{"GC_NULL",GC_NULL},

View file

@ -209,7 +209,7 @@ extern char logfilename[1024];
// to an increment in MODVERSION. This might never happen in practice.
// If MODVERSION increases, set MINOREXECVERSION to 0.
#define MAJOREXECVERSION MODVERSION
#define MINOREXECVERSION 1
#define MINOREXECVERSION 0
// (It would have been nice to use VERSION and SUBVERSION but those are zero'd out for DEVELOP builds)
// Macros
@ -556,6 +556,9 @@ UINT32 quickncasehash (const char *p, size_t n)
#define max(x, y) (((x) > (y)) ? (x) : (y))
#endif
// Max gamepad/joysticks that can be detected/used.
#define MAX_JOYSTICKS 4
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif

View file

@ -37,7 +37,6 @@
#include "m_cond.h"
#include "p_local.h"
#include "p_setup.h"
#include "p_haptic.h"
#include "st_stuff.h" // hud hiding
#include "fastcmp.h"
#include "console.h"
@ -511,7 +510,6 @@ void F_StartIntro(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
P_StopRumble(NULL);
F_NewCutscene(introtext[0]);
intro_scenenum = 0;
@ -993,10 +991,9 @@ void F_IntroTicker(void)
//
boolean F_IntroResponder(event_t *event)
{
INT32 type = event->type;
INT32 key = G_RemapGamepadEvent(event, &type);
INT32 key = event->key;
// remap virtual keys (mouse & gamepad buttons)
// remap virtual keys (mouse & joystick buttons)
switch (key)
{
case KEY_MOUSE1:
@ -1005,30 +1002,34 @@ boolean F_IntroResponder(event_t *event)
case KEY_MOUSE1 + 1:
key = KEY_BACKSPACE;
break;
case GAMEPAD_KEY(START):
case GAMEPAD_KEY(A):
case GAMEPAD_KEY(X):
case GAMEPAD_KEY(B):
case KEY_JOY1:
case KEY_JOY1 + 2:
key = KEY_ENTER;
break;
case GAMEPAD_KEY(DPAD_UP):
case KEY_JOY1 + 3:
key = 'n';
break;
case KEY_JOY1 + 1:
key = KEY_BACKSPACE;
break;
case KEY_HAT1:
key = KEY_UPARROW;
break;
case GAMEPAD_KEY(DPAD_DOWN):
case KEY_HAT1 + 1:
key = KEY_DOWNARROW;
break;
case GAMEPAD_KEY(DPAD_LEFT):
case KEY_HAT1 + 2:
key = KEY_LEFTARROW;
break;
case GAMEPAD_KEY(DPAD_RIGHT):
case KEY_HAT1 + 3:
key = KEY_RIGHTARROW;
break;
}
if (type != ev_keydown)
if (event->type != ev_keydown && key != 301)
return false;
if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_SPACE && key != KEY_BACKSPACE)
if (key != 27 && key != KEY_ENTER && key != KEY_SPACE && key != KEY_BACKSPACE)
return false;
if (keypressed)
@ -1263,7 +1264,6 @@ void F_StartCredits(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
P_StopRumble(NULL);
S_StopMusic();
S_StopSounds();
@ -1376,10 +1376,9 @@ void F_CreditTicker(void)
boolean F_CreditResponder(event_t *event)
{
INT32 type = event->type;
INT32 key = G_RemapGamepadEvent(event, &type);
INT32 key = event->key;
// remap virtual keys (mouse & gamepad buttons)
// remap virtual keys (mouse & joystick buttons)
switch (key)
{
case KEY_MOUSE1:
@ -1388,22 +1387,26 @@ boolean F_CreditResponder(event_t *event)
case KEY_MOUSE1 + 1:
key = KEY_BACKSPACE;
break;
case GAMEPAD_KEY(START):
case GAMEPAD_KEY(A):
case GAMEPAD_KEY(X):
case GAMEPAD_KEY(B):
case KEY_JOY1:
case KEY_JOY1 + 2:
key = KEY_ENTER;
break;
case GAMEPAD_KEY(DPAD_UP):
case KEY_JOY1 + 3:
key = 'n';
break;
case KEY_JOY1 + 1:
key = KEY_BACKSPACE;
break;
case KEY_HAT1:
key = KEY_UPARROW;
break;
case GAMEPAD_KEY(DPAD_DOWN):
case KEY_HAT1 + 1:
key = KEY_DOWNARROW;
break;
case GAMEPAD_KEY(DPAD_LEFT):
case KEY_HAT1 + 2:
key = KEY_LEFTARROW;
break;
case GAMEPAD_KEY(DPAD_RIGHT):
case KEY_HAT1 + 3:
key = KEY_RIGHTARROW;
break;
}
@ -1411,7 +1414,7 @@ boolean F_CreditResponder(event_t *event)
if (!(timesBeaten) && !(netgame || multiplayer) && !cv_debug)
return false;
if (type != ev_keydown)
if (event->type != ev_keydown)
return false;
if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_SPACE && key != KEY_BACKSPACE)
@ -1452,7 +1455,6 @@ void F_StartGameEvaluation(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
P_StopRumble(NULL);
finalecount = -1;
sparklloop = 0;
@ -1778,7 +1780,6 @@ void F_StartEnding(void)
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
P_StopRumble(NULL);
S_StopMusic(); // todo: placeholder
S_StopSounds();
@ -2224,7 +2225,6 @@ void F_StartGameEnd(void)
paused = false;
CON_ToggleOff();
S_StopSounds();
P_StopRumble(NULL);
// In case menus are still up?!!
M_ClearMenus(true);
@ -3567,7 +3567,6 @@ void F_StartContinue(void)
keypressed = false;
paused = false;
CON_ToggleOff();
P_StopRumble(NULL);
// In case menus are still up?!!
M_ClearMenus(true);
@ -3820,26 +3819,24 @@ void F_ContinueTicker(void)
boolean F_ContinueResponder(event_t *event)
{
INT32 key = event->key;
if (keypressed)
return true;
INT32 type = event->type;
INT32 key = G_RemapGamepadEvent(event, &type);
if (timetonext >= 21*TICRATE/2)
return false;
if (event->type != ev_keydown)
return false;
// remap virtual keys (mouse & gamepad buttons)
// remap virtual keys (mouse & joystick buttons)
switch (key)
{
case KEY_ENTER:
case KEY_SPACE:
case KEY_MOUSE1:
case GAMEPAD_KEY(START):
case GAMEPAD_KEY(A):
case GAMEPAD_KEY(X):
case KEY_JOY1:
case KEY_JOY1 + 2:
break;
default:
return false;
@ -3957,7 +3954,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
P_StopRumble(NULL);
F_NewCutscene(cutscenes[cutscenenum]->scene[0].text);

View file

@ -32,7 +32,7 @@
#include "z_zone.h"
#include "i_video.h"
#include "byteptr.h"
#include "i_gamepad.h"
#include "i_joy.h"
#include "r_local.h"
#include "r_skins.h"
#include "y_inter.h"
@ -1527,9 +1527,9 @@ void G_BeginRecording(void)
buf |= 0x08;
pflags |= PF_AUTOBRAKE;
}
if (cv_usegamepad[0].value)
if (cv_usejoystick.value)
buf |= 0x10;
CV_SetValue(&cv_showinputjoy, !!(cv_usegamepad[0].value));
CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
WRITEUINT8(demo_p,buf);
player->pflags = pflags;

File diff suppressed because it is too large Load diff

View file

@ -68,14 +68,10 @@ typedef enum {
#define P_ControlStyle(player) ((((player)->pflags & PF_ANALOGMODE) ? CS_LMAOGALOG : 0) | (((player)->pflags & PF_DIRECTIONCHAR) ? CS_STANDARD : 0))
extern consvar_t cv_autobrake, cv_autobrake2;
extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_jumpaxis,cv_spinaxis,cv_fireaxis,cv_firenaxis,cv_deadzone,cv_digitaldeadzone;
extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_fireaxis2,cv_firenaxis2,cv_deadzone2,cv_digitaldeadzone2;
extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
extern consvar_t cv_sideaxis[2], cv_turnaxis[2], cv_moveaxis[2], cv_lookaxis[2],
cv_jumpaxis[2], cv_spinaxis[2], cv_fireaxis[2], cv_firenaxis[2],
cv_deadzone[2], cv_digitaldeadzone[2];
extern CV_PossibleValue_t joyaxis_cons_t[];
// hi here's some new controls
extern consvar_t cv_cam_shiftfacing[2], cv_cam_turnfacing[2],
cv_cam_turnfacingability[2], cv_cam_turnfacingspindash[2], cv_cam_turnfacinginput[2],
@ -88,12 +84,10 @@ typedef enum
LOCK_INTERESTS = 1<<2,
} lockassist_e;
// Legacy axis stuff
#define JOYAXISSET 4 // 4 Sets of 2 axes
typedef enum
{
JA_NONE,
JA_NONE = 0,
JA_TURN,
JA_MOVE,
JA_LOOK,
@ -107,7 +101,8 @@ typedef enum
JA_FIRENORMAL,
} joyaxis_e;
INT16 G_JoyAxis(UINT8 which, joyaxis_e axissel);
INT32 JoyAxis(joyaxis_e axissel);
INT32 Joy2Axis(joyaxis_e axissel);
// mouseaiming (looking up/down with the mouse or keyboard)
#define KB_LOOKSPEED (1<<25)
@ -127,15 +122,6 @@ ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n);
// copy ticcmd_t to and fro network packets
ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n);
// gets the user-set gamepad device for a specific player
INT32 G_GetGamepadDeviceIndex(INT32 player);
// returns a player's gamepad index
INT16 G_GetGamepadForPlayer(player_t *player);
// called when a player's gamepad is disconnected
void G_OnGamepadDisconnect(UINT8 which);
// clip the console player aiming to the view
INT16 G_ClipAimingPitch(INT32 *aiming);
INT16 G_SoftwareClipAimingPitch(INT32 *aiming);

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file g_input.h
/// \brief handle mouse/keyboard/gamepad inputs,
/// \brief handle mouse/keyboard/joystick inputs,
/// maps inputs to game controls (forward, spin, jump...)
#ifndef __G_INPUT__
@ -17,178 +17,45 @@
#include "d_event.h"
#include "keys.h"
#include "command.h"
#include "m_fixed.h"
// number of total 'button' inputs, include keyboard keys, plus virtual
// keys (mousebuttons and joybuttons becomes keys)
#define NUMKEYS 256
// Max gamepads that can be used by every player
#define NUM_GAMEPADS 2
// Max gamepads that can be detected
#define MAX_CONNECTED_GAMEPADS 4
// Max mouse buttons
#define MOUSEBUTTONS 8
typedef enum
{
GAMEPAD_TYPE_UNKNOWN,
GAMEPAD_TYPE_XBOX360,
GAMEPAD_TYPE_XBOXONE,
GAMEPAD_TYPE_XBOX_SERIES_XS,
GAMEPAD_TYPE_XBOX_ELITE,
GAMEPAD_TYPE_PS3,
GAMEPAD_TYPE_PS4,
GAMEPAD_TYPE_PS5,
GAMEPAD_TYPE_NINTENDO_SWITCH_PRO,
GAMEPAD_TYPE_NINTENDO_SWITCH_JOY_CON_GRIP,
GAMEPAD_TYPE_NINTENDO_SWITCH_JOY_CON_LEFT,
GAMEPAD_TYPE_NINTENDO_SWITCH_JOY_CON_RIGHT,
GAMEPAD_TYPE_GOOGLE_STADIA,
GAMEPAD_TYPE_AMAZON_LUNA,
GAMEPAD_TYPE_STEAM_CONTROLLER,
GAMEPAD_TYPE_VIRTUAL
} gamepadtype_e;
boolean G_GamepadTypeIsXbox(gamepadtype_e type);
boolean G_GamepadTypeIsPlayStation(gamepadtype_e type);
boolean G_GamepadTypeIsNintendoSwitch(gamepadtype_e type);
boolean G_GamepadTypeIsJoyCon(gamepadtype_e type);
const char *G_GamepadTypeToString(gamepadtype_e type);
typedef enum
{
GAMEPAD_BUTTON_A,
GAMEPAD_BUTTON_B,
GAMEPAD_BUTTON_X,
GAMEPAD_BUTTON_Y,
GAMEPAD_BUTTON_BACK,
GAMEPAD_BUTTON_GUIDE,
GAMEPAD_BUTTON_START,
GAMEPAD_BUTTON_LEFTSTICK,
GAMEPAD_BUTTON_RIGHTSTICK,
GAMEPAD_BUTTON_LEFTSHOULDER,
GAMEPAD_BUTTON_RIGHTSHOULDER,
GAMEPAD_BUTTON_DPAD_UP,
GAMEPAD_BUTTON_DPAD_DOWN,
GAMEPAD_BUTTON_DPAD_LEFT,
GAMEPAD_BUTTON_DPAD_RIGHT,
// According to SDL, this button can be:
// the Xbox Series X|S share button
// the PS5 microphone button
// the Nintendo Switch (Pro or Joy-Con) capture button
// the Amazon Luna microphone button
GAMEPAD_BUTTON_MISC1,
// Xbox Elite paddles
GAMEPAD_BUTTON_PADDLE1,
GAMEPAD_BUTTON_PADDLE2,
GAMEPAD_BUTTON_PADDLE3,
GAMEPAD_BUTTON_PADDLE4,
// PS4/PS5 touchpad button
GAMEPAD_BUTTON_TOUCHPAD,
NUM_GAMEPAD_BUTTONS
} gamepad_button_e;
typedef enum
{
GAMEPAD_AXIS_LEFTX,
GAMEPAD_AXIS_LEFTY,
GAMEPAD_AXIS_RIGHTX,
GAMEPAD_AXIS_RIGHTY,
GAMEPAD_AXIS_TRIGGERLEFT,
GAMEPAD_AXIS_TRIGGERRIGHT,
NUM_GAMEPAD_AXES
} gamepad_axis_e;
extern const char *const gamepad_button_names[NUM_GAMEPAD_BUTTONS + 1];
extern const char *const gamepad_axis_names[NUM_GAMEPAD_AXES + 1];
// Haptic effects
typedef struct
{
fixed_t large_magnitude; // Magnitude of the large motor
fixed_t small_magnitude; // Magnitude of the small motor
tic_t duration; // The total duration of the effect, in tics
} haptic_t;
// Gamepad info for each player on the system
typedef struct
{
// Gamepad index
UINT8 num;
// Gamepad is connected and being used by a player
boolean connected;
// What kind of controller this is (Xbox 360, DualShock, Joy-Con, etc.)
gamepadtype_e type;
// Treat this gamepad's axes as if it they were buttons
boolean digital;
struct {
boolean supported; // Gamepad can rumble
boolean active; // Rumble is active
boolean paused; // Rumble is paused
haptic_t data; // Current haptic effect status
} rumble;
UINT8 buttons[NUM_GAMEPAD_BUTTONS]; // Current state of all buttons
INT16 axes[NUM_GAMEPAD_AXES]; // Current state of all axes
} gamepad_t;
void G_InitGamepads(void);
typedef enum
{
GAMEPAD_STRING_DEFAULT, // A
GAMEPAD_STRING_MENU1, // A Button
GAMEPAD_STRING_MENU2 // the A Button
} gamepad_string_e;
const char *G_GetGamepadButtonString(gamepadtype_e type, gamepad_button_e button, gamepad_string_e strtype);
const char *G_GetGamepadAxisString(gamepadtype_e type, gamepad_axis_e button, gamepad_string_e strtype, boolean inv);
extern gamepad_t gamepads[NUM_GAMEPADS];
#define JOYBUTTONS 32 // 32 buttons
#define JOYHATS 4 // 4 hats
#define JOYAXISSET 4 // 4 Sets of 2 axises
//
// mouse and gamepad buttons are handled as 'virtual' keys
// mouse and joystick buttons are handled as 'virtual' keys
//
typedef enum
{
KEY_MOUSE1 = NUMKEYS,
KEY_GAMEPAD = KEY_MOUSE1 + MOUSEBUTTONS,
KEY_AXES = KEY_GAMEPAD + NUM_GAMEPAD_BUTTONS, // Sure, why not.
KEY_INV_AXES = KEY_AXES + NUM_GAMEPAD_AXES,
KEY_JOY1 = KEY_MOUSE1 + MOUSEBUTTONS,
KEY_HAT1 = KEY_JOY1 + JOYBUTTONS,
KEY_DBLMOUSE1 = KEY_INV_AXES + NUM_GAMEPAD_AXES, // double clicks
KEY_DBLMOUSE1 =KEY_HAT1 + JOYHATS*4, // double clicks
KEY_DBLJOY1 = KEY_DBLMOUSE1 + MOUSEBUTTONS,
KEY_DBLHAT1 = KEY_DBLJOY1 + JOYBUTTONS,
KEY_2MOUSE1 = KEY_DBLMOUSE1 + MOUSEBUTTONS,
KEY_DBL2MOUSE1 = KEY_2MOUSE1 + MOUSEBUTTONS,
KEY_2MOUSE1 = KEY_DBLHAT1 + JOYHATS*4,
KEY_2JOY1 = KEY_2MOUSE1 + MOUSEBUTTONS,
KEY_2HAT1 = KEY_2JOY1 + JOYBUTTONS,
KEY_MOUSEWHEELUP = KEY_DBL2MOUSE1 + MOUSEBUTTONS,
KEY_MOUSEWHEELDOWN,
KEY_2MOUSEWHEELUP,
KEY_2MOUSEWHEELDOWN,
KEY_DBL2MOUSE1 = KEY_2HAT1 + JOYHATS*4,
KEY_DBL2JOY1 = KEY_DBL2MOUSE1 + MOUSEBUTTONS,
KEY_DBL2HAT1 = KEY_DBL2JOY1 + JOYBUTTONS,
NUMINPUTS
KEY_MOUSEWHEELUP = KEY_DBL2HAT1 + JOYHATS*4,
KEY_MOUSEWHEELDOWN = KEY_MOUSEWHEELUP + 1,
KEY_2MOUSEWHEELUP = KEY_MOUSEWHEELDOWN + 1,
KEY_2MOUSEWHEELDOWN = KEY_2MOUSEWHEELUP + 1,
NUMINPUTS = KEY_2MOUSEWHEELDOWN + 1,
} key_input_e;
#define GAMEPAD_KEY(key) (KEY_GAMEPAD + GAMEPAD_BUTTON_##key)
typedef enum
{
GC_NULL = 0, // a key/button mapped to GC_NULL has no effect
@ -274,22 +141,19 @@ typedef struct
extern mouse_t mouse;
extern mouse_t mouse2;
extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET];
// current state of the keys: true if pushed
extern UINT8 gamekeydown[NUMINPUTS];
// two key codes (or virtual key) per game control
extern INT32 gamecontrol[NUM_GAMECONTROLS][2];
extern INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
// default control storage, use 0 (gcs_custom) for memory retention
extern INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
extern INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
boolean G_PlayerInputDown(UINT8 which, gamecontrols_e gc);
boolean G_CheckDigitalPlayerInput(UINT8 which, gamecontrols_e gc);
SINT8 G_PlayerInputIsAnalog(UINT8 which, gamecontrols_e gc, UINT8 settings);
INT16 G_GetAnalogPlayerInput(UINT8 which, gamecontrols_e gc, UINT8 settings);
#define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
#define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
#define PLAYERINPUTDOWN(p, gc) ((p) == 2 ? PLAYER2INPUTDOWN(gc) : PLAYER1INPUTDOWN(gc))
#define num_gcl_tutorial_check 6
#define num_gcl_tutorial_used 8
@ -317,37 +181,13 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin];
// remaps the input event to a game control.
void G_MapEventsToControls(event_t *ev);
boolean G_RumbleSupported(UINT8 which);
boolean G_RumbleGamepad(UINT8 which, fixed_t large_magnitude, fixed_t small_magnitude, tic_t duration);
void G_StopGamepadRumble(UINT8 which);
fixed_t G_GetLargeMotorFreq(UINT8 which);
fixed_t G_GetSmallMotorFreq(UINT8 which);
boolean G_GetGamepadRumblePaused(UINT8 which);
boolean G_SetLargeMotorFreq(UINT8 which, fixed_t freq);
boolean G_SetSmallMotorFreq(UINT8 which, fixed_t freq);
void G_SetGamepadRumblePaused(UINT8 which, boolean pause);
INT16 G_GamepadAxisEventValue(UINT8 which, INT16 value);
INT16 G_GetGamepadAxisValue(UINT8 which, gamepad_axis_e axis);
fixed_t G_GetAdjustedGamepadAxis(UINT8 which, gamepad_axis_e axis, boolean applyDeadzone);
UINT16 G_GetGamepadDeadZone(UINT8 which);
UINT16 G_GetGamepadDigitalDeadZone(UINT8 which);
INT32 G_BasicDeadZoneCalculation(INT32 magnitude, const UINT16 jdeadzone);
INT32 G_RemapGamepadEvent(event_t *event, INT32 *type);
// returns the name of a key
const char *G_KeyNumToName(INT32 keynum);
INT32 G_KeyNameToNum(const char *keystr);
const char *G_GetDisplayNameForKey(INT32 keynum);
// detach any keys associated to the given game control
void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);
void G_ClearAllControlKeys(void);
void Command_Setcontrol_f(void);
void Command_Setcontrol2_f(void);
void G_DefineDefaultControls(void);

View file

@ -877,7 +877,7 @@ void HU_Ticker(void)
hu_tick++;
hu_tick &= 7; // currently only to blink chat input cursor
if (G_PlayerInputDown(0, GC_SCORES))
if (PLAYER1INPUTDOWN(GC_SCORES))
hu_showscores = !chat_on;
else
hu_showscores = false;
@ -1052,6 +1052,26 @@ boolean HU_Responder(event_t *ev)
// only KeyDown events now...
/*// Shoot, to prevent P1 chatting from ruining the game for everyone else, it's either:
// A. completely disallow opening chat entirely in online splitscreen
// or B. iterate through all controls to make sure it's bound to player 1 before eating
// You can see which one I chose.
// (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...)
// (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...)
if (ev->key >= KEY_MOUSE1)
{
INT32 i;
for (i = 0; i < NUM_GAMECONTROLS; i++)
{
if (gamecontrol[i][0] == ev->key || gamecontrol[i][1] == ev->key)
break;
}
if (i == NUM_GAMECONTROLS)
return false;
}*/ //We don't actually care about that unless we get splitscreen netgames. :V
#ifndef NONET
c = (INT32)ev->key;

View file

@ -1,58 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_gamepad.h
/// \brief Gamepads
#ifndef __I_GAMEPAD_H__
#define __I_GAMEPAD_H__
#include "g_input.h"
#include "p_haptic.h"
// So m_menu knows whether to store cv_usegamepad value or string
#define GAMEPAD_HOTPLUG
// Value range for axes
#define JOYAXISRANGE INT16_MAX
#define OLDJOYAXISRANGE 1023
// Starts all gamepads
void I_InitGamepads(void);
// Returns the number of gamepads on the system
INT32 I_NumGamepads(void);
// Changes a gamepad's device
void I_ChangeGamepad(UINT8 which);
// Toggles a gamepad's digital axis setting
void I_SetGamepadDigital(UINT8 which, boolean enable);
// Shuts down all gamepads
void I_ShutdownGamepads(void);
// Returns the name of a gamepad from its index
const char *I_GetGamepadName(INT32 joyindex);
// Gamepad rumble interface
boolean I_RumbleSupported(void);
boolean I_RumbleGamepad(UINT8 which, const haptic_t *effect);
boolean I_GetGamepadRumblePaused(UINT8 which);
boolean I_SetGamepadLargeMotorFreq(UINT8 which, fixed_t freq);
boolean I_SetGamepadSmallMotorFreq(UINT8 which, fixed_t freq);
void I_SetGamepadRumblePaused(UINT8 which, boolean pause);
boolean I_GetGamepadRumbleSupported(UINT8 which);
void I_StopGamepadRumble(UINT8 which);
#endif // __I_GAMEPAD_H__

58
src/i_joy.h Normal file
View file

@ -0,0 +1,58 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// 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
#ifndef __I_JOY_H__
#define __I_JOY_H__
#include "g_input.h"
/*!
\brief -JOYAXISRANGE to +JOYAXISRANGE for each axis
(1024-1) so we can do a right shift instead of division
(doesnt matter anyway, just give enough precision)
a gamepad will return -1, 0, or 1 in the event data
an analog type joystick will return a value
from -JOYAXISRANGE to +JOYAXISRANGE for each axis
*/
#define JOYAXISRANGE 1023
// detect a bug if we increase JOYBUTTONS above DIJOYSTATE's number of buttons
#if (JOYBUTTONS > 64)
"JOYBUTTONS is greater than INT64 bits can hold"
#endif
/** \brief The struct JoyType_s
share some joystick information (maybe 2 for splitscreen), to the game input code,
actually, we need to know if it is a gamepad or analog controls
*/
struct JoyType_s
{
/*! 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;
};
typedef struct JoyType_s JoyType_t;
/** \brief Joystick info
for palyer 1 and 2's joystick/gamepad
*/
extern JoyType_t Joystick, Joystick2;
#endif // __I_JOY_H__

View file

@ -101,6 +101,90 @@ ticcmd_t *I_BaseTiccmd2(void);
*/
void I_Quit(void) FUNCNORETURN;
typedef enum
{
EvilForce = -1,
//Constant
ConstantForce = 0,
//Ramp
RampForce,
//Periodics
SquareForce,
SineForce,
TriangleForce,
SawtoothUpForce,
SawtoothDownForce,
//MAX
NumberofForces,
} FFType;
typedef struct JoyFF_s
{
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.
} JoyFF_t;
/** \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 to set up the first joystick scale
*/
void I_JoyScale(void);
/** \brief to set up the second joystick scale
*/
void I_JoyScale2(void);
// Called by D_SRB2Main.
/** \brief to startup the first joystick
*/
void I_InitJoystick(void);
/** \brief to startup the second joystick
*/
void I_InitJoystick2(void);
/** \brief return the number of joystick on the system
*/
INT32 I_NumJoys(void);
/** \brief The *I_GetJoyName function
\param joyindex which joystick
\return joystick name
*/
const char *I_GetJoyName(INT32 joyindex);
#ifndef NOMUMBLE
#include "p_mobj.h" // mobj_t
#include "s_sound.h" // listener_t
@ -209,7 +293,15 @@ const CPUInfoFlags *I_CPUInfo(void);
*/
const char *I_LocateWad(void);
/** \brief Mice events
/** \brief First Joystick's events
*/
void I_GetJoystickEvents(void);
/** \brief Second Joystick's events
*/
void I_GetJoystick2Events(void);
/** \brief Mouses events
*/
void I_GetMouseEvents(void);

View file

@ -15,7 +15,6 @@
#include "g_game.h"
#include "hu_stuff.h"
#include "i_system.h"
#include "i_gamepad.h"
#include "lua_script.h"
#include "lua_libs.h"
@ -31,7 +30,7 @@ static int lib_gameControlDown(lua_State *L)
int i = luaL_checkinteger(L, 1);
if (i < 0 || i >= NUM_GAMECONTROLS)
return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
lua_pushinteger(L, G_PlayerInputDown(0, i));
lua_pushinteger(L, PLAYER1INPUTDOWN(i));
return 1;
}
@ -40,7 +39,7 @@ static int lib_gameControl2Down(lua_State *L)
int i = luaL_checkinteger(L, 1);
if (i < 0 || i >= NUM_GAMECONTROLS)
return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
lua_pushinteger(L, G_PlayerInputDown(1, i));
lua_pushinteger(L, PLAYER2INPUTDOWN(i));
return 1;
}
@ -67,14 +66,14 @@ static int lib_gameControl2ToKeyNum(lua_State *L)
static int lib_joyAxis(lua_State *L)
{
int i = luaL_checkinteger(L, 1);
lua_pushinteger(L, G_JoyAxis(0, i) / 32);
lua_pushinteger(L, JoyAxis(i));
return 1;
}
static int lib_joy2Axis(lua_State *L)
{
int i = luaL_checkinteger(L, 1);
lua_pushinteger(L, G_JoyAxis(1, i) / 32);
lua_pushinteger(L, Joy2Axis(i));
return 1;
}

View file

@ -199,41 +199,39 @@ static UINT8 cht_CheckCheat(cheatseq_t *cht, char key)
boolean cht_Responder(event_t *ev)
{
UINT8 ch = 0;
UINT8 ret = 0, ch = 0;
if (ev->type != ev_keydown)
return false;
if (ev->type == ev_gamepad_down)
if (ev->key > 0xFF)
{
// map some fake (joy) inputs into keys
// map joy inputs into keys
switch (ev->key)
{
case GAMEPAD_BUTTON_DPAD_UP:
case KEY_JOY1:
case KEY_JOY1 + 2:
ch = KEY_ENTER;
break;
case KEY_HAT1:
ch = KEY_UPARROW;
break;
case GAMEPAD_BUTTON_DPAD_DOWN:
case KEY_HAT1 + 1:
ch = KEY_DOWNARROW;
break;
case GAMEPAD_BUTTON_DPAD_LEFT:
case KEY_HAT1 + 2:
ch = KEY_LEFTARROW;
break;
case GAMEPAD_BUTTON_DPAD_RIGHT:
case KEY_HAT1 + 3:
ch = KEY_RIGHTARROW;
break;
case GAMEPAD_BUTTON_START:
ch = KEY_ENTER;
break;
default:
// no mapping
return false;
}
}
else if (ev->type == ev_keydown)
{
if (ev->key > 0xFF)
return false;
else
ch = (UINT8)ev->key;
}
UINT8 ret = 0;
ret += cht_CheckCheat(&cheat_ultimate, (char)ch);
ret += cht_CheckCheat(&cheat_ultimate_joy, (char)ch);

File diff suppressed because it is too large Load diff

View file

@ -223,9 +223,8 @@ typedef enum
{
MM_NOTHING = 0, // is just displayed until the user do someting
MM_YESNO, // routine is called with only 'y' or 'n' in param
MM_KEYHANDLER, // the same of above but without 'y' or 'n' restriction
MM_EVENTHANDLER // the same of above but routine is void routine(event_t *)
// (ex: set control)
MM_EVENTHANDLER // the same of above but without 'y' or 'n' restriction
// and routine is void routine(event_t *) (ex: set control)
} menumessagetype_t;
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
@ -362,11 +361,9 @@ extern menu_t *currentMenu;
extern menu_t MainDef;
extern menu_t SP_LoadDef;
// Call when a gamepad is connected or disconnected
void M_UpdateGamepadMenu(void);
// Returns true if the player is on the gamepad selection menu
boolean M_OnGamepadMenu(void);
// Call upon joystick hotplug
void M_SetupJoystickMenu(INT32 choice);
extern menu_t OP_JoystickSetDef;
// Stuff for customizing the player select screen
typedef struct
@ -541,19 +538,6 @@ void M_FreePlayerSetupColors(void);
NULL\
}
#define GAMEPADMENUSTYLE(id, header, source, prev, x, y)\
{\
id,\
header,\
sizeof(source)/sizeof(menuitem_t),\
prev,\
source,\
M_DrawGamepadMenu,\
x, y,\
0,\
NULL\
}
#define MAPPLATTERMENUSTYLE(id, header, source)\
{\
id,\
@ -574,7 +558,7 @@ void M_FreePlayerSetupColors(void);
sizeof (source)/sizeof (menuitem_t),\
prev,\
source,\
M_DrawControlConfigMenu,\
M_DrawControl,\
24, 40,\
0,\
NULL\

View file

@ -1,115 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2021-2022 by Jaime "Lactozilla" Passos.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file p_haptic.c
/// \brief Haptic feedback
#include "p_haptic.h"
#include "g_game.h"
#include "d_netcmd.h"
#include "i_gamepad.h"
#include "doomstat.h"
// Helper function: Returns the gamepad index for a player if it's enabled
static INT16 GetGamepadIndex(player_t *player)
{
INT16 index = G_GetGamepadForPlayer(player);
if (index >= 0 && cv_usegamepad[index].value)
return index;
return -1;
}
// Rumbles a player's gamepad, or all gamepads
boolean P_DoRumble(player_t *player, fixed_t large_magnitude, fixed_t small_magnitude, tic_t duration)
{
if (!I_RumbleSupported())
return false;
// Rumble every gamepad
if (player == NULL)
{
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
if (cv_gamepad_rumble[i].value)
G_RumbleGamepad(i, large_magnitude, small_magnitude, duration);
}
return true;
}
INT16 which = GetGamepadIndex(player);
if (which < 0 || !cv_gamepad_rumble[which].value)
return false;
return G_RumbleGamepad((UINT8)which, large_magnitude, small_magnitude, duration);
}
// Pauses or unpauses gamepad rumble for a player (or all of them)
// Rumble is paused or unpaused regardless if it's enabled or not
static void SetRumblePaused(player_t *player, boolean pause)
{
INT16 which = GetGamepadIndex(player);
if (which >= 0)
G_SetGamepadRumblePaused((UINT8)which, pause);
else if (player == NULL)
{
// Pause or unpause every gamepad
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
G_SetGamepadRumblePaused(i, pause);
}
}
void P_PauseRumble(player_t *player)
{
SetRumblePaused(player, true);
}
void P_UnpauseRumble(player_t *player)
{
SetRumblePaused(player, false);
}
boolean P_IsRumbleEnabled(player_t *player)
{
INT16 which = GetGamepadIndex(player);
if (which < 0 || !cv_gamepad_rumble[which].value)
return false;
return G_RumbleSupported((UINT8)which);
}
boolean P_IsRumblePaused(player_t *player)
{
INT16 which = GetGamepadIndex(player);
if (which < 0 || !cv_gamepad_rumble[which].value)
return false;
return G_GetGamepadRumblePaused((UINT8)which);
}
// Stops gamepad rumble for a player (or all of them)
void P_StopRumble(player_t *player)
{
if (!I_RumbleSupported())
return;
if (player)
{
INT16 which = GetGamepadIndex(player);
if (which >= 0)
G_StopGamepadRumble((UINT8)which);
return;
}
// Stop every gamepad instead
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
G_StopGamepadRumble(i);
}

View file

@ -1,27 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2021-2022 by Jaime "Lactozilla" Passos.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file p_haptic.h
/// \brief Haptic feedback
#ifndef __P_HAPTIC__
#define __P_HAPTIC__
#include "doomdef.h"
#include "p_local.h"
boolean P_DoRumble(player_t *player, fixed_t large_magnitude, fixed_t small_magnitude, tic_t duration);
void P_PauseRumble(player_t *player);
void P_UnpauseRumble(player_t *player);
boolean P_IsRumbleEnabled(player_t *player);
boolean P_IsRumblePaused(player_t *player);
void P_StopRumble(player_t *player);
#define P_DoRumbleCombined(player, magnitude, dur) P_DoRumble(player, magnitude, magnitude, dur);
#endif // __P_HAPTIC__

View file

@ -13,7 +13,6 @@
#include "doomdef.h"
#include "i_system.h"
#include "i_gamepad.h"
#include "am_map.h"
#include "g_game.h"
#include "m_random.h"
@ -25,7 +24,6 @@
#include "lua_hook.h"
#include "m_cond.h" // unlockables, emblems, etc
#include "p_setup.h"
#include "p_haptic.h"
#include "m_cheat.h" // objectplace
#include "m_misc.h"
#include "v_video.h" // video flags for CEchos
@ -35,6 +33,54 @@
#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[secondarydisplayplayer])
I_Tactile2(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[secondarydisplayplayer])
I_Tactile2(ConstantForce, &RampQuake);
}
//
// GET STUFF
//
@ -3011,8 +3057,6 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
player_t *player = target->player;
(void)damage; //unused parm
P_DoRumbleCombined(player, FRACUNIT, TICRATE / 6);
// If flashing or invulnerable, ignore the tag,
if (player->powers[pw_flashing] || player->powers[pw_invulnerability])
return false;
@ -3116,8 +3160,6 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
{
player_t *player = target->player;
(void)damage;
if (!(damagetype & DMG_CANHURTSELF))
{
// You can't kill yourself, idiot...
@ -3180,8 +3222,6 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
{
(void)damage;
player->pflags &= ~PF_SLIDING;
player->powers[pw_carry] = CR_NONE;
@ -3202,7 +3242,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
// Get rid of emeralds
player->powers[pw_emeralds] = 0;
P_DoRumbleCombined(player, FRACUNIT, TICRATE / 3);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
P_ResetPlayer(player);
@ -3242,9 +3282,7 @@ static void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, I
fixed_t fallbackspeed;
angle_t ang;
(void)damage;
P_DoRumbleCombined(player, FRACUNIT, TICRATE / 6);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (player->mo->eflags & MFE_VERTICALFLIP)
player->mo->z--;
@ -3325,14 +3363,12 @@ void P_RemoveShield(player_t *player)
static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{
(void)damage;
// Must do pain first to set flashing -- P_RemoveShield can cause damage
P_DoPlayerPain(player, source, inflictor);
P_RemoveShield(player);
P_DoRumbleCombined(player, FRACUNIT, TICRATE / 6);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth);
@ -3361,7 +3397,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
{
P_DoPlayerPain(player, source, inflictor);
P_DoRumbleCombined(player, FRACUNIT, TICRATE / 6);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth);
@ -3692,6 +3728,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
damage = 1;
P_KillPlayer(player, source, damage);
}
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
}
// Killing dead. Just for kicks.

View file

@ -453,6 +453,18 @@ extern mobj_t **blocklinks; // for thing chains
//
// P_INTER
//
typedef struct BasicFF_s
{
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.
} BasicFF_t;
/* Damage/death types, for P_DamageMobj and related */
//// Damage types
//#define DMG_NORMAL 0 (unneeded?)
@ -473,6 +485,9 @@ extern mobj_t **blocklinks; // for thing chains
#define DMG_CANHURTSELF 0x40 // Flag - can hurt self/team indirectly, such as through mines
#define DMG_DEATHMASK DMG_INSTAKILL // if bit 7 is set, this is a death type instead of a damage type
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_RemoveShield(player_t *player);
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);

View file

@ -5331,9 +5331,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
// disabled because it seemed to disorient people and Z-targeting exists now
/*if (!demoplayback)
{
if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(G_PlayerInputDown(0, GC_TURNLEFT) || G_PlayerInputDown(0, GC_TURNRIGHT)))
if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(GC_TURNLEFT) || PLAYER1INPUTDOWN(GC_TURNRIGHT)))
P_SetPlayerAngle(player, player->mo->angle);;
else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(G_PlayerInputDown(1, GC_TURNLEFT) || G_PlayerInputDown(1, GC_TURNRIGHT)))
else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(GC_TURNLEFT) || PLAYER2INPUTDOWN(GC_TURNRIGHT)))
P_SetPlayerAngle(player, player->mo->angle);
}*/
}
@ -7342,7 +7342,7 @@ static void P_NiGHTSMovement(player_t *player)
else if (cmd->forwardmove < 0)
newangle = 270;
}
else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axes.
else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axises.
newangle = (INT16)FixedInt(AngleFixed(R_PointToAngle2(0,0, cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT)));
newangle -= player->viewrollangle / ANG1;

View file

@ -2,7 +2,6 @@ i_net.c
i_system.c
i_main.c
i_video.c
i_gamepad.c
dosstr.c
endtxt.c
hwsym_sdl.c

View file

@ -1,914 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_gamepad.c
/// \brief Gamepads
#ifdef HAVE_SDL
#include "../i_gamepad.h"
#include "../i_system.h"
#include "../doomdef.h"
#include "../d_main.h"
#include "../d_netcmd.h"
#include "../g_game.h"
#include "../m_argv.h"
#include "../m_menu.h"
#include "../z_zone.h"
#include "SDL.h"
#include "SDL_joystick.h"
#include "sdlmain.h"
static void Controller_ChangeDevice(UINT8 num);
static void Controller_Close(UINT8 num);
static void Controller_StopRumble(UINT8 num);
static ControllerInfo controllers[NUM_GAMEPADS];
static boolean rumble_supported = false;
static boolean rumble_paused = false;
// This attempts to initialize the gamepad subsystems
static boolean InitGamepadSubsystems(void)
{
if (M_CheckParm("-noxinput"))
SDL_SetHintWithPriority(SDL_HINT_XINPUT_ENABLED, "0", SDL_HINT_OVERRIDE);
if (M_CheckParm("-nohidapi"))
SDL_SetHintWithPriority(SDL_HINT_JOYSTICK_HIDAPI, "0", SDL_HINT_OVERRIDE);
if (SDL_WasInit(GAMEPAD_INIT_FLAGS) == 0)
{
if (SDL_InitSubSystem(GAMEPAD_INIT_FLAGS) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize game controller subsystems: %s\n"), SDL_GetError());
return false;
}
}
return true;
}
void I_InitGamepads(void)
{
if (M_CheckParm("-nojoy"))
return;
CONS_Printf("I_InitGamepads()...\n");
if (!InitGamepadSubsystems())
return;
rumble_supported = !M_CheckParm("-norumble");
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
controllers[i].info = &gamepads[i];
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
Controller_ChangeDevice(i);
}
INT32 I_NumGamepads(void)
{
if (SDL_WasInit(GAMEPAD_INIT_FLAGS) == GAMEPAD_INIT_FLAGS)
return SDL_NumJoysticks();
else
return 0;
}
// From the SDL source code
#define USB_VENDOR_MICROSOFT 0x045e
#define USB_VENDOR_PDP 0x0e6f
#define USB_VENDOR_POWERA_ALT 0x20d6
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 0x02e3
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 0x0b00
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH 0x0b05
#define USB_PRODUCT_XBOX_SERIES_X 0x0b12
#define USB_PRODUCT_XBOX_SERIES_X_BLE 0x0b13
#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6
#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9
#define USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW 0x02da
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 0x4001
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002
static boolean IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 ||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
return true;
}
}
return false;
}
static boolean IsJoystickXboxSeriesXS(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_SERIES_X ||
product_id == USB_PRODUCT_XBOX_SERIES_X_BLE) {
return true;
}
}
else if (vendor_id == USB_VENDOR_PDP) {
if (product_id == USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT ||
product_id == USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE ||
product_id == USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW) {
return true;
}
}
else if (vendor_id == USB_VENDOR_POWERA_ALT) {
if ((product_id >= 0x2001 && product_id <= 0x201a) ||
product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 ||
product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA) {
return true;
}
}
return false;
}
// Opens a controller device
static boolean Controller_OpenDevice(UINT8 which, INT32 devindex)
{
if (SDL_WasInit(GAMEPAD_INIT_FLAGS) == 0)
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Game controller subsystems not started\n"));
return false;
}
if (devindex <= 0)
return false;
if (SDL_NumJoysticks() == 0)
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Found no controllers on this system\n"));
return false;
}
devindex--;
if (!SDL_IsGameController(devindex))
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Device index %d isn't a game controller\n"), devindex);
return false;
}
ControllerInfo *controller = &controllers[which];
SDL_GameController *newdev = SDL_GameControllerOpen(devindex);
// Handle the edge case where the device <-> controller 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 (controller->dev)
{
if (controller->dev == newdev // same device, nothing to do
|| (newdev == NULL && SDL_GameControllerGetAttached(controller->dev))) // we failed, but already have a working device
return true;
// Else, we're changing devices, so close the controller
CONS_Debug(DBG_GAMELOGIC, M_GetText("Controller %d device is changing; closing controller...\n"), which);
Controller_Close(which);
}
if (newdev == NULL)
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Controller %d: Couldn't open device - %s\n"), which, SDL_GetError());
controller->started = false;
}
else
{
controller->dev = newdev;
controller->joydev = SDL_GameControllerGetJoystick(controller->dev);
controller->started = true;
CONS_Debug(DBG_GAMELOGIC, M_GetText("Controller %d: %s\n"), which, SDL_GameControllerName(controller->dev));
#define GAMEPAD_TYPE_CASE(ctrl) \
case SDL_CONTROLLER_TYPE_##ctrl: \
controller->info->type = GAMEPAD_TYPE_##ctrl; \
break
switch (SDL_GameControllerGetType(newdev))
{
GAMEPAD_TYPE_CASE(UNKNOWN);
GAMEPAD_TYPE_CASE(XBOX360);
GAMEPAD_TYPE_CASE(XBOXONE);
GAMEPAD_TYPE_CASE(PS3);
GAMEPAD_TYPE_CASE(PS4);
GAMEPAD_TYPE_CASE(PS5);
GAMEPAD_TYPE_CASE(NINTENDO_SWITCH_PRO);
GAMEPAD_TYPE_CASE(GOOGLE_STADIA);
GAMEPAD_TYPE_CASE(AMAZON_LUNA);
GAMEPAD_TYPE_CASE(VIRTUAL);
default: break;
}
#undef GAMEPAD_BUTTON_CASE
// Check the device vendor and product to find out what controller this actually is
Uint16 vendor = SDL_JoystickGetDeviceVendor(devindex);
Uint16 product = SDL_JoystickGetDeviceProduct(devindex);
if (IsJoystickXboxSeriesXS(vendor, product))
controller->info->type = GAMEPAD_TYPE_XBOX_SERIES_XS;
else if (IsJoystickXboxOneElite(vendor, product))
controller->info->type = GAMEPAD_TYPE_XBOX_ELITE;
CONS_Debug(DBG_GAMELOGIC, M_GetText(" Type: %s\n"), G_GamepadTypeToString(controller->info->type));
// Change the ring LEDs on Xbox 360 controllers
// TODO: Doesn't seem to work?
SDL_GameControllerSetPlayerIndex(controller->dev, which);
// Check if rumble is supported
if (SDL_GameControllerHasRumble(controller->dev) == SDL_TRUE)
{
controller->info->rumble.supported = true;
CONS_Debug(DBG_GAMELOGIC, M_GetText(" Rumble supported: Yes\n"));
}
else
{
controller->info->rumble.supported = false;
CONS_Debug(DBG_GAMELOGIC, M_GetText(" Rumble supported: No\n"));;
}
controller->info->connected = true;
}
return controller->started;
}
// Initializes a controller
static INT32 Controller_Init(SDL_GameController **newcontroller, UINT8 which, INT32 *index)
{
ControllerInfo *info = &controllers[which];
SDL_GameController *controller = NULL;
INT32 device = (*index);
if (device && SDL_IsGameController(device - 1))
controller = SDL_GameControllerOpen(device - 1);
if (newcontroller)
(*newcontroller) = controller;
if (controller && info->dev == controller) // don't override an active device
(*index) = I_GetControllerIndex(info->dev) + 1;
else if (controller && Controller_OpenDevice(which, device))
{
// SDL's device indexes are unstable, so cv_usegamepad may not match
// the actual device index. So let's cheat a bit and find the device's current index.
info->lastindex = I_GetControllerIndex(info->dev) + 1;
return 1;
}
else
{
(*index) = 0;
return 0;
}
return -1;
}
// Changes a controller's device
static void Controller_ChangeDevice(UINT8 num)
{
SDL_GameController *newjoy = NULL;
if (!Controller_Init(&newjoy, num, &cv_usegamepad[num].value) && controllers[num].lastindex)
Controller_Close(num);
I_CloseInactiveController(newjoy);
}
static boolean Controller_IsAnyUsingDevice(SDL_GameController *dev)
{
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
if (controllers[i].dev == dev)
return true;
}
return false;
}
static boolean Controller_IsAnyOtherUsingDevice(SDL_GameController *dev, UINT8 thisjoy)
{
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
if (i == thisjoy)
continue;
else if (controllers[i].dev == dev)
return true;
}
return false;
}
void I_ControllerDeviceAdded(INT32 which)
{
if (!SDL_IsGameController(which))
return;
SDL_GameController *newjoy = SDL_GameControllerOpen(which);
CONS_Debug(DBG_GAMELOGIC, "Gamepad device index %d added\n", which + 1);
// Because SDL's device index is unstable, we're going to cheat here a bit:
// For the first controller setting that is NOT active:
// 1. Set cv_usegamepadX.value to the new device index (this does not change what is written to config.cfg)
// 2. Set OTHERS' cv_usegamepadX.value to THEIR new device index, because it likely changed
// * If device doesn't exist, switch cv_usegamepad back to default value (.string)
// * BUT: If that default index is being occupied, use ANOTHER cv_usegamepad's default value!
for (UINT8 this = 0; this < NUM_GAMEPADS && newjoy; this++)
{
if ((!controllers[this].dev || !SDL_GameControllerGetAttached(controllers[this].dev))
&& !Controller_IsAnyOtherUsingDevice(newjoy, this)) // don't override a currently active device
{
cv_usegamepad[this].value = which + 1;
// Go through every other device
for (UINT8 other = 0; other < NUM_GAMEPADS; other++)
{
if (other == this)
{
// Don't change this controller's index
continue;
}
else if (controllers[other].dev)
{
// Update this controller's index if the device is open
cv_usegamepad[other].value = I_GetControllerIndex(controllers[other].dev) + 1;
}
else if (atoi(cv_usegamepad[other].string) != controllers[this].lastindex
&& atoi(cv_usegamepad[other].string) != cv_usegamepad[this].value)
{
// If the user-set index for the other controller doesn't
// match this controller's current or former internal index,
// then use the other controller's internal index
cv_usegamepad[other].value = atoi(cv_usegamepad[other].string);
}
else if (atoi(cv_usegamepad[this].string) != controllers[this].lastindex
&& atoi(cv_usegamepad[this].string) != cv_usegamepad[this].value)
{
// If the user-set index for this controller doesn't match
// its current or former internal index, then use this
// controller's internal index
cv_usegamepad[other].value = atoi(cv_usegamepad[this].string);
}
else
{
// Try again
cv_usegamepad[other].value = 0;
continue;
}
break;
}
break;
}
}
// Was cv_usegamepad disabled in settings?
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
if (!strcmp(cv_usegamepad[i].string, "0") || !cv_usegamepad[i].value)
cv_usegamepad[i].value = 0;
else if (atoi(cv_usegamepad[i].string) <= I_NumGamepads() // don't mess if we intentionally set higher than NumJoys
&& cv_usegamepad[i].value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usegamepad[i], cv_usegamepad[i].value);
}
// Update all gamepads' init states
// This is a little wasteful since cv_usegamepad 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 (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
Controller_ChangeDevice(i);
CONS_Debug(DBG_GAMELOGIC, "Controller %d device index: %d\n", i, controllers[i].lastindex);
}
if (M_OnGamepadMenu())
M_UpdateGamepadMenu();
I_CloseInactiveController(newjoy);
}
void I_ControllerDeviceRemoved(void)
{
for (UINT8 this = 0; this < NUM_GAMEPADS; this++)
{
if (controllers[this].dev && !SDL_GameControllerGetAttached(controllers[this].dev))
{
CONS_Debug(DBG_GAMELOGIC, "Controller %d removed, device index: %d\n", this, controllers[this].lastindex);
G_OnGamepadDisconnect(this);
Controller_Close(this);
}
// Update the device indexes, because they likely changed
// * If device doesn't exist, switch cv_usegamepad back to default value (.string)
// * BUT: If that default index is being occupied, use ANOTHER cv_usegamepad's default value!
if (controllers[this].dev)
cv_usegamepad[this].value = controllers[this].lastindex = I_GetControllerIndex(controllers[this].dev) + 1;
else
{
for (UINT8 other = 0; other < NUM_GAMEPADS; other++)
{
if (other == this)
continue;
if (atoi(cv_usegamepad[this].string) != controllers[other].lastindex)
{
// Update this internal index if this user-set index
// doesn't match the other's former internal index
cv_usegamepad[this].value = atoi(cv_usegamepad[this].string);
}
else if (atoi(cv_usegamepad[other].string) != controllers[other].lastindex)
{
// Otherwise, set this internal index to the other's
// user-set index, if the other user-set index is not the
// same as the other's former internal index
cv_usegamepad[this].value = atoi(cv_usegamepad[other].string);
}
else
{
// Try again
cv_usegamepad[this].value = 0;
continue;
}
break;
}
}
// Was cv_usegamepad disabled in settings?
if (!strcmp(cv_usegamepad[this].string, "0"))
cv_usegamepad[this].value = 0;
else if (atoi(cv_usegamepad[this].string) <= I_NumGamepads() // don't mess if we intentionally set higher than NumJoys
&& cv_usegamepad[this].value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usegamepad[this], cv_usegamepad[this].value);
CONS_Debug(DBG_GAMELOGIC, "Controller %d device index: %d\n", this, controllers[this].lastindex);
}
if (M_OnGamepadMenu())
M_UpdateGamepadMenu();
}
// Close the controller device if there isn't any controller using it
void I_CloseInactiveController(SDL_GameController *dev)
{
if (!Controller_IsAnyUsingDevice(dev))
SDL_GameControllerClose(dev);
}
// Cheat to get the device index for a game controller handle
INT32 I_GetControllerIndex(SDL_GameController *dev)
{
INT32 i, count = SDL_NumJoysticks();
for (i = 0; dev && i < count; i++)
{
SDL_GameController *test = SDL_GameControllerOpen(i);
if (test && test == dev)
return i;
else
I_CloseInactiveController(test);
}
return -1;
}
// Changes a gamepad's device
void I_ChangeGamepad(UINT8 which)
{
if (which >= NUM_GAMEPADS)
return;
if (controllers[which].started)
Controller_StopRumble(which);
Controller_ChangeDevice(which);
}
// Returns the name of a controller from its index
const char *I_GetGamepadName(INT32 joyindex)
{
static char joyname[256];
joyname[0] = '\0';
if (SDL_WasInit(GAMEPAD_INIT_FLAGS) == GAMEPAD_INIT_FLAGS)
{
const char *tempname = SDL_GameControllerNameForIndex(joyindex - 1);
if (tempname)
strlcpy(joyname, tempname, sizeof joyname);
}
return joyname;
}
// Toggles a gamepad's digital axis setting
void I_SetGamepadDigital(UINT8 which, boolean enable)
{
if (which >= NUM_GAMEPADS)
return;
gamepads[which].digital = enable;
}
static gamepad_t *Controller_GetFromID(SDL_JoystickID which, UINT8 *found)
{
// Determine the joystick IDs for each current open controller
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
if (which == SDL_JoystickInstanceID(controllers[i].joydev))
{
(*found) = i;
return &gamepads[i];
}
}
(*found) = UINT8_MAX;
return NULL;
}
void I_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type)
{
event_t event;
gamepad_t *gamepad = Controller_GetFromID(evt.which, &event.which);
if (gamepad == NULL)
return;
if (type == SDL_CONTROLLERBUTTONUP)
event.type = ev_gamepad_up;
else if (type == SDL_CONTROLLERBUTTONDOWN)
event.type = ev_gamepad_down;
else
return;
#define GAMEPAD_BUTTON_CASE(btn) \
case SDL_CONTROLLER_BUTTON_##btn: \
event.key = GAMEPAD_BUTTON_##btn; \
break
switch (evt.button)
{
GAMEPAD_BUTTON_CASE(A);
GAMEPAD_BUTTON_CASE(B);
GAMEPAD_BUTTON_CASE(X);
GAMEPAD_BUTTON_CASE(Y);
GAMEPAD_BUTTON_CASE(BACK);
GAMEPAD_BUTTON_CASE(GUIDE);
GAMEPAD_BUTTON_CASE(START);
GAMEPAD_BUTTON_CASE(LEFTSTICK);
GAMEPAD_BUTTON_CASE(RIGHTSTICK);
GAMEPAD_BUTTON_CASE(LEFTSHOULDER);
GAMEPAD_BUTTON_CASE(RIGHTSHOULDER);
GAMEPAD_BUTTON_CASE(DPAD_UP);
GAMEPAD_BUTTON_CASE(DPAD_DOWN);
GAMEPAD_BUTTON_CASE(DPAD_LEFT);
GAMEPAD_BUTTON_CASE(DPAD_RIGHT);
GAMEPAD_BUTTON_CASE(MISC1);
GAMEPAD_BUTTON_CASE(PADDLE1);
GAMEPAD_BUTTON_CASE(PADDLE2);
GAMEPAD_BUTTON_CASE(PADDLE3);
GAMEPAD_BUTTON_CASE(PADDLE4);
GAMEPAD_BUTTON_CASE(TOUCHPAD);
default: return;
}
#undef GAMEPAD_BUTTON_CASE
D_PostEvent(&event);
}
void I_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt)
{
event_t event;
gamepad_t *gamepad = Controller_GetFromID(evt.which, &event.which);
if (gamepad == NULL)
return;
#define GAMEPAD_AXIS_CASE(btn) \
case SDL_CONTROLLER_AXIS_##btn: \
event.key = GAMEPAD_AXIS_##btn; \
break
switch (evt.axis)
{
GAMEPAD_AXIS_CASE(LEFTX);
GAMEPAD_AXIS_CASE(LEFTY);
GAMEPAD_AXIS_CASE(RIGHTX);
GAMEPAD_AXIS_CASE(RIGHTY);
GAMEPAD_AXIS_CASE(TRIGGERLEFT);
GAMEPAD_AXIS_CASE(TRIGGERRIGHT);
default: return;
}
#undef GAMEPAD_AXIS_CASE
event.type = ev_gamepad_axis;
event.x = evt.value;
D_PostEvent(&event);
}
static void Controller_StopRumble(UINT8 num)
{
ControllerInfo *controller = &controllers[num];
controller->rumble.large_magnitude = 0;
controller->rumble.small_magnitude = 0;
controller->rumble.time_left = 0;
controller->rumble.expiration = 0;
gamepad_t *gamepad = controller->info;
gamepad->rumble.active = false;
gamepad->rumble.paused = false;
gamepad->rumble.data.large_magnitude = 0;
gamepad->rumble.data.small_magnitude = 0;
gamepad->rumble.data.duration = 0;
if (gamepad->rumble.supported)
SDL_GameControllerRumble(controller->dev, 0, 0, 0);
}
static void Controller_Close(UINT8 num)
{
ControllerInfo *controller = &controllers[num];
// Close the game controller device
if (controller->dev)
{
Controller_StopRumble(num);
SDL_GameControllerClose(controller->dev);
}
controller->dev = NULL;
controller->joydev = NULL;
controller->lastindex = -1;
controller->started = false;
// Reset gamepad info
gamepad_t *gamepad = controller->info;
if (gamepad)
{
gamepad->type = GAMEPAD_TYPE_UNKNOWN;
gamepad->connected = false;
gamepad->digital = false;
gamepad->rumble.supported = false;
for (UINT8 i = 0; i < NUM_GAMEPAD_BUTTONS; i++)
gamepad->buttons[i] = 0;
for (UINT8 i = 0; i < NUM_GAMEPAD_AXES; i++)
gamepad->axes[i] = 0;
}
}
void I_ShutdownGamepads(void)
{
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
Controller_Close(i);
}
boolean I_RumbleSupported(void)
{
return rumble_supported;
}
static boolean Controller_Rumble(ControllerInfo *c)
{
if (SDL_GameControllerRumble(c->dev, c->rumble.large_magnitude, c->rumble.small_magnitude, 0) == -1)
return false;
return true;
}
void I_ToggleControllerRumble(boolean unpause)
{
if (!I_RumbleSupported() || rumble_paused == !unpause)
return;
rumble_paused = !unpause;
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
ControllerInfo *controller = &controllers[i];
if (!controller->started || !controller->info->rumble.supported)
continue;
if (rumble_paused)
SDL_GameControllerRumble(controller->dev, 0, 0, 0);
else if (!controller->info->rumble.paused)
{
if (!Controller_Rumble(controller))
controller->rumble.expiration = controller->rumble.time_left = 0;
}
}
}
void I_UpdateControllers(void)
{
if (SDL_WasInit(GAMEPAD_INIT_FLAGS) != GAMEPAD_INIT_FLAGS)
return;
for (UINT8 i = 0; i < NUM_GAMEPADS; i++)
{
ControllerInfo *controller = &controllers[i];
if (!controller->started || !controller->info->rumble.supported || controller->info->rumble.paused)
continue;
if (controller->rumble.expiration &&
SDL_TICKS_PASSED(SDL_GetTicks(), controller->rumble.expiration))
{
// Enough time has passed, so stop the effect
Controller_StopRumble(i);
}
}
SDL_JoystickUpdate();
}
// Converts duration in tics to milliseconds
#define TICS_TO_MS(tics) ((INT32)(tics * (1000.0f/TICRATE)))
boolean I_RumbleGamepad(UINT8 which, const haptic_t *effect)
{
if (!I_RumbleSupported() || which >= NUM_GAMEPADS)
return false;
ControllerInfo *controller = &controllers[which];
if (!controller->started || !controller->info->rumble.supported)
return false;
UINT16 duration = min(TICS_TO_MS(effect->duration), UINT16_MAX);
UINT16 large_magnitude = max(0, min(effect->large_magnitude, UINT16_MAX));
UINT16 small_magnitude = max(0, min(effect->small_magnitude, UINT16_MAX));
CONS_Debug(DBG_GAMELOGIC, "Starting rumble effect for controller %d:\n", which);
CONS_Debug(DBG_GAMELOGIC, " Large motor magnitude: %f\n", large_magnitude / 65535.0f);
CONS_Debug(DBG_GAMELOGIC, " Small motor magnitude: %f\n", small_magnitude / 65535.0f);
if (!duration)
CONS_Debug(DBG_GAMELOGIC, " Duration: forever\n");
else
CONS_Debug(DBG_GAMELOGIC, " Duration: %dms\n", duration);
controller->rumble.large_magnitude = large_magnitude;
controller->rumble.small_magnitude = small_magnitude;
if (!rumble_paused && !Controller_Rumble(controller))
{
Controller_StopRumble(which);
return false;
}
controller->rumble.time_left = 0;
if (duration)
controller->rumble.expiration = SDL_GetTicks() + duration;
else
controller->rumble.expiration = 0;
// Update gamepad rumble info
gamepad_t *gamepad = controller->info;
gamepad->rumble.active = true;
gamepad->rumble.paused = false;
gamepad->rumble.data.large_magnitude = effect->large_magnitude;
gamepad->rumble.data.small_magnitude = effect->small_magnitude;
gamepad->rumble.data.duration = effect->duration;
return true;
}
#undef TICS_TO_MS
#define SET_MOTOR_FREQ(type) \
if (!I_RumbleSupported() || which >= NUM_GAMEPADS) \
return false; \
\
ControllerInfo *controller = &controllers[which]; \
if (!controller->started || !controller->info->rumble.supported) \
return false; \
\
gamepad_t *gamepad = controller->info; \
if (gamepad->rumble.data.type##_magnitude == freq) \
return true; \
\
UINT16 frequency = max(0, min(freq, UINT16_MAX)); \
\
controller->rumble.type##_magnitude = frequency; \
\
if (!rumble_paused && !gamepad->rumble.paused && !Controller_Rumble(controller)) \
{ \
Controller_StopRumble(which); \
return false; \
} \
\
gamepad->rumble.data.type##_magnitude = freq; \
gamepad->rumble.active = true; \
return true
boolean I_SetGamepadLargeMotorFreq(UINT8 which, fixed_t freq)
{
SET_MOTOR_FREQ(large);
}
boolean I_SetGamepadSmallMotorFreq(UINT8 which, fixed_t freq)
{
SET_MOTOR_FREQ(small);
}
void I_SetGamepadRumblePaused(UINT8 which, boolean pause)
{
if (!I_RumbleSupported() || which >= NUM_GAMEPADS)
return;
ControllerInfo *controller = &controllers[which];
if (!controller->started || !controller->info->rumble.supported)
return;
if (pause == controller->info->rumble.paused)
return;
else if (pause)
{
if (!rumble_paused)
SDL_GameControllerRumble(controller->dev, 0, 0, 0);
if (controller->rumble.expiration)
{
controller->rumble.time_left = controller->rumble.expiration - SDL_GetTicks();
controller->rumble.expiration = 0;
}
}
else
{
if (!rumble_paused)
SDL_GameControllerRumble(controller->dev, controller->rumble.large_magnitude, controller->rumble.small_magnitude, 0);
if (controller->rumble.time_left)
controller->rumble.expiration = SDL_GetTicks() + controller->rumble.time_left;
}
controller->info->rumble.paused = pause;
}
boolean I_GetGamepadRumbleSupported(UINT8 which)
{
if (!I_RumbleSupported() || which >= NUM_GAMEPADS)
return false;
ControllerInfo *controller = &controllers[which];
if (!controller->started)
return false;
return controller->info->rumble.supported;
}
boolean I_GetGamepadRumblePaused(UINT8 which)
{
if (!I_RumbleSupported() || which >= NUM_GAMEPADS)
return false;
ControllerInfo *controller = &controllers[which];
if (!controller->started || !controller->info->rumble.supported)
return false;
return controller->info->rumble.paused;
}
void I_StopGamepadRumble(UINT8 which)
{
if (!I_RumbleSupported() || which >= NUM_GAMEPADS)
return;
ControllerInfo *controller = &controllers[which];
if (!controller->started || !controller->info->rumble.supported)
return;
Controller_StopRumble(which);
}
#endif

View file

@ -185,7 +185,6 @@ static char returnWadPath[256];
#include "../i_video.h"
#include "../i_sound.h"
#include "../i_system.h"
#include "../i_gamepad.h"
#include "../i_threads.h"
#include "../screen.h" //vid.WndParent
#include "../d_net.h"
@ -194,6 +193,8 @@ static char returnWadPath[256];
#include "endtxt.h"
#include "sdlmain.h"
#include "../i_joy.h"
#include "../m_argv.h"
#include "../r_main.h" // Frame interpolation/uncapped
@ -211,6 +212,41 @@ static char returnWadPath[256];
#include "../byteptr.h"
#endif
/** \brief The JoyReset function
\param JoySet Joystick info to reset
\return void
*/
static void JoyReset(SDLJoyInfo_t *JoySet)
{
if (JoySet->dev)
{
SDL_JoystickClose(JoySet->dev);
}
JoySet->dev = NULL;
JoySet->oldjoy = -1;
JoySet->axises = JoySet->buttons = JoySet->hats = JoySet->balls = 0;
//JoySet->scale
}
/** \brief First joystick up and running
*/
static INT32 joystick_started = 0;
/** \brief SDL info about joystick 1
*/
SDLJoyInfo_t JoyInfo;
/** \brief Second joystick up and running
*/
static INT32 joystick2_started = 0;
/** \brief SDL inof about joystick 2
*/
SDLJoyInfo_t JoyInfo2;
#ifdef HAVE_TERMIOS
static INT32 fdmouse2 = -1;
static INT32 mouse2_started = 0;
@ -903,17 +939,721 @@ INT32 I_GetKey (void)
return rc;
}
//
// I_JoyScale
//
void I_JoyScale(void)
{
Joystick.bGamepadStyle = cv_joyscale.value==0;
JoyInfo.scale = Joystick.bGamepadStyle?1:cv_joyscale.value;
}
void I_JoyScale2(void)
{
Joystick2.bGamepadStyle = cv_joyscale2.value==0;
JoyInfo2.scale = Joystick2.bGamepadStyle?1:cv_joyscale2.value;
}
// Cheat to get the device index for a joystick handle
INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev)
{
INT32 i, count = SDL_NumJoysticks();
for (i = 0; dev && i < count; i++)
{
SDL_Joystick *test = SDL_JoystickOpen(i);
if (test && test == dev)
return i;
else if (JoyInfo.dev != test && JoyInfo2.dev != test)
SDL_JoystickClose(test);
}
return -1;
}
/** \brief Joystick 1 buttons states
*/
static UINT64 lastjoybuttons = 0;
/** \brief Joystick 1 hats state
*/
static UINT64 lastjoyhats = 0;
/** \brief Shuts down joystick 1
\return void
*/
void I_ShutdownJoystick(void)
{
INT32 i;
event_t event;
event.type=ev_keyup;
event.x = 0;
event.y = 0;
lastjoybuttons = lastjoyhats = 0;
// emulate the up of all joystick buttons
for (i=0;i<JOYBUTTONS;i++)
{
event.key=KEY_JOY1+i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i=0;i<JOYHATS*4;i++)
{
event.key=KEY_HAT1+i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick;
for (i=0;i<JOYAXISSET; i++)
{
event.key = i;
D_PostEvent(&event);
}
joystick_started = 0;
JoyReset(&JoyInfo);
// don't shut down the subsystem here, because hotplugging
}
void I_GetJoystickEvents(void)
{
static event_t event = {0,0,0,0,false};
INT32 i = 0;
UINT64 joyhats = 0;
#if 0
UINT64 joybuttons = 0;
Sint16 axisx, axisy;
#endif
if (!joystick_started) return;
if (!JoyInfo.dev) //I_ShutdownJoystick();
return;
#if 0
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JoyInfo.buttons - 1; i >= 0; i--)
{
joybuttons <<= 1;
if (SDL_JoystickGetButton(JoyInfo.dev,i))
joybuttons |= 1;
}
if (joybuttons != lastjoybuttons)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newbuttons = joybuttons ^ lastjoybuttons;
lastjoybuttons = joybuttons;
for (i = 0; i < JOYBUTTONS; i++, j <<= 1)
{
if (newbuttons & j) // button changed state?
{
if (joybuttons & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.key = KEY_JOY1 + i;
D_PostEvent(&event);
}
}
}
#endif
for (i = JoyInfo.hats - 1; i >= 0; i--)
{
Uint8 hat = SDL_JoystickGetHat(JoyInfo.dev, i);
if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i);
if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
}
if (joyhats != lastjoyhats)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newhats = joyhats ^ lastjoyhats;
lastjoyhats = joyhats;
for (i = 0; i < JOYHATS*4; i++, j <<= 1)
{
if (newhats & j) // hat changed state?
{
if (joyhats & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.key = KEY_HAT1 + i;
D_PostEvent(&event);
}
}
}
#if 0
// send joystick axis positions
event.type = ev_joystick;
for (i = JOYAXISSET - 1; i >= 0; i--)
{
event.key = i;
if (i*2 + 1 <= JoyInfo.axises)
axisx = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 0);
else axisx = 0;
if (i*2 + 2 <= JoyInfo.axises)
axisy = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 1);
else axisy = 0;
// -32768 to 32767
axisx = axisx/32;
axisy = axisy/32;
if (Joystick.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2))
event.x = -1;
else if (axisx > (JOYAXISRANGE/2))
event.x = 1;
else event.x = 0;
if (axisy < -(JOYAXISRANGE/2))
event.y = -1;
else if (axisy > (JOYAXISRANGE/2))
event.y = 1;
else event.y = 0;
}
else
{
axisx = JoyInfo.scale?((axisx/JoyInfo.scale)*JoyInfo.scale):axisx;
axisy = JoyInfo.scale?((axisy/JoyInfo.scale)*JoyInfo.scale):axisy;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0;
if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0;
#endif
// analog control style , just send the raw data
event.x = axisx; // x axis
event.y = axisy; // y axis
}
D_PostEvent(&event);
}
#endif
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open(int joyindex)
{
SDL_Joystick *newdev = NULL;
int num_joy = 0;
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf(M_GetText("Joystick subsystem not started\n"));
return -1;
}
if (joyindex <= 0)
return -1;
num_joy = SDL_NumJoysticks();
if (num_joy == 0)
{
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
return -1;
}
newdev = SDL_JoystickOpen(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.
//
// 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.dev)
{
if (JoyInfo.dev == newdev // same device, nothing to do
|| (newdev == NULL && SDL_JoystickGetAttached(JoyInfo.dev))) // we failed, but already have a working device
return JoyInfo.axises;
// Else, we're changing devices, so send neutral joy events
CONS_Debug(DBG_GAMELOGIC, "Joystick1 device is changing; resetting events...\n");
I_ShutdownJoystick();
}
JoyInfo.dev = newdev;
if (JoyInfo.dev == NULL)
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: Couldn't open device - %s\n"), SDL_GetError());
return -1;
}
else
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: %s\n"), SDL_JoystickName(JoyInfo.dev));
JoyInfo.axises = SDL_JoystickNumAxes(JoyInfo.dev);
if (JoyInfo.axises > JOYAXISSET*2)
JoyInfo.axises = JOYAXISSET*2;
/* if (joyaxes<2)
{
I_OutputMsg("Not enought axes?\n");
return 0;
}*/
JoyInfo.buttons = SDL_JoystickNumButtons(JoyInfo.dev);
if (JoyInfo.buttons > JOYBUTTONS)
JoyInfo.buttons = JOYBUTTONS;
JoyInfo.hats = SDL_JoystickNumHats(JoyInfo.dev);
if (JoyInfo.hats > JOYHATS)
JoyInfo.hats = JOYHATS;
JoyInfo.balls = SDL_JoystickNumBalls(JoyInfo.dev);
//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo.dev), "pad");
return JoyInfo.axises;
}
}
//Joystick2
/** \brief Joystick 2 buttons states
*/
static UINT64 lastjoy2buttons = 0;
/** \brief Joystick 2 hats state
*/
static UINT64 lastjoy2hats = 0;
/** \brief Shuts down joystick 2
\return void
*/
void I_ShutdownJoystick2(void)
{
INT32 i;
event_t event;
event.type = ev_keyup;
event.x = 0;
event.y = 0;
lastjoy2buttons = lastjoy2hats = 0;
// emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++)
{
event.key = KEY_2JOY1 + i;
D_PostEvent(&event);
}
// emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++)
{
event.key = KEY_2HAT1 + i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick2;
for (i = 0; i < JOYAXISSET; i++)
{
event.key = i;
D_PostEvent(&event);
}
joystick2_started = 0;
JoyReset(&JoyInfo2);
// don't shut down the subsystem here, because hotplugging
}
void I_GetJoystick2Events(void)
{
static event_t event = {0,0,0,0,false};
INT32 i = 0;
UINT64 joyhats = 0;
#if 0
INT64 joybuttons = 0;
INT32 axisx, axisy;
#endif
if (!joystick2_started)
return;
if (!JoyInfo2.dev) //I_ShutdownJoystick2();
return;
#if 0
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JoyInfo2.buttons - 1; i >= 0; i--)
{
joybuttons <<= 1;
if (SDL_JoystickGetButton(JoyInfo2.dev,i))
joybuttons |= 1;
}
if (joybuttons != lastjoy2buttons)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newbuttons = joybuttons ^ lastjoy2buttons;
lastjoy2buttons = joybuttons;
for (i = 0; i < JOYBUTTONS; i++, j <<= 1)
{
if (newbuttons & j) // button changed state?
{
if (joybuttons & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.key = KEY_2JOY1 + i;
D_PostEvent(&event);
}
}
}
#endif
for (i = JoyInfo2.hats - 1; i >= 0; i--)
{
Uint8 hat = SDL_JoystickGetHat(JoyInfo2.dev, i);
if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i);
if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
}
if (joyhats != lastjoy2hats)
{
INT64 j = 1; // keep only bits that changed since last time
INT64 newhats = joyhats ^ lastjoy2hats;
lastjoy2hats = joyhats;
for (i = 0; i < JOYHATS*4; i++, j <<= 1)
{
if (newhats & j) // hat changed state?
{
if (joyhats & j)
event.type = ev_keydown;
else
event.type = ev_keyup;
event.key = KEY_2HAT1 + i;
D_PostEvent(&event);
}
}
}
#if 0
// send joystick axis positions
event.type = ev_joystick2;
for (i = JOYAXISSET - 1; i >= 0; i--)
{
event.key = i;
if (i*2 + 1 <= JoyInfo2.axises)
axisx = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 0);
else axisx = 0;
if (i*2 + 2 <= JoyInfo2.axises)
axisy = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 1);
else axisy = 0;
// -32768 to 32767
axisx = axisx/32;
axisy = axisy/32;
if (Joystick2.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2))
event.x = -1;
else if (axisx > (JOYAXISRANGE/2))
event.x = 1;
else
event.x = 0;
if (axisy < -(JOYAXISRANGE/2))
event.y = -1;
else if (axisy > (JOYAXISRANGE/2))
event.y = 1;
else
event.y = 0;
}
else
{
axisx = JoyInfo2.scale?((axisx/JoyInfo2.scale)*JoyInfo2.scale):axisx;
axisy = JoyInfo2.scale?((axisy/JoyInfo2.scale)*JoyInfo2.scale):axisy;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0;
if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0;
#endif
// analog control style , just send the raw data
event.x = axisx; // x axis
event.y = axisy; // y axis
}
D_PostEvent(&event);
}
#endif
}
/** \brief Open joystick handle
\param fname name of joystick
\return axises
*/
static int joy_open2(int joyindex)
{
SDL_Joystick *newdev = NULL;
int num_joy = 0;
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf(M_GetText("Joystick subsystem not started\n"));
return -1;
}
if (joyindex <= 0)
return -1;
num_joy = SDL_NumJoysticks();
if (num_joy == 0)
{
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
return -1;
}
newdev = SDL_JoystickOpen(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.
//
// 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 (JoyInfo2.dev)
{
if (JoyInfo2.dev == newdev // same device, nothing to do
|| (newdev == NULL && SDL_JoystickGetAttached(JoyInfo2.dev))) // we failed, but already have a working device
return JoyInfo.axises;
// Else, we're changing devices, so send neutral joy events
CONS_Debug(DBG_GAMELOGIC, "Joystick2 device is changing; resetting events...\n");
I_ShutdownJoystick2();
}
JoyInfo2.dev = newdev;
if (JoyInfo2.dev == NULL)
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: couldn't open device - %s\n"), SDL_GetError());
return -1;
}
else
{
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev));
JoyInfo2.axises = SDL_JoystickNumAxes(JoyInfo2.dev);
if (JoyInfo2.axises > JOYAXISSET*2)
JoyInfo2.axises = JOYAXISSET*2;
/* if (joyaxes<2)
{
I_OutputMsg("Not enought axes?\n");
return 0;
}*/
JoyInfo2.buttons = SDL_JoystickNumButtons(JoyInfo2.dev);
if (JoyInfo2.buttons > JOYBUTTONS)
JoyInfo2.buttons = JOYBUTTONS;
JoyInfo2.hats = SDL_JoystickNumHats(JoyInfo2.dev);
if (JoyInfo2.hats > JOYHATS)
JoyInfo2.hats = JOYHATS;
JoyInfo2.balls = SDL_JoystickNumBalls(JoyInfo2.dev);
//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo2.dev), "pad");
return JoyInfo2.axises;
}
}
//
// I_InitJoystick
//
void I_InitJoystick(void)
{
SDL_Joystick *newjoy = NULL;
//I_ShutdownJoystick();
if (M_CheckParm("-nojoy"))
return;
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 (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf("I_InitJoystick()...\n");
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return;
}
}
if (cv_usejoystick.value)
newjoy = SDL_JoystickOpen(cv_usejoystick.value-1);
if (newjoy && JoyInfo2.dev == newjoy) // don't override an active device
cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1;
else if (newjoy && joy_open(cv_usejoystick.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.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1;
joystick_started = 1;
}
else
{
if (JoyInfo.oldjoy)
I_ShutdownJoystick();
cv_usejoystick.value = 0;
joystick_started = 0;
}
if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy)
SDL_JoystickClose(newjoy);
}
void I_InitJoystick2(void)
{
SDL_Joystick *newjoy = NULL;
//I_ShutdownJoystick2();
if (M_CheckParm("-nojoy"))
return;
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 (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf("I_InitJoystick2()...\n");
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
{
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
return;
}
}
if (cv_usejoystick2.value)
newjoy = SDL_JoystickOpen(cv_usejoystick2.value-1);
if (newjoy && JoyInfo.dev == newjoy) // don't override an active device
cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1;
else if (newjoy && joy_open2(cv_usejoystick2.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.
JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1;
joystick2_started = 1;
}
else
{
if (JoyInfo2.oldjoy)
I_ShutdownJoystick2();
cv_usejoystick2.value = 0;
joystick2_started = 0;
}
if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy)
SDL_JoystickClose(newjoy);
}
static void I_ShutdownInput(void)
{
I_ShutdownGamepads();
// 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.
I_ShutdownJoystick();
I_ShutdownJoystick2();
if (SDL_WasInit(GAMEPAD_INIT_FLAGS) == GAMEPAD_INIT_FLAGS)
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
CONS_Printf("Shutting down game controller subsystems\n");
SDL_QuitSubSystem(GAMEPAD_INIT_FLAGS);
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 numjoy = 0;
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
numjoy = SDL_NumJoysticks();
return numjoy;
}
static char joyname[255]; // joystick name is straight from the driver
const char *I_GetJoyName(INT32 joyindex)
{
const char *tempname = NULL;
joyname[0] = 0;
joyindex--; //SDL's Joystick System starts at 0, not 1
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
tempname = SDL_JoystickNameForIndex(joyindex);
if (tempname)
strncpy(joyname, tempname, 255);
}
return joyname;
}
#ifndef NOMUMBLE
#ifdef HAVE_MUMBLE
// Best Mumble positional audio settings:
@ -1373,6 +2113,23 @@ void I_StartupMouse2(void)
#endif
}
//
// 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;
}
/** \brief empty ticcmd for player 1
*/
static ticcmd_t emptycmd;

View file

@ -66,7 +66,7 @@
#include "../m_menu.h"
#include "../d_main.h"
#include "../s_sound.h"
#include "../i_gamepad.h"
#include "../i_joy.h"
#include "../st_stuff.h"
#include "../hu_stuff.h"
#include "../g_game.h"
@ -449,10 +449,51 @@ static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText)
static void VID_Command_Info_f (void)
{
#if 0
SDL2STUB();
#else
#if 0
const SDL_VideoInfo *videoInfo;
videoInfo = SDL_GetVideoInfo(); //Alam: Double-Check
if (videoInfo)
{
CONS_Printf("%s", M_GetText("Video Interface Capabilities:\n"));
if (videoInfo->hw_available)
CONS_Printf("%s", M_GetText(" Hardware surfaces\n"));
if (videoInfo->wm_available)
CONS_Printf("%s", M_GetText(" Window manager\n"));
//UnusedBits1 :6
//UnusedBits2 :1
if (videoInfo->blit_hw)
CONS_Printf("%s", M_GetText(" Accelerated blits HW-2-HW\n"));
if (videoInfo->blit_hw_CC)
CONS_Printf("%s", M_GetText(" Accelerated blits HW-2-HW with Colorkey\n"));
if (videoInfo->wm_available)
CONS_Printf("%s", M_GetText(" Accelerated blits HW-2-HW with Alpha\n"));
if (videoInfo->blit_sw)
{
CONS_Printf("%s", M_GetText(" Accelerated blits SW-2-HW\n"));
if (!M_CheckParm("-noblit")) videoblitok = SDL_TRUE;
}
if (videoInfo->blit_sw_CC)
CONS_Printf("%s", M_GetText(" Accelerated blits SW-2-HW with Colorkey\n"));
if (videoInfo->blit_sw_A)
CONS_Printf("%s", M_GetText(" Accelerated blits SW-2-HW with Alpha\n"));
if (videoInfo->blit_fill)
CONS_Printf("%s", M_GetText(" Accelerated Color filling\n"));
//UnusedBits3 :16
if (videoInfo->video_mem)
CONS_Printf(M_GetText(" There is %i KB of video memory\n"), videoInfo->video_mem);
else
CONS_Printf("%s", M_GetText(" There no video memory for SDL\n"));
//*vfmt
}
#else
if (!M_CheckParm("-noblit")) videoblitok = SDL_TRUE;
#endif
SurfaceInfo(bufSurface, M_GetText("Current Engine Mode"));
SurfaceInfo(vidSurface, M_GetText("Current Video Mode"));
#endif
}
static void VID_Command_ModeList_f(void)
@ -487,6 +528,61 @@ static void VID_Command_Mode_f (void)
setmodeneeded = modenum+1; // request vid mode change
}
static inline void SDLJoyRemap(event_t *event)
{
(void)event;
}
static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which)
{
// -32768 to 32767
INT32 raxis = axis/32;
if (which == ev_joystick)
{
if (Joystick.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (raxis < -(JOYAXISRANGE/2))
raxis = -1;
else if (raxis > (JOYAXISRANGE/2))
raxis = 1;
else
raxis = 0;
}
else
{
raxis = JoyInfo.scale!=1?((raxis/JoyInfo.scale)*JoyInfo.scale):raxis;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE)
raxis = 0;
#endif
}
}
else if (which == ev_joystick2)
{
if (Joystick2.bGamepadStyle)
{
// gamepad control type, on or off, live or die
if (raxis < -(JOYAXISRANGE/2))
raxis = -1;
else if (raxis > (JOYAXISRANGE/2))
raxis = 1;
else raxis = 0;
}
else
{
raxis = JoyInfo2.scale!=1?((raxis/JoyInfo2.scale)*JoyInfo2.scale):raxis;
#ifdef SDL_JDEADZONE
if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE)
raxis = 0;
#endif
}
}
return raxis;
}
static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
{
static SDL_bool firsttimeonmouse = SDL_TRUE;
@ -518,13 +614,13 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
// Tell game we got focus back, resume music if necessary
window_notinfocus = false;
if (!paused)
S_ResumeAudio();
S_ResumeAudio(); //resume it
I_ToggleControllerRumble(true);
P_UnpauseRumble(NULL);
if (!firsttimeonmouse && cv_usemouse.value)
I_StartupMouse();
if (!firsttimeonmouse)
{
if (cv_usemouse.value) I_StartupMouse();
}
//else firsttimeonmouse = SDL_FALSE;
if (USE_MOUSEINPUT && !IgnoreMouse())
SDLdoGrabMouse();
@ -533,45 +629,43 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
{
// Tell game we lost focus, pause music
window_notinfocus = true;
if (!cv_playmusicifunfocused.value)
if (! cv_playmusicifunfocused.value)
S_PauseAudio();
if (!cv_playsoundsifunfocused.value)
if (! cv_playsoundsifunfocused.value)
S_StopSounds();
if (!disable_mouse)
{
SDLforceUngrabMouse();
}
memset(gamekeydown, 0, NUMKEYS); // TODO this is a scary memset
I_ToggleControllerRumble(false);
if (P_AutoPause())
P_PauseRumble(NULL);
if (MOUSE_MENU)
{
SDLdoUngrabMouse();
}
}
}
static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
{
event_t event;
if (type == SDL_KEYUP)
{
event.type = ev_keyup;
}
else if (type == SDL_KEYDOWN)
{
event.type = ev_keydown;
}
else
{
return;
}
event.key = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
if (!event.key)
return;
event.repeated = (evt.repeat != 0);
event.which = 0;
D_PostEvent(&event);
if (event.key) D_PostEvent(&event);
}
static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
@ -636,35 +730,32 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
if (SDL_GetMouseFocus() != window || IgnoreMouse())
return;
/// \todo inputEvent.button.which
if (USE_MOUSEINPUT)
{
if (type == SDL_MOUSEBUTTONUP)
event.type = ev_keyup;
else if (type == SDL_MOUSEBUTTONDOWN)
event.type = ev_keydown;
else
return;
switch (evt.button)
{
case SDL_BUTTON_LEFT:
event.key = KEY_MOUSE1+0;
break;
case SDL_BUTTON_RIGHT:
event.key = KEY_MOUSE1+1;
break;
case SDL_BUTTON_MIDDLE:
event.key = KEY_MOUSE1+2;
break;
case SDL_BUTTON_X1:
event.key = KEY_MOUSE1+3;
break;
case SDL_BUTTON_X2:
event.key = KEY_MOUSE1+4;
break;
event.type = ev_keyup;
}
else if (type == SDL_MOUSEBUTTONDOWN)
{
event.type = ev_keydown;
}
else return;
if (evt.button == SDL_BUTTON_MIDDLE)
event.key = KEY_MOUSE1+2;
else if (evt.button == SDL_BUTTON_RIGHT)
event.key = KEY_MOUSE1+1;
else if (evt.button == SDL_BUTTON_LEFT)
event.key = KEY_MOUSE1;
else if (evt.button == SDL_BUTTON_X1)
event.key = KEY_MOUSE1+3;
else if (evt.button == SDL_BUTTON_X2)
event.key = KEY_MOUSE1+4;
if (event.type == ev_keyup || event.type == ev_keydown)
{
D_PostEvent(&event);
}
D_PostEvent(&event);
}
}
@ -695,6 +786,111 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
}
}
static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
{
event_t event;
SDL_JoystickID joyid[2];
// Determine the Joystick IDs for each current open joystick
joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev);
joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
evt.axis++;
event.key = event.x = event.y = INT32_MAX;
if (evt.which == joyid[0])
{
event.type = ev_joystick;
}
else if (evt.which == joyid[1])
{
event.type = ev_joystick2;
}
else return;
//axis
if (evt.axis > JOYAXISSET*2)
return;
//vaule
if (evt.axis%2)
{
event.key = evt.axis / 2;
event.x = SDLJoyAxis(evt.value, event.type);
}
else
{
evt.axis--;
event.key = evt.axis / 2;
event.y = SDLJoyAxis(evt.value, event.type);
}
D_PostEvent(&event);
}
#if 0
static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt)
{
event_t event;
SDL_JoystickID joyid[2];
// Determine the Joystick IDs for each current open joystick
joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev);
joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
if (evt.hat >= JOYHATS)
return; // ignore hats with too high an index
if (evt.which == joyid[0])
{
event.key = KEY_HAT1 + (evt.hat*4);
}
else if (evt.which == joyid[1])
{
event.key = KEY_2HAT1 + (evt.hat*4);
}
else return;
// NOTE: UNFINISHED
}
#endif
static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
{
event_t event;
SDL_JoystickID joyid[2];
// Determine the Joystick IDs for each current open joystick
joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev);
joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
if (evt.which == joyid[0])
{
event.key = KEY_JOY1;
}
else if (evt.which == joyid[1])
{
event.key = KEY_2JOY1;
}
else return;
if (type == SDL_JOYBUTTONUP)
{
event.type = ev_keyup;
}
else if (type == SDL_JOYBUTTONDOWN)
{
event.type = ev_keydown;
}
else return;
if (evt.button < JOYBUTTONS)
{
event.key += evt.button;
}
else return;
SDLJoyRemap(&event);
if (event.type != ev_console) D_PostEvent(&event);
}
void I_GetEvent(void)
{
SDL_Event evt;
@ -732,18 +928,147 @@ void I_GetEvent(void)
case SDL_MOUSEWHEEL:
Impl_HandleMouseWheelEvent(evt.wheel);
break;
case SDL_CONTROLLERAXISMOTION:
I_HandleControllerAxisEvent(evt.caxis);
case SDL_JOYAXISMOTION:
Impl_HandleJoystickAxisEvent(evt.jaxis);
break;
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERBUTTONDOWN:
I_HandleControllerButtonEvent(evt.cbutton, evt.type);
#if 0
case SDL_JOYHATMOTION:
Impl_HandleJoystickHatEvent(evt.jhat)
break;
case SDL_CONTROLLERDEVICEADDED:
I_ControllerDeviceAdded(evt.cdevice.which);
#endif
case SDL_JOYBUTTONUP:
case SDL_JOYBUTTONDOWN:
Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type);
break;
case SDL_CONTROLLERDEVICEREMOVED:
I_ControllerDeviceRemoved();
case SDL_JOYDEVICEADDED:
{
SDL_Joystick *newjoy = SDL_JoystickOpen(evt.jdevice.which);
CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 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!
if (newjoy && (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev))
&& JoyInfo2.dev != newjoy) // don't override a currently active device
{
cv_usejoystick.value = evt.jdevice.which + 1;
if (JoyInfo2.dev)
cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1;
else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy
&& atoi(cv_usejoystick2.string) != cv_usejoystick.value)
cv_usejoystick2.value = atoi(cv_usejoystick2.string);
else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy
&& atoi(cv_usejoystick.string) != cv_usejoystick.value)
cv_usejoystick2.value = atoi(cv_usejoystick.string);
else // we tried...
cv_usejoystick2.value = 0;
}
else if (newjoy && (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev))
&& JoyInfo.dev != newjoy) // don't override a currently active device
{
cv_usejoystick2.value = evt.jdevice.which + 1;
if (JoyInfo.dev)
cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1;
else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy
&& atoi(cv_usejoystick.string) != cv_usejoystick2.value)
cv_usejoystick.value = atoi(cv_usejoystick.string);
else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy
&& atoi(cv_usejoystick2.string) != cv_usejoystick2.value)
cv_usejoystick.value = atoi(cv_usejoystick2.string);
else // we tried...
cv_usejoystick.value = 0;
}
// Was cv_usejoystick disabled in settings?
if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value)
cv_usejoystick.value = 0;
else if (atoi(cv_usejoystick.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
&& cv_usejoystick.value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usejoystick, cv_usejoystick.value);
if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value)
cv_usejoystick2.value = 0;
else if (atoi(cv_usejoystick2.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
&& cv_usejoystick2.value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usejoystick2, cv_usejoystick2.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.
I_InitJoystick();
I_InitJoystick2();
CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy);
CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy);
// update the menu
if (currentMenu == &OP_JoystickSetDef)
M_SetupJoystickMenu(0);
if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy)
SDL_JoystickClose(newjoy);
}
break;
case SDL_JOYDEVICEREMOVED:
if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev))
{
CONS_Debug(DBG_GAMELOGIC, "Joystick1 removed, device index: %d\n", JoyInfo.oldjoy);
I_ShutdownJoystick();
}
if (JoyInfo2.dev && !SDL_JoystickGetAttached(JoyInfo2.dev))
{
CONS_Debug(DBG_GAMELOGIC, "Joystick2 removed, device index: %d\n", JoyInfo2.oldjoy);
I_ShutdownJoystick2();
}
// 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!
if (JoyInfo.dev)
cv_usejoystick.value = JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1;
else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy)
cv_usejoystick.value = atoi(cv_usejoystick.string);
else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy)
cv_usejoystick.value = atoi(cv_usejoystick2.string);
else // we tried...
cv_usejoystick.value = 0;
if (JoyInfo2.dev)
cv_usejoystick2.value = JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1;
else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy)
cv_usejoystick2.value = atoi(cv_usejoystick2.string);
else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy)
cv_usejoystick2.value = atoi(cv_usejoystick.string);
else // we tried...
cv_usejoystick2.value = 0;
// Was cv_usejoystick disabled in settings?
if (!strcmp(cv_usejoystick.string, "0"))
cv_usejoystick.value = 0;
else if (atoi(cv_usejoystick.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
&& cv_usejoystick.value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usejoystick, cv_usejoystick.value);
if (!strcmp(cv_usejoystick2.string, "0"))
cv_usejoystick2.value = 0;
else if (atoi(cv_usejoystick2.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
&& cv_usejoystick2.value) // update the cvar ONLY if a device exists
CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value);
CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy);
CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy);
// update the menu
if (currentMenu == &OP_JoystickSetDef)
M_SetupJoystickMenu(0);
break;
case SDL_QUIT:
LUA_HookBool(true, HOOK(GameQuit));
@ -761,7 +1086,6 @@ void I_GetEvent(void)
//SDL_memset(&event, 0, sizeof(event_t));
event.type = ev_mouse;
event.key = 0;
event.which = 0;
event.x = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
event.y = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
D_PostEvent(&event);
@ -800,9 +1124,15 @@ void I_OsPolling(void)
if (consolevent)
I_GetConsoleEvents();
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_JoystickUpdate();
I_GetJoystickEvents();
I_GetJoystick2Events();
}
I_UpdateControllers();
I_GetMouseEvents();
I_GetEvent();
mod = SDL_GetModState();

View file

@ -23,41 +23,59 @@ extern SDL_bool consolevent;
extern SDL_bool framebuffer;
#include "../m_fixed.h"
#include "../i_gamepad.h"
// SDL info about all controllers
typedef struct
// SDL2 stub macro
#ifdef _MSC_VER
#define SDL2STUB() CONS_Printf("SDL2: stubbed: %s:%d\n", __FUNCTION__, __LINE__)
#else
#define SDL2STUB() CONS_Printf("SDL2: stubbed: %s:%d\n", __func__, __LINE__)
#endif
// So m_menu knows whether to store cv_usejoystick value or string
#define JOYSTICK_HOTPLUG
/** \brief The JoyInfo_s struct
info about joystick
*/
typedef struct SDLJoyInfo_s
{
boolean started; // started
int lastindex; // last gamepad ID
/// Joystick handle
SDL_Joystick *dev;
/// number of old joystick
int oldjoy;
/// number of axies
int axises;
/// scale of axises
INT32 scale;
/// number of buttons
int buttons;
/// number of hats
int hats;
/// number of balls
int balls;
SDL_GameController *dev;
SDL_Joystick *joydev;
} SDLJoyInfo_t;
gamepad_t *info; // pointer to gamepad info
/** \brief SDL info about joystick 1
*/
extern SDLJoyInfo_t JoyInfo;
struct {
Uint16 large_magnitude;
Uint16 small_magnitude;
Uint32 expiration, time_left;
} rumble;
} ControllerInfo;
/** \brief joystick axis deadzone
*/
#define SDL_JDEADZONE 153
#undef SDL_JDEADZONE
#define GAMEPAD_INIT_FLAGS (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER)
/** \brief SDL inof about joystick 2
*/
extern SDLJoyInfo_t JoyInfo2;
void I_UpdateControllers(void);
// So we can call this from i_video event loop
void I_ShutdownJoystick(void);
void I_ShutdownJoystick2(void);
void I_ControllerDeviceAdded(INT32 which);
void I_ControllerDeviceRemoved(void);
void I_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type);
void I_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt);
INT32 I_GetControllerIndex(SDL_GameController *dev);
void I_CloseInactiveController(SDL_GameController *dev);
void I_CloseInactiveHapticDevice(SDL_Haptic *dev);
void I_ToggleControllerRumble(boolean unpause);
// Cheat to get the device index for a joystick handle
INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev);
void I_GetConsoleEvents(void);