From e5dea805fa6c66b151b9510703795bc0070a1ff1 Mon Sep 17 00:00:00 2001 From: Eidolon <furyhunter600@gmail.com> Date: Thu, 26 Jan 2023 19:26:28 -0600 Subject: [PATCH] Revert "Merge branch 'gamepad-refactor' into next" This reverts commit 696e2ab9097a674716e579eb848024b0b8539205, reversing changes made to d98d59494f493307b3cae8d741e9a3969c2af2eb. --- src/Sourcefile | 1 - src/command.c | 81 +-- src/console.c | 9 +- src/d_clisrv.c | 89 ++- src/d_event.h | 14 +- src/d_main.c | 8 - src/d_netcmd.c | 140 ++--- src/d_netcmd.h | 12 +- src/deh_tables.c | 10 +- src/doomdef.h | 5 +- src/f_finale.c | 76 ++- src/g_demo.c | 6 +- src/g_game.c | 653 ++++++++++------------ src/g_game.h | 24 +- src/g_input.c | 1257 +++++++++++-------------------------------- src/g_input.h | 216 +------- src/hu_stuff.c | 22 +- src/i_gamepad.h | 58 -- src/i_joy.h | 58 ++ src/i_system.h | 94 +++- src/lua_inputlib.c | 9 +- src/m_cheat.c | 32 +- src/m_menu.c | 748 +++++++++++-------------- src/m_menu.h | 28 +- src/p_haptic.c | 115 ---- src/p_haptic.h | 27 - src/p_inter.c | 70 ++- src/p_local.h | 15 + src/p_user.c | 6 +- src/sdl/Sourcefile | 1 - src/sdl/i_gamepad.c | 914 ------------------------------- src/sdl/i_system.c | 767 +++++++++++++++++++++++++- src/sdl/i_video.c | 438 +++++++++++++-- src/sdl/sdlmain.h | 80 +-- 34 files changed, 2595 insertions(+), 3488 deletions(-) delete mode 100644 src/i_gamepad.h create mode 100644 src/i_joy.h delete mode 100644 src/p_haptic.c delete mode 100644 src/p_haptic.h delete mode 100644 src/sdl/i_gamepad.c diff --git a/src/Sourcefile b/src/Sourcefile index 9de90eee48..de90bb6091 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -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 diff --git a/src/command.c b/src/command.c index 201cceeeea..b22f03d1a6 100644 --- a/src/command.c +++ b/src/command.c @@ -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; } diff --git a/src/console.c b/src/console.c index 7cad4aee53..40fb43121f 100644 --- a/src/console.c +++ b/src/console.c @@ -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; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3091f33440..1ff053e5cc 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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); diff --git a/src/d_event.h b/src/d_event.h index 9448b9c5a0..c0b9cef773 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -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; // diff --git a/src/d_main.c b/src/d_main.c index 1af8d090c1..3566e7f3d2 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -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(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 07dba17774..f63f38a74a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -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); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 47f68a17e9..0beeae1549 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -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; diff --git a/src/deh_tables.c b/src/deh_tables.c index a2cc9732db..4a3467f783 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -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}, diff --git a/src/doomdef.h b/src/doomdef.h index 24b4fa9807..2b62bcd6e9 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -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 diff --git a/src/f_finale.c b/src/f_finale.c index 307e00aaa2..bca8e3ba69 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -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); diff --git a/src/g_demo.c b/src/g_demo.c index 9099adc712..2da5a76ab2 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -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; diff --git a/src/g_game.c b/src/g_game.c index ce41ccaf68..74bc427112 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -24,7 +24,6 @@ #include "am_map.h" #include "m_random.h" #include "p_local.h" -#include "p_haptic.h" #include "r_draw.h" #include "r_main.h" #include "s_sound.h" @@ -39,7 +38,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" @@ -60,6 +59,9 @@ boolean botingame; UINT8 botskin; UINT16 botcolor; +JoyType_t Joystick; +JoyType_t Joystick2; + // 1024 bytes is plenty for a savegame #define SAVEGAMESIZE (1024) @@ -254,6 +256,12 @@ UINT32 timesBeaten; UINT32 timesBeatenWithEmeralds; UINT32 timesBeatenUltimate; +typedef struct joystickvector2_s +{ + INT32 xaxis; + INT32 yaxis; +} joystickvector2_t; + boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; @@ -272,42 +280,21 @@ static void AutoBrake2_OnChange(void); void SendWeaponPref(void); void SendWeaponPref2(void); -CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, -#ifndef OLD_GAMEPAD_AXES - {1, "Left Stick X"}, {2, "Left Stick Y"}, - {3, "Right Stick X"},{4, "Right Stick Y"}, - {-1, "Left Stick X-"}, {-2, "Left Stick Y-"}, - {-3, "Right Stick X-"}, {-4, "Right Stick Y-"}, - {5, "Left Trigger"}, {6, "Right Trigger"}, -#else - {1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"}, - #if JOYAXISSET > 1 - {3, "Z-Axis"}, {4, "X-Rudder"}, {-3, "Z-Axis-"}, {-4, "X-Rudder-"}, - #endif - #if JOYAXISSET > 2 - {5, "Y-Rudder"}, {6, "Z-Rudder"}, {-5, "Y-Rudder-"}, {-6, "Z-Rudder-"}, - #endif - #if JOYAXISSET > 3 - {7, "U-Axis"}, {8, "V-Axis"}, {-7, "U-Axis-"}, {-8, "V-Axis-"}, - #endif +static CV_PossibleValue_t crosshair_cons_t[] = {{0, "Off"}, {1, "Cross"}, {2, "Angle"}, {3, "Point"}, {0, NULL}}; +static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, +{1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"}, +#if JOYAXISSET > 1 +{3, "Z-Axis"}, {4, "X-Rudder"}, {-3, "Z-Axis-"}, {-4, "X-Rudder-"}, #endif - {0, NULL} -}; - -#ifndef OLD_GAMEPAD_AXES -#define MOVEAXIS_DEFAULT "Left Stick Y" -#define SIDEAXIS_DEFAULT "Left Stick X" -#define LOOKAXIS_DEFAULT "Right Stick Y-" -#define TURNAXIS_DEFAULT "Right Stick X" -#define FIREAXIS_DEFAULT "Right Trigger" -#define FIRENAXIS_DEFAULT "Left Trigger" -#else -#define MOVEAXIS_DEFAULT "Y-Axis" -#define SIDEAXIS_DEFAULT "X-Axis" -#define LOOKAXIS_DEFAULT "Y-Rudder-" -#define TURNAXIS_DEFAULT "X-Rudder" -#define FIREAXIS_DEFAULT "Z-Rudder" -#define FIRENAXIS_DEFAULT "Z-Axis" +#if JOYAXISSET > 2 +{5, "Y-Rudder"}, {6, "Z-Rudder"}, {-5, "Y-Rudder-"}, {-6, "Z-Rudder-"}, +#endif +#if JOYAXISSET > 3 +{7, "U-Axis"}, {8, "V-Axis"}, {-7, "U-Axis-"}, {-8, "V-Axis-"}, +#endif + {0, NULL}}; +#if JOYAXISSET > 4 +"More Axis Sets" #endif // don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. @@ -343,7 +330,6 @@ consvar_t cv_consolechat = CVAR_INIT ("chatmode", "Window", CV_SAVE, consolechat // Pause game upon window losing focus consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL); -static CV_PossibleValue_t crosshair_cons_t[] = {{0, "Off"}, {1, "Cross"}, {2, "Angle"}, {3, "Point"}, {0, NULL}}; consvar_t cv_crosshair = CVAR_INIT ("crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL); consvar_t cv_crosshair2 = CVAR_INIT ("crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL); consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL); @@ -423,46 +409,27 @@ consvar_t cv_cam_lockonboss[2] = { CVAR_INIT ("cam2_lockaimassist", "Full", CV_SAVE, lockedassist_cons_t, NULL), }; -consvar_t cv_moveaxis[2] = { - CVAR_INIT ("joyaxis_move", MOVEAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_move", MOVEAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_sideaxis[2] = { - CVAR_INIT ("joyaxis_side", SIDEAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_side", SIDEAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_lookaxis[2] = { - CVAR_INIT ("joyaxis_look", LOOKAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_look", LOOKAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_turnaxis[2] = { - CVAR_INIT ("joyaxis_turn", TURNAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_turn", TURNAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_jumpaxis[2] = { - CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_spinaxis[2] = { - CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_fireaxis[2] = { - CVAR_INIT ("joyaxis_fire", FIREAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_fire", FIREAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_firenaxis[2] = { - CVAR_INIT ("joyaxis_firenormal", FIRENAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), - CVAR_INIT ("joyaxis2_firenormal", FIRENAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) -}; -consvar_t cv_deadzone[2] = { - CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) -}; -consvar_t cv_digitaldeadzone[2] = { - CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) -}; +consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); +consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); + +consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); +consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); player_t *seenplayer; // player we're aiming at right now @@ -861,171 +828,194 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming) return (INT16)((*aiming)>>16); } -#ifdef OLD_GAMEPAD_AXES -static gamepad_axis_e ConvertXboxControllerAxes(int type) +INT32 JoyAxis(joyaxis_e axissel) { - switch (type) - { - // Left stick - case 1: // X-Axis - return GAMEPAD_AXIS_LEFTX; - case 2: // Y-Axis - return GAMEPAD_AXIS_LEFTY; - - // Right stick - case 4: // X-Rudder - return GAMEPAD_AXIS_RIGHTX; - case 5: // Y-Rudder - return GAMEPAD_AXIS_RIGHTY; - - // Triggers - case 3: // Z-Axis - return GAMEPAD_AXIS_TRIGGERLEFT; - case 6: // Z-Rudder - return GAMEPAD_AXIS_TRIGGERRIGHT; + INT32 retaxis; + INT32 axisval; + boolean flp = false; - default: // All the other ones - return NUM_GAMEPAD_AXES; + //find what axis to get + switch (axissel) + { + case JA_TURN: + axisval = cv_turnaxis.value; + break; + case JA_MOVE: + axisval = cv_moveaxis.value; + break; + case JA_LOOK: + axisval = cv_lookaxis.value; + break; + case JA_STRAFE: + axisval = cv_sideaxis.value; + break; + case JA_JUMP: + axisval = cv_jumpaxis.value; + break; + case JA_SPIN: + axisval = cv_spinaxis.value; + break; + case JA_FIRE: + axisval = cv_fireaxis.value; + break; + case JA_FIRENORMAL: + axisval = cv_firenaxis.value; + break; + default: + return 0; } -} -#endif -static INT16 GetJoystickAxisValue(UINT8 which, joyaxis_e axissel, INT32 axisval) -{ - boolean flp = false; - - if (axisval < 0) // odd -axes + if (axisval < 0) //odd -axises { axisval = -axisval; flp = true; } - else if (axisval == 0) - return 0; - - if (axisval > JOYAXISSET*2) - return 0; - - gamepad_axis_e gp_axis; - -#ifdef OLD_GAMEPAD_AXES - gp_axis = ConvertXboxControllerAxes(axisval); -#else - gp_axis = axisval - 1; -#endif - - if (gp_axis >= NUM_GAMEPAD_AXES) + if (axisval > JOYAXISSET*2 || axisval == 0) //not there in array or None return 0; - if (axisval % 2) + if (axisval%2) + { axisval /= 2; + retaxis = joyxmove[axisval]; + } else { axisval--; axisval /= 2; + retaxis = joyymove[axisval]; } - INT16 retaxis = G_GetGamepadAxisValue(0, gp_axis); + if (retaxis < (-JOYAXISRANGE)) + retaxis = -JOYAXISRANGE; + if (retaxis > (+JOYAXISRANGE)) + retaxis = +JOYAXISRANGE; - if (gamepads[which].digital && axissel >= JA_DIGITAL) + if (!Joystick.bGamepadStyle && axissel >= JA_DIGITAL) { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(which) / 2; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } - // flip it around - if (flp) - retaxis = -retaxis; - + if (flp) retaxis = -retaxis; //flip it around return retaxis; } -INT16 G_JoyAxis(UINT8 which, joyaxis_e axissel) +INT32 Joy2Axis(joyaxis_e axissel) { + INT32 retaxis; INT32 axisval; + boolean flp = false; - // find what axis to get + //find what axis to get switch (axissel) { case JA_TURN: - axisval = cv_turnaxis[which].value; + axisval = cv_turnaxis2.value; break; case JA_MOVE: - axisval = cv_moveaxis[which].value; + axisval = cv_moveaxis2.value; break; case JA_LOOK: - axisval = cv_lookaxis[which].value; + axisval = cv_lookaxis2.value; break; case JA_STRAFE: - axisval = cv_sideaxis[which].value; + axisval = cv_sideaxis2.value; break; case JA_JUMP: - axisval = cv_jumpaxis[which].value; + axisval = cv_jumpaxis2.value; break; case JA_SPIN: - axisval = cv_spinaxis[which].value; + axisval = cv_spinaxis2.value; break; case JA_FIRE: - axisval = cv_fireaxis[which].value; + axisval = cv_fireaxis2.value; break; case JA_FIRENORMAL: - axisval = cv_firenaxis[which].value; + axisval = cv_firenaxis2.value; break; default: return 0; } - return GetJoystickAxisValue(which, axissel, axisval); -} -static INT16 GetAnalogInput(UINT8 which, gamecontrols_e gc) -{ - for (UINT8 i = 0; i < 2; i++) + if (axisval < 0) //odd -axises { - SINT8 isAnalog = G_PlayerInputIsAnalog(which, gc, i); - if (!isAnalog) - continue; + axisval = -axisval; + flp = true; + } + + if (axisval > JOYAXISSET*2 || axisval == 0) //not there in array or None + return 0; + + if (axisval%2) + { + axisval /= 2; + retaxis = joy2xmove[axisval]; + } + else + { + axisval--; + axisval /= 2; + retaxis = joy2ymove[axisval]; + } + + if (retaxis < (-JOYAXISRANGE)) + retaxis = -JOYAXISRANGE; + if (retaxis > (+JOYAXISRANGE)) + retaxis = +JOYAXISRANGE; - INT16 value = G_GetAnalogPlayerInput(which, gc, i); - if (value > 0 && isAnalog == 1) - return value; - else if (value < 0 && isAnalog == -1) - return max(min(-value, INT16_MAX), INT16_MIN); + if (!Joystick2.bGamepadStyle && axissel >= JA_DIGITAL) + { + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone2.value) >> FRACBITS; + if (-jdeadzone < retaxis && retaxis < jdeadzone) + return 0; } - return 0; + if (flp) retaxis = -retaxis; //flip it around + return retaxis; } -static boolean CheckAxesUsable(UINT8 which, gamecontrols_e gc1, gamecontrols_e gc2) + +#define PlayerJoyAxis(p, ax) ((p) == 1 ? JoyAxis(ax) : Joy2Axis(ax)) + +// Take a magnitude of two axes, and adjust it to take out the deadzone +// Will return a value between 0 and JOYAXISRANGE +static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone) { - INT32 (*controls)[2] = which == 0 ? gamecontrol : gamecontrolbis; + const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT; + INT32 deadzoneAppliedValue = 0; + INT32 adjustedMagnitude = abs(magnitude); -#define CHECK_RANGE(x, y, z) \ - (controls[x][y] >= KEY_AXES && controls[x][y] < KEY_AXES + NUM_GAMEPAD_AXES \ - && controls[x][z] >= KEY_INV_AXES && controls[x][z] < KEY_INV_AXES + NUM_GAMEPAD_AXES) + if (jdeadzone >= JOYAXISRANGE && adjustedMagnitude >= JOYAXISRANGE) // If the deadzone and magnitude are both 100%... + return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0 + else if (adjustedMagnitude > jdeadzone) // Otherwise, calculate how much the magnitude exceeds the deadzone + { + adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE); - if (CHECK_RANGE(gc1, 0, 1) || CHECK_RANGE(gc2, 0, 1)) - return false; - if (CHECK_RANGE(gc1, 1, 0) || CHECK_RANGE(gc2, 1, 0)) - return false; + adjustedMagnitude -= jdeadzone; -#undef CHECK_RANGE + deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone); + } - return true; + return deadzoneAppliedValue; } -typedef struct -{ - INT32 xaxis, yaxis; -} joystickvector2_t; - // Get the actual sensible radial value for a joystick axis when accounting for a deadzone -static void G_HandleAxisDeadZone(UINT8 playernum, joystickvector2_t *joystickvector) +static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvector) { - if (!gamepads[playernum].digital) + INT32 gamepadStyle = Joystick.bGamepadStyle; + fixed_t deadZone = cv_deadzone.value; + + if (splitnum == 1) { - const UINT16 deadZone = G_GetGamepadDeadZone(playernum); + gamepadStyle = Joystick2.bGamepadStyle; + deadZone = cv_deadzone2.value; + } + // When gamepadstyle is "true" the values are just -1, 0, or 1. This is done in the interface code. + if (!gamepadStyle) + { // Get the total magnitude of the 2 axes INT32 magnitude = (joystickvector->xaxis * joystickvector->xaxis) + (joystickvector->yaxis * joystickvector->yaxis); INT32 normalisedXAxis; @@ -1039,18 +1029,18 @@ static void G_HandleAxisDeadZone(UINT8 playernum, joystickvector2_t *joystickvec normalisedYAxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE; // Apply the deadzone to the magnitude to give a correct value between 0 and JOYAXISRANGE - normalisedMagnitude = G_BasicDeadZoneCalculation(abs(magnitude), deadZone); + normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude, deadZone); // Apply the deadzone to the xy axes joystickvector->xaxis = (normalisedXAxis * normalisedMagnitude) / JOYAXISRANGE; joystickvector->yaxis = (normalisedYAxis * normalisedMagnitude) / JOYAXISRANGE; - } - // Cap the values so they don't go above the correct maximum - joystickvector->xaxis = min(joystickvector->xaxis, JOYAXISRANGE); - joystickvector->xaxis = max(joystickvector->xaxis, -JOYAXISRANGE - 1); - joystickvector->yaxis = min(joystickvector->yaxis, JOYAXISRANGE); - joystickvector->yaxis = max(joystickvector->yaxis, -JOYAXISRANGE - 1); + // Cap the values so they don't go above the correct maximum + joystickvector->xaxis = min(joystickvector->xaxis, JOYAXISRANGE); + joystickvector->xaxis = max(joystickvector->xaxis, -JOYAXISRANGE); + joystickvector->yaxis = min(joystickvector->yaxis, JOYAXISRANGE); + joystickvector->yaxis = max(joystickvector->yaxis, -JOYAXISRANGE); + } } // @@ -1073,8 +1063,6 @@ boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object? void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { - UINT8 forplayer = ssplayer - 1; - boolean forcestrafe = false; boolean forcefullinput = false; INT32 tspeed, forward, side, axis, strafeaxis, moveaxis, turnaxis, lookaxis, i; @@ -1083,17 +1071,15 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) const INT32 speed = 1; // these ones used for multiple conditions - boolean turnleft, turnright, strafelkey, straferkey, movefkey, movebkey, mouseaiming; - boolean analogaxismove, digitalaxismove, thisjoyaiming; + boolean turnleft, turnright, strafelkey, straferkey, movefkey, movebkey, mouseaiming, analogjoystickmove, gamepadjoystickmove, thisjoyaiming; boolean strafeisturn; // Simple controls only player_t *player = &players[ssplayer == 2 ? secondarydisplayplayer : consoleplayer]; camera_t *thiscam = ((ssplayer == 1 || player->bot == BOT_2PHUMAN) ? &camera : &camera2); angle_t *myangle = (ssplayer == 1 ? &localangle : &localangle2); INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2); - gamepad_t *gamepad = &gamepads[forplayer]; angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0; - INT32 chasecam, chasefreelook, alwaysfreelook, usegamepad, invertmouse, turnmultiplier, mousemove; + INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove; controlstyle_e controlstyle = G_ControlStyle(ssplayer); INT32 mdx, mdy, mldy; @@ -1107,11 +1093,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) static fixed_t tta_factor[2] = {FRACUNIT, FRACUNIT}; // disables turn-to-angle when manually turning camera until movement happens boolean centerviewdown = false; + UINT8 forplayer = ssplayer-1; + if (ssplayer == 1) { chasecam = cv_chasecam.value; chasefreelook = cv_chasefreelook.value; alwaysfreelook = cv_alwaysfreelook.value; + usejoystick = cv_usejoystick.value; invertmouse = cv_invertmouse.value; turnmultiplier = cv_cam_turnmultiplier.value; mousemove = cv_mousemove.value; @@ -1125,6 +1114,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) chasecam = cv_chasecam2.value; chasefreelook = cv_chasefreelook2.value; alwaysfreelook = cv_alwaysfreelook2.value; + usejoystick = cv_usejoystick2.value; invertmouse = cv_invertmouse2.value; turnmultiplier = cv_cam2_turnmultiplier.value; mousemove = cv_mousemove2.value; @@ -1134,8 +1124,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver } - usegamepad = cv_usegamepad[forplayer].value; - if (menuactive || CON_Ready() || chat_on) mdx = mdy = mldy = 0; @@ -1154,14 +1142,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) return; } - // Axes for turning or strafing are ignored here - turnright = G_CheckDigitalPlayerInput(forplayer, GC_TURNRIGHT); - turnleft = G_CheckDigitalPlayerInput(forplayer, GC_TURNLEFT); + turnright = PLAYERINPUTDOWN(ssplayer, GC_TURNRIGHT); + turnleft = PLAYERINPUTDOWN(ssplayer, GC_TURNLEFT); - straferkey = G_CheckDigitalPlayerInput(forplayer, GC_STRAFERIGHT); - strafelkey = G_CheckDigitalPlayerInput(forplayer, GC_STRAFELEFT); - movefkey = G_CheckDigitalPlayerInput(forplayer, GC_FORWARD); - movebkey = G_CheckDigitalPlayerInput(forplayer, GC_BACKWARD); + straferkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFERIGHT); + strafelkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFELEFT); + movefkey = PLAYERINPUTDOWN(ssplayer, GC_FORWARD); + movebkey = PLAYERINPUTDOWN(ssplayer, GC_BACKWARD); if (strafeisturn) { @@ -1170,10 +1157,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) straferkey = strafelkey = false; } - mouseaiming = (G_PlayerInputDown(forplayer, GC_MOUSEAIMING)) ^ + mouseaiming = (PLAYERINPUTDOWN(ssplayer, GC_MOUSEAIMING)) ^ ((chasecam && !player->spectator) ? chasefreelook : alwaysfreelook); - analogaxismove = usegamepad && !gamepad->digital; - digitalaxismove = usegamepad && gamepad->digital; + analogjoystickmove = usejoystick && !Joystick.bGamepadStyle; + gamepadjoystickmove = usejoystick && Joystick.bGamepadStyle; thisjoyaiming = (chasecam && !player->spectator) ? chasefreelook : alwaysfreelook; @@ -1182,38 +1169,19 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) *myaiming = 0; joyaiming[forplayer] = thisjoyaiming; - turnaxis = G_JoyAxis(forplayer, JA_TURN); + turnaxis = PlayerJoyAxis(ssplayer, JA_TURN); if (strafeisturn) - turnaxis += G_JoyAxis(forplayer, JA_STRAFE); - lookaxis = G_JoyAxis(forplayer, JA_LOOK); - - if (usegamepad) - { - turnaxis -= GetAnalogInput(forplayer, GC_TURNLEFT); - turnaxis += GetAnalogInput(forplayer, GC_TURNRIGHT); - - if (strafeisturn) - { - turnaxis -= GetAnalogInput(forplayer, GC_STRAFELEFT); - turnaxis += GetAnalogInput(forplayer, GC_STRAFERIGHT); - } - - lookaxis += GetAnalogInput(forplayer, GC_LOOKUP); - lookaxis -= GetAnalogInput(forplayer, GC_LOOKDOWN); - } - - // Handle deadzones + turnaxis += PlayerJoyAxis(ssplayer, JA_STRAFE); + lookaxis = PlayerJoyAxis(ssplayer, JA_LOOK); lookjoystickvector.xaxis = turnaxis; lookjoystickvector.yaxis = lookaxis; G_HandleAxisDeadZone(forplayer, &lookjoystickvector); - // Do digital axis turning - if (digitalaxismove && lookjoystickvector.xaxis != 0) + if (gamepadjoystickmove && lookjoystickvector.xaxis != 0) { turnright = turnright || (lookjoystickvector.xaxis > 0); turnleft = turnleft || (lookjoystickvector.xaxis < 0); } - forward = side = 0; // use two stage accelerative turning @@ -1252,10 +1220,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (turnleft) side -= sidemove[speed]; - if (analogaxismove && lookjoystickvector.xaxis != 0) + if (analogjoystickmove && lookjoystickvector.xaxis != 0) { - // JOYAXISRANGE is supposed to be 32767 (divide by 32768) - side += ((lookjoystickvector.xaxis * sidemove[1]) >> 15); + // JOYAXISRANGE is supposed to be 1023 (divide by 1024) + side += ((lookjoystickvector.xaxis * sidemove[1]) >> 10); } } else if (controlstyle == CS_LMAOGALOG) // Analog @@ -1273,69 +1241,47 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else if (turnleft) cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * turnmultiplier)>>FRACBITS)); - if (analogaxismove && lookjoystickvector.xaxis != 0) + if (analogjoystickmove && lookjoystickvector.xaxis != 0) { - // JOYAXISRANGE should be 32767 (divide by 32768) - cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 15) * turnmultiplier)>>FRACBITS)); // ANALOG! + // JOYAXISRANGE should be 1023 (divide by 1024) + cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * turnmultiplier)>>FRACBITS)); // ANALOG! } if (turnright || turnleft || abs(cmd->angleturn) > angleturn[2]) tta_factor[forplayer] = 0; // suspend turn to angle } - // Strafing axes (moving left and right) - if (strafeisturn) - strafeaxis = 0; - else - { - strafeaxis = G_JoyAxis(forplayer, JA_STRAFE); - - if (usegamepad && CheckAxesUsable(forplayer, GC_STRAFELEFT, GC_STRAFERIGHT)) - { - strafeaxis -= GetAnalogInput(forplayer, GC_STRAFELEFT); - strafeaxis += GetAnalogInput(forplayer, GC_STRAFERIGHT); - } - } - - // Moving axes (moving forwards and backwards) - moveaxis = G_JoyAxis(forplayer, JA_MOVE); - if (usegamepad && CheckAxesUsable(forplayer, GC_FORWARD, GC_BACKWARD)) - { - moveaxis -= GetAnalogInput(forplayer, GC_FORWARD); - moveaxis += GetAnalogInput(forplayer, GC_BACKWARD); - } - + strafeaxis = strafeisturn ? 0 : PlayerJoyAxis(ssplayer, JA_STRAFE); + moveaxis = PlayerJoyAxis(ssplayer, JA_MOVE); movejoystickvector.xaxis = strafeaxis; movejoystickvector.yaxis = moveaxis; G_HandleAxisDeadZone(forplayer, &movejoystickvector); - if (digitalaxismove && movejoystickvector.xaxis != 0) + if (gamepadjoystickmove && movejoystickvector.xaxis != 0) { - // Do digital axis movement if (movejoystickvector.xaxis > 0) side += sidemove[speed]; else if (movejoystickvector.xaxis < 0) side -= sidemove[speed]; } - else if (analogaxismove && movejoystickvector.xaxis != 0) + else if (analogjoystickmove && movejoystickvector.xaxis != 0) { - // JOYAXISRANGE is supposed to be 32767 (divide by 32768) - side += ((movejoystickvector.xaxis * sidemove[1]) >> 15); + // JOYAXISRANGE is supposed to be 1023 (divide by 1024) + side += ((movejoystickvector.xaxis * sidemove[1]) >> 10); } // forward with key or button - // also handles digital axis movement - if (movefkey || (digitalaxismove && movejoystickvector.yaxis < 0) + if (movefkey || (gamepadjoystickmove && movejoystickvector.yaxis < 0) || ((player->powers[pw_carry] == CR_NIGHTSMODE) - && (G_CheckDigitalPlayerInput(forplayer, GC_LOOKUP) || (digitalaxismove && lookjoystickvector.yaxis > 0)))) + && (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0)))) forward = forwardmove[speed]; - if (movebkey || (digitalaxismove && movejoystickvector.yaxis > 0) + if (movebkey || (gamepadjoystickmove && movejoystickvector.yaxis > 0) || ((player->powers[pw_carry] == CR_NIGHTSMODE) - && (G_CheckDigitalPlayerInput(forplayer, GC_LOOKDOWN) || (digitalaxismove && lookjoystickvector.yaxis < 0)))) + && (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0)))) forward -= forwardmove[speed]; - if (analogaxismove && movejoystickvector.yaxis != 0) - forward -= ((movejoystickvector.yaxis * forwardmove[1]) >> 15); // ANALOG! + if (analogjoystickmove && movejoystickvector.yaxis != 0) + forward -= ((movejoystickvector.yaxis * forwardmove[1]) >> 10); // ANALOG! // some people strafe left & right with mouse buttons // those people are weird @@ -1344,54 +1290,53 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (strafelkey) side -= sidemove[speed]; - if (G_PlayerInputDown(forplayer, GC_WEAPONNEXT)) + if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONNEXT)) cmd->buttons |= BT_WEAPONNEXT; // Next Weapon - if (G_PlayerInputDown(forplayer, GC_WEAPONPREV)) + if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONPREV)) cmd->buttons |= BT_WEAPONPREV; // Previous Weapon #if NUM_WEAPONS > 10 -#error "Add extra inputs to g_input.h/gamecontrols_e" +"Add extra inputs to g_input.h/gamecontrols_e" #endif - //use the four avaliable bits to determine the weapon. cmd->buttons &= ~BT_WEAPONMASK; for (i = 0; i < NUM_WEAPONS; ++i) - if (G_PlayerInputDown(forplayer, GC_WEPSLOT1 + i)) + if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i)) { cmd->buttons |= (UINT16)(i + 1); break; } // fire with any button/key - axis = G_JoyAxis(forplayer, JA_FIRE); - if (G_PlayerInputDown(forplayer, GC_FIRE) || (usegamepad && axis > 0)) + axis = PlayerJoyAxis(ssplayer, JA_FIRE); + if (PLAYERINPUTDOWN(ssplayer, GC_FIRE) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; // fire normal with any button/key - axis = G_JoyAxis(forplayer, JA_FIRENORMAL); - if (G_PlayerInputDown(forplayer, GC_FIRENORMAL) || (usegamepad && axis > 0)) + axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL); + if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0)) cmd->buttons |= BT_FIRENORMAL; - if (G_PlayerInputDown(forplayer, GC_TOSSFLAG)) + if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG)) cmd->buttons |= BT_TOSSFLAG; // Lua scriptable buttons - if (G_PlayerInputDown(forplayer, GC_CUSTOM1)) + if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1)) cmd->buttons |= BT_CUSTOM1; - if (G_PlayerInputDown(forplayer, GC_CUSTOM2)) + if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM2)) cmd->buttons |= BT_CUSTOM2; - if (G_PlayerInputDown(forplayer, GC_CUSTOM3)) + if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM3)) cmd->buttons |= BT_CUSTOM3; - // spin with any button/key - axis = G_JoyAxis(forplayer, JA_SPIN); - if (G_PlayerInputDown(forplayer, GC_SPIN) || (usegamepad && axis > 0)) + // use with any button/key + axis = PlayerJoyAxis(ssplayer, JA_SPIN); + if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0)) cmd->buttons |= BT_SPIN; // Centerview can be a toggle in simple mode! { static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior - boolean down = G_PlayerInputDown(forplayer, GC_CENTERVIEW); + boolean down = PLAYERINPUTDOWN(ssplayer, GC_CENTERVIEW); if (!(controlstyle == CS_SIMPLE && cv_cam_centertoggle[forplayer].value)) centerviewdown = down; @@ -1490,7 +1435,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (ticcmd_centerviewdown[forplayer] && controlstyle == CS_SIMPLE) controlstyle = CS_LEGACY; - if (G_PlayerInputDown(forplayer, GC_CAMRESET)) + if (PLAYERINPUTDOWN(ssplayer, GC_CAMRESET)) { if (thiscam->chase && !resetdown[forplayer]) P_ResetCamera(&players[ssplayer == 1 ? displayplayer : secondarydisplayplayer], thiscam); @@ -1500,9 +1445,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else resetdown[forplayer] = false; + // jump button - axis = G_JoyAxis(forplayer, JA_JUMP); - if (G_PlayerInputDown(forplayer, GC_JUMP) || (usegamepad && axis > 0)) + axis = PlayerJoyAxis(ssplayer, JA_JUMP); + if (PLAYERINPUTDOWN(ssplayer, GC_JUMP) || (usejoystick && axis > 0)) cmd->buttons |= BT_JUMP; // player aiming shit, ahhhh... @@ -1512,6 +1458,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) (player->mo && (player->mo->eflags & MFE_VERTICALFLIP) && (!thiscam->chase || player->pflags & PF_FLIPCAM)) //because chasecam's not inverted ? -1 : 1; // set to -1 or 1 to multiply + INT32 configlookaxis = ssplayer == 1 ? cv_lookaxis.value : cv_lookaxis2.value; // mouse look stuff (mouse look is not the same as mouse aim) if (mouseaiming) @@ -1522,21 +1469,21 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) *myaiming += (mldy<<19)*player_invert*screen_invert; } - if (joyaiming[forplayer] && lookjoystickvector.yaxis != 0) - *myaiming += (lookjoystickvector.yaxis<<11) * screen_invert; + if (analogjoystickmove && joyaiming[forplayer] && lookjoystickvector.yaxis != 0 && configlookaxis != 0) + *myaiming += (lookjoystickvector.yaxis<<16) * screen_invert; // spring back if not using keyboard neither mouselookin' - if (!keyboard_look[forplayer] && !joyaiming[forplayer] && !mouseaiming) + if (!keyboard_look[forplayer] && configlookaxis == 0 && !joyaiming[forplayer] && !mouseaiming) *myaiming = 0; if (!(player->powers[pw_carry] == CR_NIGHTSMODE)) { - if (G_CheckDigitalPlayerInput(forplayer, GC_LOOKUP) || (digitalaxismove && lookjoystickvector.yaxis < 0)) + if (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0)) { *myaiming += KB_LOOKSPEED * screen_invert; keyboard_look[forplayer] = true; } - else if (G_CheckDigitalPlayerInput(forplayer, GC_LOOKDOWN) || (digitalaxismove && lookjoystickvector.yaxis > 0)) + else if (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0)) { *myaiming -= KB_LOOKSPEED * screen_invert; keyboard_look[forplayer] = true; @@ -1769,57 +1716,6 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) return dest; } -static player_t *G_GetInputPlayer(UINT8 which) -{ - if (which == 0) - return &players[displayplayer]; - else if (which == 1) - { - if (splitscreen) - return &players[secondarydisplayplayer]; - else if (playeringame[1] && players[1].bot == BOT_2PHUMAN) - return &players[1]; - } - - return NULL; -} - -// Returns a player's gamepad index, even if it's disabled -// Gamepad indexes correspond to the local player index. -INT16 G_GetGamepadForPlayer(player_t *player) -{ - for (UINT8 i = 0; i < 2; i++) - { - if (player == G_GetInputPlayer(i)) - return i; - } - - return -1; -} - -// Gets the user-set gamepad device for a specific player -INT32 G_GetGamepadDeviceIndex(INT32 player) -{ -#ifdef GAMEPAD_HOTPLUG - if (atoi(cv_usegamepad[player].string) > I_NumGamepads()) - return atoi(cv_usegamepad[player].string); - else -#endif - return cv_usegamepad[player].value; -} - -void G_OnGamepadDisconnect(UINT8 which) -{ - if (!cv_gamepad_autopause.value) - return; - - if (gamestate != GS_LEVEL || paused || netgame || splitscreen) - return; - - if (which == 0 || (which == 1 && playeringame[1] && players[1].bot == BOT_2PHUMAN)) - COM_ImmedExecute("pause"); -} - // User has designated that they want // analog ON, so tell the game to stop // fudging with it. @@ -1891,25 +1787,6 @@ static void AutoBrake2_OnChange(void) SendWeaponPref2(); } -static void G_ResetInputs(void) -{ - memset(gamekeydown, 0, sizeof (gamekeydown)); - - for (UINT8 i = 0; i < NUM_GAMEPADS; i++) - { - for (UINT8 j = 0; j < NUM_GAMEPAD_BUTTONS; j++) - gamepads[i].buttons[j] = 0; - - for (UINT8 j = 0; j < NUM_GAMEPAD_AXES; j++) - gamepads[i].axes[j] = 0; - } - - G_SetMouseDeltas(0, 0, 1); - G_SetMouseDeltas(0, 0, 2); - - P_StopRumble(NULL); -} - // // G_DoLoadLevel // @@ -1978,7 +1855,14 @@ void G_DoLoadLevel(boolean resetplayer) P_ResetCamera(&players[secondarydisplayplayer], &camera2); // clear cmd building stuff - G_ResetInputs(); + memset(gamekeydown, 0, sizeof (gamekeydown)); + for (i = 0;i < JOYAXISSET; i++) + { + joyxmove[i] = joyymove[i] = 0; + joy2xmove[i] = joy2ymove[i] = 0; + } + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -2160,14 +2044,11 @@ static boolean ViewpointSwitchResponder(event_t *ev) // boolean G_Responder(event_t *ev) { - INT32 evtype = ev->type; - INT32 key = G_RemapGamepadEvent(ev, &evtype); - // any other key pops up menu if in demos if (gameaction == ga_nothing && !singledemo && ((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN)) { - if (evtype == ev_keydown && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE)) + if (ev->type == ev_keydown && ev->key != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE)) { M_StartControlPanel(); return true; @@ -2192,7 +2073,7 @@ boolean G_Responder(event_t *ev) return true; // chat ate the event if (AM_Responder(ev)) return true; // automap ate it - // map the event (key/mouse/gamepad) to a gamecontrol + // map the event (key/mouse/joy) to a gamecontrol } // Intro else if (gamestate == GS_INTRO) @@ -2247,16 +2128,16 @@ boolean G_Responder(event_t *ev) // update keys current state G_MapEventsToControls(ev); - switch (evtype) + switch (ev->type) { case ev_keydown: - if (key == gamecontrol[GC_PAUSE][0] - || key == gamecontrol[GC_PAUSE][1] - || key == KEY_PAUSE) + if (ev->key == gamecontrol[GC_PAUSE][0] + || ev->key == gamecontrol[GC_PAUSE][1] + || ev->key == KEY_PAUSE) { if (modeattacking && !demoplayback && (gamestate == GS_LEVEL)) { - pausebreakkey = (key == KEY_PAUSE); + pausebreakkey = (ev->key == KEY_PAUSE); if (menuactive || pausedelay < 0 || leveltime < 2) return true; @@ -2281,8 +2162,8 @@ boolean G_Responder(event_t *ev) } } } - if (key == gamecontrol[GC_CAMTOGGLE][0] - || key == gamecontrol[GC_CAMTOGGLE][1]) + if (ev->key == gamecontrol[GC_CAMTOGGLE][0] + || ev->key == gamecontrol[GC_CAMTOGGLE][1]) { if (!camtoggledelay) { @@ -2290,8 +2171,8 @@ boolean G_Responder(event_t *ev) CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1); } } - if (key == gamecontrolbis[GC_CAMTOGGLE][0] - || key == gamecontrolbis[GC_CAMTOGGLE][1]) + if (ev->key == gamecontrolbis[GC_CAMTOGGLE][0] + || ev->key == gamecontrolbis[GC_CAMTOGGLE][1]) { if (!camtoggledelay2) { @@ -2304,9 +2185,15 @@ boolean G_Responder(event_t *ev) case ev_keyup: return false; // always let key up events filter down - case ev_mouse: // eat events - case ev_gamepad_axis: - return true; + case ev_mouse: + return true; // eat events + + case ev_joystick: + return true; // eat events + + case ev_joystick2: + return true; // eat events + default: break; @@ -3300,7 +3187,14 @@ void G_DoReborn(INT32 playernum) P_ResetCamera(&players[secondarydisplayplayer], &camera2); // clear cmd building stuff - G_ResetInputs(); + memset(gamekeydown, 0, sizeof (gamekeydown)); + for (i = 0; i < JOYAXISSET; i++) + { + joyxmove[i] = joyymove[i] = 0; + joy2xmove[i] = joy2ymove[i] = 0; + } + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -4708,7 +4602,11 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) } save_p += VERSIONSIZE; - P_StopRumble(NULL); +// if (demoplayback) // reset game engine +// G_StopDemo(); + +// paused = false; +// automapactive = false; // dearchive all the modifications if (!P_LoadGame(mapoverride)) @@ -4971,7 +4869,6 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean { INT32 i; - P_StopRumble(NULL); Y_CleanupScreenBuffer(); if (paused) diff --git a/src/g_game.h b/src/g_game.h index 6c24054a07..dca043f2e0 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -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); diff --git a/src/g_input.c b/src/g_input.c index 465db0316b..79bd2a4a29 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -8,14 +8,12 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file g_input.c -/// \brief handle mouse/keyboard/gamepad inputs, +/// \brief handle mouse/keyboard/joystick inputs, /// maps inputs to game controls (forward, spin, jump...) #include "doomdef.h" #include "doomstat.h" -#include "g_game.h" #include "g_input.h" -#include "i_gamepad.h" #include "keys.h" #include "hu_stuff.h" // need HUFONT start & end #include "d_net.h" @@ -36,7 +34,8 @@ consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecont mouse_t mouse; mouse_t mouse2; -gamepad_t gamepads[NUM_GAMEPADS]; +// joystick values are repeated +INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET]; // current state of the keys: true if pushed UINT8 gamekeydown[NUMINPUTS]; @@ -87,114 +86,26 @@ const INT32 gcl_jump_spin[num_gcl_jump_spin] = { GC_JUMP, GC_SPIN }; -static boolean CheckInputDown(UINT8 which, gamecontrols_e gc, boolean checkaxes) -{ - INT32 (*controls)[2] = which == 0 ? gamecontrol : gamecontrolbis; - - for (unsigned i = 0; i < 2; i++) - { - INT32 key = controls[gc][i]; - - if (key >= KEY_GAMEPAD && key < KEY_AXES) - { - if (gamepads[which].buttons[key - KEY_GAMEPAD]) - return true; - } - else if (checkaxes && (key >= KEY_AXES && key < KEY_INV_AXES + NUM_GAMEPAD_AXES)) - { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(which); - const INT16 value = G_GetGamepadAxisValue(which, (key - KEY_AXES) % NUM_GAMEPAD_AXES); - - if (abs(value) > jdeadzone) - return true; - } - else if (gamekeydown[key]) - return true; - } - - return false; -} - -boolean G_PlayerInputDown(UINT8 which, gamecontrols_e gc) -{ - return CheckInputDown(which, gc, true); -} - -boolean G_CheckDigitalPlayerInput(UINT8 which, gamecontrols_e gc) -{ - return CheckInputDown(which, gc, false); -} - -SINT8 G_PlayerInputIsAnalog(UINT8 which, gamecontrols_e gc, UINT8 settings) -{ - INT32 (*controls)[2] = which == 0 ? gamecontrol : gamecontrolbis; - INT32 key = controls[gc][settings]; - - if (key >= KEY_AXES && key < KEY_AXES + NUM_GAMEPAD_AXES) - return 1; - else if (key >= KEY_INV_AXES && key < KEY_INV_AXES + NUM_GAMEPAD_AXES) - return -1; - - return 0; -} - -INT16 G_GetAnalogPlayerInput(UINT8 which, gamecontrols_e gc, UINT8 settings) -{ - INT32 (*controls)[2] = which == 0 ? gamecontrol : gamecontrolbis; - INT32 key = controls[gc][settings]; - - if (key >= KEY_AXES && key < KEY_INV_AXES + NUM_GAMEPAD_AXES) - return G_GetGamepadAxisValue(which, (key - KEY_AXES) % NUM_GAMEPAD_AXES); - - return 0; -} - typedef struct { UINT8 time; UINT8 state; UINT8 clicks; } dclick_t; - static dclick_t mousedclicks[MOUSEBUTTONS]; +static dclick_t joydclicks[JOYBUTTONS + JOYHATS*4]; static dclick_t mouse2dclicks[MOUSEBUTTONS]; +static dclick_t joy2dclicks[JOYBUTTONS + JOYHATS*4]; -// -// General double-click detection routine for any kind of input. -// -static UINT8 G_CheckDoubleClick(UINT8 state, dclick_t *dt) -{ - if (state != dt->state && dt->time > 1) - { - dt->state = state; - if (state) - dt->clicks++; - if (dt->clicks == 2) - { - dt->clicks = 0; - return true; - } - else - dt->time = 0; - } - else - { - dt->time++; - if (dt->time > 20) - { - dt->clicks = 0; - dt->state = 0; - } - } - return false; -} +// protos +static UINT8 G_CheckDoubleClick(UINT8 state, dclick_t *dt); // // Remaps the inputs to game controls. // // A game control can be triggered by one or more keys/buttons. // -// Each key/mouse button/gamepad button triggers ONLY ONE game control. +// Each key/mousebutton/joybutton triggers ONLY ONE game control. // void G_MapEventsToControls(event_t *ev) { @@ -208,7 +119,9 @@ void G_MapEventsToControls(event_t *ev) gamekeydown[ev->key] = 1; #ifdef PARANOIA else + { CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->key); + } #endif break; @@ -218,31 +131,36 @@ void G_MapEventsToControls(event_t *ev) gamekeydown[ev->key] = 0; #ifdef PARANOIA else + { CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->key); + } #endif break; - case ev_gamepad_down: - case ev_gamepad_up: -#ifdef PARANOIA - if (ev->which < NUM_GAMEPADS) -#endif - gamepads[ev->which].buttons[ev->key] = ev->type == ev_gamepad_down ? 1 : 0; + case ev_mouse: // buttons are virtual keys + mouse.rdx = ev->x; + mouse.rdy = ev->y; break; - case ev_gamepad_axis: -#ifdef PARANOIA - if (ev->which < NUM_GAMEPADS) -#endif - gamepads[ev->which].axes[ev->key] = ev->x; + case ev_joystick: // buttons are virtual keys + i = ev->key; + if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) + break; + if (ev->x != INT32_MAX) joyxmove[i] = ev->x; + if (ev->y != INT32_MAX) joyymove[i] = ev->y; break; - case ev_mouse: - mouse.rdx = ev->x; - mouse.rdy = ev->y; + case ev_joystick2: // buttons are virtual keys + i = ev->key; + if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) + break; + if (ev->x != INT32_MAX) joy2xmove[i] = ev->x; + if (ev->y != INT32_MAX) joy2ymove[i] = ev->y; break; - case ev_mouse2: + case ev_mouse2: // buttons are virtual keys + if (menuactive || CON_Ready() || chat_on) + break; mouse2.rdx = ev->x; mouse2.rdy = ev->y; break; @@ -251,579 +169,62 @@ void G_MapEventsToControls(event_t *ev) break; } - // ALWAYS check for mouse double-clicks even if there were no such events + // ALWAYS check for mouse & joystick double-clicks even if no mouse event for (i = 0; i < MOUSEBUTTONS; i++) { flag = G_CheckDoubleClick(gamekeydown[KEY_MOUSE1+i], &mousedclicks[i]); gamekeydown[KEY_DBLMOUSE1+i] = flag; } - for (i = 0; i < MOUSEBUTTONS; i++) + for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++) { - flag = G_CheckDoubleClick(gamekeydown[KEY_2MOUSE1+i], &mouse2dclicks[i]); - gamekeydown[KEY_DBL2MOUSE1+i] = flag; - } -} - -const char *const gamepad_button_names[NUM_GAMEPAD_BUTTONS + 1] = { - "a", - "b", - "x", - "y", - "back", - "guide", - "start", - "left-stick", - "right-stick", - "left-shoulder", - "right-shoulder", - "dpad-up", - "dpad-down", - "dpad-left", - "dpad-right", - "misc1", - "paddle1", - "paddle2", - "paddle3", - "paddle4", - "touchpad", - NULL}; - -const char *const gamepad_axis_names[NUM_GAMEPAD_AXES + 1] = { - "left-x", - "left-y", - "right-x", - "right-y", - "trigger-left", - "trigger-right", - NULL}; - -boolean G_GamepadTypeIsXbox(gamepadtype_e type) -{ - switch (type) - { - case GAMEPAD_TYPE_XBOX360: - case GAMEPAD_TYPE_XBOXONE: - case GAMEPAD_TYPE_XBOX_SERIES_XS: - case GAMEPAD_TYPE_XBOX_ELITE: - return true; - default: - return false; - } -} - -boolean G_GamepadTypeIsPlayStation(gamepadtype_e type) -{ - switch (type) - { - case GAMEPAD_TYPE_PS3: - case GAMEPAD_TYPE_PS4: - case GAMEPAD_TYPE_PS5: - return true; - default: - return false; - } -} - -boolean G_GamepadTypeIsNintendoSwitch(gamepadtype_e type) -{ - switch (type) - { - case GAMEPAD_TYPE_NINTENDO_SWITCH_PRO: - case GAMEPAD_TYPE_NINTENDO_SWITCH_JOY_CON_GRIP: - return true; - default: - return G_GamepadTypeIsJoyCon(type); - } -} - -boolean G_GamepadTypeIsJoyCon(gamepadtype_e type) -{ - switch (type) - { - case GAMEPAD_TYPE_NINTENDO_SWITCH_JOY_CON_LEFT: - case GAMEPAD_TYPE_NINTENDO_SWITCH_JOY_CON_RIGHT: - return true; - default: - return false; + flag = G_CheckDoubleClick(gamekeydown[KEY_JOY1+i], &joydclicks[i]); + gamekeydown[KEY_DBLJOY1+i] = flag; } -} - -boolean G_RumbleSupported(UINT8 which) -{ - if (!I_RumbleSupported() || which >= NUM_GAMEPADS) - return 0; - - return I_GetGamepadRumbleSupported(which); -} - -boolean G_RumbleGamepad(UINT8 which, fixed_t large_magnitude, fixed_t small_magnitude, tic_t duration) -{ - haptic_t effect; - - if (!G_RumbleSupported(which)) - return false; - effect.large_magnitude = large_magnitude; - effect.small_magnitude = small_magnitude; - effect.duration = duration; - - return I_RumbleGamepad(which, &effect); -} - -void G_StopGamepadRumble(UINT8 which) -{ - if (G_RumbleSupported(which)) - I_StopGamepadRumble(which); -} - -fixed_t G_GetLargeMotorFreq(UINT8 which) -{ - if (!G_RumbleSupported(which) || which >= NUM_GAMEPADS) - return 0; - - gamepad_t *gamepad = &gamepads[which]; - return gamepad->rumble.data.large_magnitude; -} - -fixed_t G_GetSmallMotorFreq(UINT8 which) -{ - if (!G_RumbleSupported(which) || which >= NUM_GAMEPADS) - return 0; - - gamepad_t *gamepad = &gamepads[which]; - return gamepad->rumble.data.small_magnitude; -} - -boolean G_GetGamepadRumblePaused(UINT8 which) -{ - return I_GetGamepadRumblePaused(which); -} - -boolean G_SetLargeMotorFreq(UINT8 which, fixed_t freq) -{ - return I_SetGamepadLargeMotorFreq(which, freq); -} - -boolean G_SetSmallMotorFreq(UINT8 which, fixed_t freq) -{ - return I_SetGamepadSmallMotorFreq(which, freq); -} - -void G_SetGamepadRumblePaused(UINT8 which, boolean pause) -{ - if (G_RumbleSupported(which)) - I_SetGamepadRumblePaused(which, pause); -} - -// Obtains the value of an axis, and makes it digital if needed -INT16 G_GamepadAxisEventValue(UINT8 which, INT16 value) -{ - gamepad_t *gamepad = &gamepads[which]; - - if (gamepad->digital) - { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(which); - - if (value < -jdeadzone) - value = -JOYAXISRANGE - 1; - else if (value > jdeadzone) - value = JOYAXISRANGE; - else - value = 0; - } - - return value; -} - -INT16 G_GetGamepadAxisValue(UINT8 which, gamepad_axis_e axis) -{ - gamepad_t *gamepad = &gamepads[which]; - - if (axis >= NUM_GAMEPAD_AXES) - return 0; - - return G_GamepadAxisEventValue(which, gamepad->axes[axis]); -} - -fixed_t G_GetAdjustedGamepadAxis(UINT8 which, gamepad_axis_e axis, boolean applyDeadzone) -{ - gamepad_t *gamepad = &gamepads[which]; - - if (axis >= NUM_GAMEPAD_AXES) - return 0; - - INT32 value = gamepad->axes[axis]; - - if (applyDeadzone && gamepad->digital) - { - INT16 deadzone = G_GetGamepadDigitalDeadZone(which); - - if (value < -deadzone) - value = -JOYAXISRANGE; - else if (value > deadzone) - value = JOYAXISRANGE; - else - value = 0; - } - else if (applyDeadzone) - { - INT32 sign = value < 0 ? -1 : 1; - INT16 deadzone = G_GetGamepadDeadZone(which); - INT32 magnitude = value * value; - INT32 nAxis = magnitude / JOYAXISRANGE; - INT32 nMagnitude = G_BasicDeadZoneCalculation(magnitude, deadzone); - - value = (nAxis * nMagnitude) / JOYAXISRANGE; - value = min(value * sign, JOYAXISRANGE); - value = max(value, -JOYAXISRANGE); - } - - return (value / 32767.0) * FRACUNIT; -} - -static UINT16 CalcGamepadDeadZone(fixed_t deadzone) -{ - INT32 value = (JOYAXISRANGE * deadzone) / FRACUNIT; - - if (value < 0) - value = 0; - else if (value > JOYAXISRANGE) - value = JOYAXISRANGE; - - return value; -} - -UINT16 G_GetGamepadDeadZone(UINT8 which) -{ - return CalcGamepadDeadZone(cv_deadzone[which].value); -} - -UINT16 G_GetGamepadDigitalDeadZone(UINT8 which) -{ - return CalcGamepadDeadZone(cv_digitaldeadzone[which].value); -} - -// Take a magnitude of two axes, and adjust it to take out the deadzone -// Will return a value between 0 and JOYAXISRANGE -INT32 G_BasicDeadZoneCalculation(INT32 magnitude, const UINT16 jdeadzone) -{ - INT32 deadzoneAppliedValue = 0; - INT32 adjustedMagnitude = abs(magnitude); - - if (jdeadzone >= JOYAXISRANGE && adjustedMagnitude >= JOYAXISRANGE) // If the deadzone and magnitude are both 100%... - return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0 - else if (adjustedMagnitude > jdeadzone) // Otherwise, calculate how much the magnitude exceeds the deadzone - { - adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE); - - adjustedMagnitude -= jdeadzone; - - deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone); - } - - return deadzoneAppliedValue; -} - -INT32 G_RemapGamepadEvent(event_t *event, INT32 *type) -{ - if (event->type == ev_gamepad_down) - { - *type = ev_keydown; - return KEY_GAMEPAD + event->key; - } - else if (event->type == ev_gamepad_up) - { - *type = ev_keyup; - return KEY_GAMEPAD + event->key; - } - else if (event->type == ev_gamepad_axis) - { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(event->which); - const INT16 value = G_GetGamepadAxisValue(event->which, event->key); - - if (value < -jdeadzone || value > jdeadzone) - *type = ev_keyup; - else - *type = ev_keydown; - - if (value < -jdeadzone) - return KEY_INV_AXES + event->key; - else - return KEY_AXES + event->key; - } - - return event->key; -} - -typedef struct -{ - const char *name; - const char *menu1; - const char *menu2; -} button_strings_t; - -#define DEF_NAME_BUTTON(str) {.name = str, .menu1 = str " Button", .menu2 = "the " str " Button"} -#define DEF_NAME_SIMPLE(str) {.name = str, .menu1 = NULL, .menu2 = "the " str} -#define DEF_NAME_DPAD(a, b) {.name = "D-Pad " a, .menu1 = "D-Pad " b, .menu2 = a} - -#define PARTIAL_DEF_START [GAMEPAD_BUTTON_A] = { NULL } -#define PARTIAL_DEF_END [NUM_GAMEPAD_BUTTONS - 1] = { NULL } - -static const char *GetStringFromButtonList(const button_strings_t *names, gamepad_button_e button, gamepad_string_e type) -{ - switch (type) + for (i = 0; i < MOUSEBUTTONS; i++) { - case GAMEPAD_STRING_DEFAULT: - return names[button].name; - case GAMEPAD_STRING_MENU1: - if (names[button].menu1) - return names[button].menu1; - else - return names[button].name; - case GAMEPAD_STRING_MENU2: - if (names[button].menu2) - return names[button].menu2; - else - return names[button].name; + flag = G_CheckDoubleClick(gamekeydown[KEY_2MOUSE1+i], &mouse2dclicks[i]); + gamekeydown[KEY_DBL2MOUSE1+i] = flag; } - return NULL; -} - -const char *G_GetGamepadButtonString(gamepadtype_e type, gamepad_button_e button, gamepad_string_e strtype) -{ - static const button_strings_t base_names[] = { - [GAMEPAD_BUTTON_A] = DEF_NAME_BUTTON("A"), - [GAMEPAD_BUTTON_B] = DEF_NAME_BUTTON("B"), - [GAMEPAD_BUTTON_X] = DEF_NAME_BUTTON("X"), - [GAMEPAD_BUTTON_Y] = DEF_NAME_BUTTON("Y"), - [GAMEPAD_BUTTON_BACK] = DEF_NAME_BUTTON("Back"), - [GAMEPAD_BUTTON_GUIDE] = DEF_NAME_BUTTON("Guide"), - [GAMEPAD_BUTTON_START] = DEF_NAME_BUTTON("Start"), - [GAMEPAD_BUTTON_LEFTSTICK] = DEF_NAME_SIMPLE("Left Stick"), - [GAMEPAD_BUTTON_RIGHTSTICK] = DEF_NAME_SIMPLE("Right Stick"), - [GAMEPAD_BUTTON_LEFTSHOULDER] = DEF_NAME_SIMPLE("Left Shoulder"), - [GAMEPAD_BUTTON_RIGHTSHOULDER] = DEF_NAME_SIMPLE("Right Shoulder"), - [GAMEPAD_BUTTON_DPAD_UP] = DEF_NAME_DPAD("Up", "\x1A"), - [GAMEPAD_BUTTON_DPAD_DOWN] = DEF_NAME_DPAD("Down", "\x1B"), - [GAMEPAD_BUTTON_DPAD_LEFT] = DEF_NAME_DPAD("Left", "\x1C"), - [GAMEPAD_BUTTON_DPAD_RIGHT] = DEF_NAME_DPAD("Right", "\x1D"), - [GAMEPAD_BUTTON_PADDLE1] = DEF_NAME_SIMPLE("Paddle 1"), - [GAMEPAD_BUTTON_PADDLE2] = DEF_NAME_SIMPLE("Paddle 2"), - [GAMEPAD_BUTTON_PADDLE3] = DEF_NAME_SIMPLE("Paddle 3"), - [GAMEPAD_BUTTON_PADDLE4] = DEF_NAME_SIMPLE("Paddle 4"), - [GAMEPAD_BUTTON_TOUCHPAD] = DEF_NAME_SIMPLE("Touchpad"), - - // This one's a bit weird - // Suffix the numbers in the event SDL adds more misc buttons - [GAMEPAD_BUTTON_MISC1] = { - .name = "Misc. Button", - .menu1 = "Gamepad Misc.", - .menu2 = "the Misc. Button" - }, - }; - - button_strings_t const *names = NULL; - - if (G_GamepadTypeIsXbox(type)) + for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++) { - #define BASE_XBOX_NAMES \ - [GAMEPAD_BUTTON_LEFTSHOULDER] = DEF_NAME_SIMPLE("Left Bumper"), \ - [GAMEPAD_BUTTON_RIGHTSHOULDER] = DEF_NAME_SIMPLE("Right Bumper") - - static const button_strings_t xbox_names[] = { PARTIAL_DEF_START, - BASE_XBOX_NAMES, - PARTIAL_DEF_END }; - - static const button_strings_t series_xs_names[] = { PARTIAL_DEF_START, - BASE_XBOX_NAMES, - [GAMEPAD_BUTTON_MISC1] = DEF_NAME_BUTTON("Share"), - PARTIAL_DEF_END }; - - static const button_strings_t elite_names[] = { PARTIAL_DEF_START, - BASE_XBOX_NAMES, - [GAMEPAD_BUTTON_PADDLE1] = DEF_NAME_SIMPLE("P1 Paddle"), - [GAMEPAD_BUTTON_PADDLE2] = DEF_NAME_SIMPLE("P2 Paddle"), - [GAMEPAD_BUTTON_PADDLE3] = DEF_NAME_SIMPLE("P3 Paddle"), - [GAMEPAD_BUTTON_PADDLE4] = DEF_NAME_SIMPLE("P4 Paddle"), - PARTIAL_DEF_END }; - - if (type == GAMEPAD_TYPE_XBOX_SERIES_XS) // X|S controllers have a Share button - names = series_xs_names; - else if (type == GAMEPAD_TYPE_XBOX_ELITE) // Elite controller has paddles - names = elite_names; - else - names = xbox_names; - - #undef BASE_XBOX_NAMES + flag = G_CheckDoubleClick(gamekeydown[KEY_2JOY1+i], &joy2dclicks[i]); + gamekeydown[KEY_DBL2JOY1+i] = flag; } - else if (G_GamepadTypeIsPlayStation(type)) - { - #define BASE_PS_NAMES \ - [GAMEPAD_BUTTON_A] = DEF_NAME_BUTTON("Cross"), \ - [GAMEPAD_BUTTON_B] = DEF_NAME_BUTTON("Circle"), \ - [GAMEPAD_BUTTON_X] = DEF_NAME_BUTTON("Square"), \ - [GAMEPAD_BUTTON_Y] = DEF_NAME_BUTTON("Triangle"), \ - [GAMEPAD_BUTTON_BACK] = DEF_NAME_BUTTON("Select"), \ - [GAMEPAD_BUTTON_GUIDE] = DEF_NAME_BUTTON("PS"), \ - [GAMEPAD_BUTTON_LEFTSTICK] = DEF_NAME_BUTTON("L3"), \ - [GAMEPAD_BUTTON_RIGHTSTICK] = DEF_NAME_BUTTON("R3"), \ - [GAMEPAD_BUTTON_LEFTSHOULDER] = DEF_NAME_BUTTON("L1"), \ - [GAMEPAD_BUTTON_RIGHTSHOULDER] = DEF_NAME_BUTTON("R1") - - static const button_strings_t ps_names[] = { - BASE_PS_NAMES, - PARTIAL_DEF_END }; - - static const button_strings_t ps5_names[] = { - BASE_PS_NAMES, - [GAMEPAD_BUTTON_MISC1] = DEF_NAME_BUTTON("Microphone"), - PARTIAL_DEF_END }; - - names = type == GAMEPAD_TYPE_PS5 ? ps5_names : ps_names; - #undef BASE_PS_NAMES - } - else if (G_GamepadTypeIsNintendoSwitch(type)) - { - static const button_strings_t switch_names[] = { PARTIAL_DEF_START, - [GAMEPAD_BUTTON_BACK] = DEF_NAME_BUTTON("-"), - [GAMEPAD_BUTTON_GUIDE] = DEF_NAME_BUTTON("HOME"), - [GAMEPAD_BUTTON_START] = DEF_NAME_BUTTON("+"), - [GAMEPAD_BUTTON_LEFTSHOULDER] = DEF_NAME_BUTTON("L"), - [GAMEPAD_BUTTON_RIGHTSHOULDER] = DEF_NAME_BUTTON("R"), - [GAMEPAD_BUTTON_MISC1] = DEF_NAME_BUTTON("Capture"), - PARTIAL_DEF_END }; - - names = switch_names; - } - else if (type == GAMEPAD_TYPE_AMAZON_LUNA) - { - static const button_strings_t luna_names[] = { PARTIAL_DEF_START, - [GAMEPAD_BUTTON_MISC1] = DEF_NAME_BUTTON("Microphone"), - PARTIAL_DEF_END }; - - names = luna_names; - } - - const char *str = NULL; - - if (names) - str = GetStringFromButtonList(names, button, strtype); - if (str == NULL) - str = GetStringFromButtonList(base_names, button, strtype); - if (str) - return str; - - return "Unknown"; } -#undef DEF_NAME_BUTTON -#undef DEF_NAME_SIMPLE -#undef DEF_NAME_DPAD - -#undef PARTIAL_DEF_START -#undef PARTIAL_DEF_END - -typedef struct -{ - const char *name; - const char *menu1; - const char *menu2; - const char *name_inv; - const char *menu1_inv; - const char *menu2_inv; -} axis_strings_t; - -#define DEF_NAME_AXIS(str, a, inv_a, b, inv_b) {\ - str " " a, str " " b, "the " str " " b, \ - str " " inv_a, str " " inv_b, "the " str " " inv_b} -#define DEF_NAME_TRIGGER(str) {str, NULL, "the " str, NULL, NULL, NULL} -#define DEF_NAME_BUTTON(str) {str, str " Button", "the " str " Button", NULL, NULL, NULL} - -#define PARTIAL_DEF_START [GAMEPAD_AXIS_LEFTX] = { NULL } - -static const char *GetStringFromAxisList(const axis_strings_t *names, gamepad_axis_e axis, gamepad_string_e type, boolean inv) +// +// General double-click detection routine for any kind of input. +// +static UINT8 G_CheckDoubleClick(UINT8 state, dclick_t *dt) { - switch (type) + if (state != dt->state && dt->time > 1) { - case GAMEPAD_STRING_DEFAULT: - if (inv && names[axis].name_inv) - return names[axis].name_inv; - else - return names[axis].name; - break; - case GAMEPAD_STRING_MENU1: - if (inv && names[axis].menu1_inv) - return names[axis].menu1_inv; - if (names[axis].menu1) - return names[axis].menu1; - else - return names[axis].name; - break; - case GAMEPAD_STRING_MENU2: - if (inv && names[axis].menu2_inv) - return names[axis].menu2_inv; - if (names[axis].menu2) - return names[axis].menu2; + dt->state = state; + if (state) + dt->clicks++; + if (dt->clicks == 2) + { + dt->clicks = 0; + return true; + } else - return names[axis].name; - break; - } - - return NULL; -} - -const char *G_GetGamepadAxisString(gamepadtype_e type, gamepad_axis_e axis, gamepad_string_e strtype, boolean inv) -{ - static const axis_strings_t base_names[] = { - [GAMEPAD_AXIS_LEFTX] = DEF_NAME_AXIS("Left Stick", "X", "X-", "\x1D", "\x1C"), - [GAMEPAD_AXIS_LEFTY] = DEF_NAME_AXIS("Left Stick", "Y", "Y-", "\x1B", "\x1A"), - [GAMEPAD_AXIS_RIGHTX] = DEF_NAME_AXIS("Right Stick", "X", "X-", "\x1D", "\x1C"), - [GAMEPAD_AXIS_RIGHTY] = DEF_NAME_AXIS("Right Stick", "Y", "Y-", "\x1B", "\x1A"), - [GAMEPAD_AXIS_TRIGGERLEFT] = DEF_NAME_TRIGGER("Left Trigger"), - [GAMEPAD_AXIS_TRIGGERRIGHT] = DEF_NAME_TRIGGER("Right Trigger") - }; - - axis_strings_t const *names = NULL; - - if (G_GamepadTypeIsPlayStation(type)) - { - static const axis_strings_t ps_names[] = { PARTIAL_DEF_START, - [GAMEPAD_AXIS_TRIGGERLEFT] = DEF_NAME_BUTTON("L2"), - [GAMEPAD_AXIS_TRIGGERRIGHT] = DEF_NAME_BUTTON("R2"), - }; - - names = ps_names; + dt->time = 0; } - else if (G_GamepadTypeIsNintendoSwitch(type)) + else { - static const axis_strings_t switch_names[] = { PARTIAL_DEF_START, - [GAMEPAD_AXIS_TRIGGERLEFT] = DEF_NAME_BUTTON("ZL"), - [GAMEPAD_AXIS_TRIGGERRIGHT] = DEF_NAME_BUTTON("ZR"), - }; - - names = switch_names; + dt->time++; + if (dt->time > 20) + { + dt->clicks = 0; + dt->state = 0; + } } - - const char *str = NULL; - - if (names) - str = GetStringFromAxisList(names, axis, strtype, inv); - if (str == NULL) - str = GetStringFromAxisList(base_names, axis, strtype, inv); - if (str) - return str; - - return "Unknown"; + return false; } -#undef DEF_NAME_AXIS -#undef DEF_NAME_TRIGGER -#undef DEF_NAME_BUTTON - -#undef PARTIAL_DEF_START - typedef struct { INT32 keynum; @@ -842,17 +243,20 @@ static keyname_t keynames[] = {KEY_NUMLOCK, "numlock"}, {KEY_SCROLLLOCK, "scrolllock"}, - // satya nadella keys + // bill gates keys {KEY_LEFTWIN, "leftwin"}, {KEY_RIGHTWIN, "rightwin"}, {KEY_MENU, "menu"}, {KEY_LSHIFT, "lshift"}, {KEY_RSHIFT, "rshift"}, + {KEY_LSHIFT, "shift"}, {KEY_LCTRL, "lctrl"}, {KEY_RCTRL, "rctrl"}, + {KEY_LCTRL, "ctrl"}, {KEY_LALT, "lalt"}, {KEY_RALT, "ralt"}, + {KEY_LALT, "alt"}, // keypad keys {KEY_KPADSLASH, "keypad /"}, @@ -900,7 +304,7 @@ static keyname_t keynames[] = {'`', "TILDE"}, {KEY_PAUSE, "pause/break"}, - // virtual keys for mouse buttons and gamepad buttons + // virtual keys for mouse buttons and joystick buttons {KEY_MOUSE1+0,"mouse1"}, {KEY_MOUSE1+1,"mouse2"}, {KEY_MOUSE1+2,"mouse3"}, @@ -909,8 +313,8 @@ static keyname_t keynames[] = {KEY_MOUSE1+5,"mouse6"}, {KEY_MOUSE1+6,"mouse7"}, {KEY_MOUSE1+7,"mouse8"}, - {KEY_2MOUSE1+0,"sec_mouse1"}, - {KEY_2MOUSE1+1,"sec_mouse2"}, + {KEY_2MOUSE1+0,"sec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2 + {KEY_2MOUSE1+1,"sec_mouse1"}, {KEY_2MOUSE1+2,"sec_mouse3"}, {KEY_2MOUSE1+3,"sec_mouse4"}, {KEY_2MOUSE1+4,"sec_mouse5"}, @@ -922,48 +326,58 @@ static keyname_t keynames[] = {KEY_2MOUSEWHEELUP, "wheel 2 up"}, {KEY_2MOUSEWHEELDOWN, "wheel 2 down"}, -#define DEF_GAMEPAD_NAME(btn, name) {KEY_GAMEPAD+GAMEPAD_BUTTON_##btn, name} -#define DEF_GAMEPAD_AXIS(ax, name) \ - {KEY_AXES+GAMEPAD_AXIS_##ax, name}, \ - {KEY_INV_AXES+GAMEPAD_AXIS_##ax, name "-"} - - DEF_GAMEPAD_NAME(A, "a button"), - DEF_GAMEPAD_NAME(B, "b button"), - DEF_GAMEPAD_NAME(X, "x button"), - DEF_GAMEPAD_NAME(Y, "y button"), - - DEF_GAMEPAD_NAME(BACK, "back button"), - DEF_GAMEPAD_NAME(GUIDE, "guide button"), - DEF_GAMEPAD_NAME(START, "start button"), - DEF_GAMEPAD_NAME(LEFTSTICK, "left stick"), - DEF_GAMEPAD_NAME(RIGHTSTICK, "right stick"), - - DEF_GAMEPAD_NAME(LEFTSHOULDER, "left shoulder"), - DEF_GAMEPAD_NAME(RIGHTSHOULDER, "right shoulder"), - - DEF_GAMEPAD_NAME(DPAD_UP, "d-pad up"), - DEF_GAMEPAD_NAME(DPAD_DOWN, "d-pad down"), - DEF_GAMEPAD_NAME(DPAD_LEFT, "d-pad left"), - DEF_GAMEPAD_NAME(DPAD_RIGHT, "d-pad right"), - - DEF_GAMEPAD_NAME(MISC1, "gamepad misc 1"), - DEF_GAMEPAD_NAME(PADDLE1, "paddle 1"), - DEF_GAMEPAD_NAME(PADDLE2, "paddle 2"), - DEF_GAMEPAD_NAME(PADDLE3, "paddle 3"), - DEF_GAMEPAD_NAME(PADDLE4, "paddle 4"), - DEF_GAMEPAD_NAME(TOUCHPAD, "touchpad"), - - DEF_GAMEPAD_AXIS(LEFTX, "left stick x"), - DEF_GAMEPAD_AXIS(LEFTY, "left stick y"), - - DEF_GAMEPAD_AXIS(RIGHTX, "right stick x"), - DEF_GAMEPAD_AXIS(RIGHTY, "right stick y"), - - DEF_GAMEPAD_AXIS(TRIGGERLEFT, "left trigger"), - DEF_GAMEPAD_AXIS(TRIGGERRIGHT, "right trigger"), - -#undef DEF_GAMEPAD_NAME -#undef DEF_GAMEPAD_AXIS + {KEY_JOY1+0, "joy1"}, + {KEY_JOY1+1, "joy2"}, + {KEY_JOY1+2, "joy3"}, + {KEY_JOY1+3, "joy4"}, + {KEY_JOY1+4, "joy5"}, + {KEY_JOY1+5, "joy6"}, + {KEY_JOY1+6, "joy7"}, + {KEY_JOY1+7, "joy8"}, + {KEY_JOY1+8, "joy9"}, +#if !defined (NOMOREJOYBTN_1S) + // we use up to 32 buttons in DirectInput + {KEY_JOY1+9, "joy10"}, + {KEY_JOY1+10, "joy11"}, + {KEY_JOY1+11, "joy12"}, + {KEY_JOY1+12, "joy13"}, + {KEY_JOY1+13, "joy14"}, + {KEY_JOY1+14, "joy15"}, + {KEY_JOY1+15, "joy16"}, + {KEY_JOY1+16, "joy17"}, + {KEY_JOY1+17, "joy18"}, + {KEY_JOY1+18, "joy19"}, + {KEY_JOY1+19, "joy20"}, + {KEY_JOY1+20, "joy21"}, + {KEY_JOY1+21, "joy22"}, + {KEY_JOY1+22, "joy23"}, + {KEY_JOY1+23, "joy24"}, + {KEY_JOY1+24, "joy25"}, + {KEY_JOY1+25, "joy26"}, + {KEY_JOY1+26, "joy27"}, + {KEY_JOY1+27, "joy28"}, + {KEY_JOY1+28, "joy29"}, + {KEY_JOY1+29, "joy30"}, + {KEY_JOY1+30, "joy31"}, + {KEY_JOY1+31, "joy32"}, +#endif + // the DOS version uses Allegro's joystick support + {KEY_HAT1+0, "hatup"}, + {KEY_HAT1+1, "hatdown"}, + {KEY_HAT1+2, "hatleft"}, + {KEY_HAT1+3, "hatright"}, + {KEY_HAT1+4, "hatup2"}, + {KEY_HAT1+5, "hatdown2"}, + {KEY_HAT1+6, "hatleft2"}, + {KEY_HAT1+7, "hatright2"}, + {KEY_HAT1+8, "hatup3"}, + {KEY_HAT1+9, "hatdown3"}, + {KEY_HAT1+10, "hatleft3"}, + {KEY_HAT1+11, "hatright3"}, + {KEY_HAT1+12, "hatup4"}, + {KEY_HAT1+13, "hatdown4"}, + {KEY_HAT1+14, "hatleft4"}, + {KEY_HAT1+15, "hatright4"}, {KEY_DBLMOUSE1+0, "dblmouse1"}, {KEY_DBLMOUSE1+1, "dblmouse2"}, @@ -973,154 +387,172 @@ static keyname_t keynames[] = {KEY_DBLMOUSE1+5, "dblmouse6"}, {KEY_DBLMOUSE1+6, "dblmouse7"}, {KEY_DBLMOUSE1+7, "dblmouse8"}, - {KEY_DBL2MOUSE1+0, "dblsec_mouse1"}, - {KEY_DBL2MOUSE1+1, "dblsec_mouse2"}, + {KEY_DBL2MOUSE1+0, "dblsec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2 + {KEY_DBL2MOUSE1+1, "dblsec_mouse1"}, {KEY_DBL2MOUSE1+2, "dblsec_mouse3"}, {KEY_DBL2MOUSE1+3, "dblsec_mouse4"}, {KEY_DBL2MOUSE1+4, "dblsec_mouse5"}, {KEY_DBL2MOUSE1+5, "dblsec_mouse6"}, {KEY_DBL2MOUSE1+6, "dblsec_mouse7"}, - {KEY_DBL2MOUSE1+7, "dblsec_mouse8"} -}; - -#define NUMKEYNAMES (sizeof(keynames) / sizeof(keyname_t)) - -static keyname_t displaykeynames[] = -{ - {KEY_SPACE, "Space Bar"}, - {KEY_CAPSLOCK, "Caps Lock"}, - {KEY_ENTER, "Enter"}, - {KEY_TAB, "Tab"}, - {KEY_ESCAPE, "Escape"}, - {KEY_BACKSPACE, "Backspace"}, - - {KEY_NUMLOCK, "Num Lock"}, - {KEY_SCROLLLOCK, "Scroll Lock"}, - -#ifdef _WIN32 - {KEY_LEFTWIN, "Left Windows"}, - {KEY_RIGHTWIN, "Right Windows"}, -#else - {KEY_LEFTWIN, "Left Super"}, - {KEY_RIGHTWIN, "Right Super"}, + {KEY_DBL2MOUSE1+7, "dblsec_mouse8"}, + + {KEY_DBLJOY1+0, "dbljoy1"}, + {KEY_DBLJOY1+1, "dbljoy2"}, + {KEY_DBLJOY1+2, "dbljoy3"}, + {KEY_DBLJOY1+3, "dbljoy4"}, + {KEY_DBLJOY1+4, "dbljoy5"}, + {KEY_DBLJOY1+5, "dbljoy6"}, + {KEY_DBLJOY1+6, "dbljoy7"}, + {KEY_DBLJOY1+7, "dbljoy8"}, +#if !defined (NOMOREJOYBTN_1DBL) + {KEY_DBLJOY1+8, "dbljoy9"}, + {KEY_DBLJOY1+9, "dbljoy10"}, + {KEY_DBLJOY1+10, "dbljoy11"}, + {KEY_DBLJOY1+11, "dbljoy12"}, + {KEY_DBLJOY1+12, "dbljoy13"}, + {KEY_DBLJOY1+13, "dbljoy14"}, + {KEY_DBLJOY1+14, "dbljoy15"}, + {KEY_DBLJOY1+15, "dbljoy16"}, + {KEY_DBLJOY1+16, "dbljoy17"}, + {KEY_DBLJOY1+17, "dbljoy18"}, + {KEY_DBLJOY1+18, "dbljoy19"}, + {KEY_DBLJOY1+19, "dbljoy20"}, + {KEY_DBLJOY1+20, "dbljoy21"}, + {KEY_DBLJOY1+21, "dbljoy22"}, + {KEY_DBLJOY1+22, "dbljoy23"}, + {KEY_DBLJOY1+23, "dbljoy24"}, + {KEY_DBLJOY1+24, "dbljoy25"}, + {KEY_DBLJOY1+25, "dbljoy26"}, + {KEY_DBLJOY1+26, "dbljoy27"}, + {KEY_DBLJOY1+27, "dbljoy28"}, + {KEY_DBLJOY1+28, "dbljoy29"}, + {KEY_DBLJOY1+29, "dbljoy30"}, + {KEY_DBLJOY1+30, "dbljoy31"}, + {KEY_DBLJOY1+31, "dbljoy32"}, +#endif + {KEY_DBLHAT1+0, "dblhatup"}, + {KEY_DBLHAT1+1, "dblhatdown"}, + {KEY_DBLHAT1+2, "dblhatleft"}, + {KEY_DBLHAT1+3, "dblhatright"}, + {KEY_DBLHAT1+4, "dblhatup2"}, + {KEY_DBLHAT1+5, "dblhatdown2"}, + {KEY_DBLHAT1+6, "dblhatleft2"}, + {KEY_DBLHAT1+7, "dblhatright2"}, + {KEY_DBLHAT1+8, "dblhatup3"}, + {KEY_DBLHAT1+9, "dblhatdown3"}, + {KEY_DBLHAT1+10, "dblhatleft3"}, + {KEY_DBLHAT1+11, "dblhatright3"}, + {KEY_DBLHAT1+12, "dblhatup4"}, + {KEY_DBLHAT1+13, "dblhatdown4"}, + {KEY_DBLHAT1+14, "dblhatleft4"}, + {KEY_DBLHAT1+15, "dblhatright4"}, + + {KEY_2JOY1+0, "sec_joy1"}, + {KEY_2JOY1+1, "sec_joy2"}, + {KEY_2JOY1+2, "sec_joy3"}, + {KEY_2JOY1+3, "sec_joy4"}, + {KEY_2JOY1+4, "sec_joy5"}, + {KEY_2JOY1+5, "sec_joy6"}, + {KEY_2JOY1+6, "sec_joy7"}, + {KEY_2JOY1+7, "sec_joy8"}, +#if !defined (NOMOREJOYBTN_2S) + // we use up to 32 buttons in DirectInput + {KEY_2JOY1+8, "sec_joy9"}, + {KEY_2JOY1+9, "sec_joy10"}, + {KEY_2JOY1+10, "sec_joy11"}, + {KEY_2JOY1+11, "sec_joy12"}, + {KEY_2JOY1+12, "sec_joy13"}, + {KEY_2JOY1+13, "sec_joy14"}, + {KEY_2JOY1+14, "sec_joy15"}, + {KEY_2JOY1+15, "sec_joy16"}, + {KEY_2JOY1+16, "sec_joy17"}, + {KEY_2JOY1+17, "sec_joy18"}, + {KEY_2JOY1+18, "sec_joy19"}, + {KEY_2JOY1+19, "sec_joy20"}, + {KEY_2JOY1+20, "sec_joy21"}, + {KEY_2JOY1+21, "sec_joy22"}, + {KEY_2JOY1+22, "sec_joy23"}, + {KEY_2JOY1+23, "sec_joy24"}, + {KEY_2JOY1+24, "sec_joy25"}, + {KEY_2JOY1+25, "sec_joy26"}, + {KEY_2JOY1+26, "sec_joy27"}, + {KEY_2JOY1+27, "sec_joy28"}, + {KEY_2JOY1+28, "sec_joy29"}, + {KEY_2JOY1+29, "sec_joy30"}, + {KEY_2JOY1+30, "sec_joy31"}, + {KEY_2JOY1+31, "sec_joy32"}, +#endif + // the DOS version uses Allegro's joystick support + {KEY_2HAT1+0, "sec_hatup"}, + {KEY_2HAT1+1, "sec_hatdown"}, + {KEY_2HAT1+2, "sec_hatleft"}, + {KEY_2HAT1+3, "sec_hatright"}, + {KEY_2HAT1+4, "sec_hatup2"}, + {KEY_2HAT1+5, "sec_hatdown2"}, + {KEY_2HAT1+6, "sec_hatleft2"}, + {KEY_2HAT1+7, "sec_hatright2"}, + {KEY_2HAT1+8, "sec_hatup3"}, + {KEY_2HAT1+9, "sec_hatdown3"}, + {KEY_2HAT1+10, "sec_hatleft3"}, + {KEY_2HAT1+11, "sec_hatright3"}, + {KEY_2HAT1+12, "sec_hatup4"}, + {KEY_2HAT1+13, "sec_hatdown4"}, + {KEY_2HAT1+14, "sec_hatleft4"}, + {KEY_2HAT1+15, "sec_hatright4"}, + + {KEY_DBL2JOY1+0, "dblsec_joy1"}, + {KEY_DBL2JOY1+1, "dblsec_joy2"}, + {KEY_DBL2JOY1+2, "dblsec_joy3"}, + {KEY_DBL2JOY1+3, "dblsec_joy4"}, + {KEY_DBL2JOY1+4, "dblsec_joy5"}, + {KEY_DBL2JOY1+5, "dblsec_joy6"}, + {KEY_DBL2JOY1+6, "dblsec_joy7"}, + {KEY_DBL2JOY1+7, "dblsec_joy8"}, +#if !defined (NOMOREJOYBTN_2DBL) + {KEY_DBL2JOY1+8, "dblsec_joy9"}, + {KEY_DBL2JOY1+9, "dblsec_joy10"}, + {KEY_DBL2JOY1+10, "dblsec_joy11"}, + {KEY_DBL2JOY1+11, "dblsec_joy12"}, + {KEY_DBL2JOY1+12, "dblsec_joy13"}, + {KEY_DBL2JOY1+13, "dblsec_joy14"}, + {KEY_DBL2JOY1+14, "dblsec_joy15"}, + {KEY_DBL2JOY1+15, "dblsec_joy16"}, + {KEY_DBL2JOY1+16, "dblsec_joy17"}, + {KEY_DBL2JOY1+17, "dblsec_joy18"}, + {KEY_DBL2JOY1+18, "dblsec_joy19"}, + {KEY_DBL2JOY1+19, "dblsec_joy20"}, + {KEY_DBL2JOY1+20, "dblsec_joy21"}, + {KEY_DBL2JOY1+21, "dblsec_joy22"}, + {KEY_DBL2JOY1+22, "dblsec_joy23"}, + {KEY_DBL2JOY1+23, "dblsec_joy24"}, + {KEY_DBL2JOY1+24, "dblsec_joy25"}, + {KEY_DBL2JOY1+25, "dblsec_joy26"}, + {KEY_DBL2JOY1+26, "dblsec_joy27"}, + {KEY_DBL2JOY1+27, "dblsec_joy28"}, + {KEY_DBL2JOY1+28, "dblsec_joy29"}, + {KEY_DBL2JOY1+29, "dblsec_joy30"}, + {KEY_DBL2JOY1+30, "dblsec_joy31"}, + {KEY_DBL2JOY1+31, "dblsec_joy32"}, #endif + {KEY_DBL2HAT1+0, "dblsec_hatup"}, + {KEY_DBL2HAT1+1, "dblsec_hatdown"}, + {KEY_DBL2HAT1+2, "dblsec_hatleft"}, + {KEY_DBL2HAT1+3, "dblsec_hatright"}, + {KEY_DBL2HAT1+4, "dblsec_hatup2"}, + {KEY_DBL2HAT1+5, "dblsec_hatdown2"}, + {KEY_DBL2HAT1+6, "dblsec_hatleft2"}, + {KEY_DBL2HAT1+7, "dblsec_hatright2"}, + {KEY_DBL2HAT1+8, "dblsec_hatup3"}, + {KEY_DBL2HAT1+9, "dblsec_hatdown3"}, + {KEY_DBL2HAT1+10, "dblsec_hatleft3"}, + {KEY_DBL2HAT1+11, "dblsec_hatright3"}, + {KEY_DBL2HAT1+12, "dblsec_hatup4"}, + {KEY_DBL2HAT1+13, "dblsec_hatdown4"}, + {KEY_DBL2HAT1+14, "dblsec_hatleft4"}, + {KEY_DBL2HAT1+15, "dblsec_hatright4"}, - {KEY_MENU, "Menu"}, - - {KEY_LSHIFT, "Left Shift"}, - {KEY_RSHIFT, "Right Shift"}, - {KEY_LCTRL, "Left Ctrl"}, - {KEY_RCTRL, "Right Ctrl"}, - {KEY_LALT, "Left Alt"}, - {KEY_RALT, "Right Alt"}, - - {KEY_KEYPAD0, "Keypad 0"}, - {KEY_KEYPAD1, "Keypad 1"}, - {KEY_KEYPAD2, "Keypad 2"}, - {KEY_KEYPAD3, "Keypad 3"}, - {KEY_KEYPAD4, "Keypad 4"}, - {KEY_KEYPAD5, "Keypad 5"}, - {KEY_KEYPAD6, "Keypad 6"}, - {KEY_KEYPAD7, "Keypad 7"}, - {KEY_KEYPAD8, "Keypad 8"}, - {KEY_KEYPAD9, "Keypad 9"}, - {KEY_PLUSPAD, "Keypad +"}, - {KEY_MINUSPAD, "Keypad -"}, - {KEY_KPADSLASH, "Keypad /"}, - {KEY_KPADDEL, "Keypad ."}, - - {KEY_UPARROW, "Up Arrow"}, - {KEY_DOWNARROW, "Down Arrow"}, - {KEY_LEFTARROW, "Left Arrow"}, - {KEY_RIGHTARROW, "Right Arrow"}, - - {KEY_HOME, "Home"}, - {KEY_END, "End"}, - {KEY_PGUP, "Page Up"}, - {KEY_PGDN, "Page Down"}, - {KEY_INS, "Insert"}, - {KEY_DEL, "Delete"}, - - {KEY_F1, "F1"}, - {KEY_F2, "F2"}, - {KEY_F3, "F3"}, - {KEY_F4, "F4"}, - {KEY_F5, "F5"}, - {KEY_F6, "F6"}, - {KEY_F7, "F7"}, - {KEY_F8, "F8"}, - {KEY_F9, "F9"}, - {KEY_F10, "F10"}, - {KEY_F11, "F11"}, - {KEY_F12, "F12"}, - - {'`', "Tilde"}, - {KEY_PAUSE, "Pause/Break"}, - - {KEY_MOUSE1+0, "Left Mouse Button"}, - {KEY_MOUSE1+1, "Right Mouse Button"}, - {KEY_MOUSE1+2, "Middle Mouse Button"}, - {KEY_MOUSE1+3, "X1 Mouse Button"}, - {KEY_MOUSE1+4, "X2 Mouse Button"}, - - {KEY_2MOUSE1+0, "Sec. Mouse Left Button"}, - {KEY_2MOUSE1+1, "Sec. Mouse Right Button"}, - {KEY_2MOUSE1+2, "Sec. Mouse Middle Button"}, - {KEY_2MOUSE1+3, "Sec. Mouse X1 Button"}, - {KEY_2MOUSE1+4, "Sec. Mouse X2 Button"}, - - {KEY_MOUSEWHEELUP, "Mouse Wheel Up"}, - {KEY_MOUSEWHEELDOWN, "Mouse Wheel Down"}, - {KEY_2MOUSEWHEELUP, "Sec. Mouse Wheel Up"}, - {KEY_2MOUSEWHEELDOWN, "Sec. Mouse Wheel Down"}, - -#define DEF_GAMEPAD_NAME(btn, name) {KEY_GAMEPAD+GAMEPAD_BUTTON_##btn, name} -#define DEF_GAMEPAD_AXIS(ax, name) {KEY_AXES+GAMEPAD_AXIS_##ax, name} - - DEF_GAMEPAD_NAME(A, "A Button"), - DEF_GAMEPAD_NAME(B, "B Button"), - DEF_GAMEPAD_NAME(X, "X Button"), - DEF_GAMEPAD_NAME(Y, "Y Button"), - - DEF_GAMEPAD_NAME(BACK, "Back Button"), - DEF_GAMEPAD_NAME(GUIDE, "Guide Button"), - DEF_GAMEPAD_NAME(START, "Start Button"), - DEF_GAMEPAD_NAME(LEFTSTICK, "Left Stick Button"), - DEF_GAMEPAD_NAME(RIGHTSTICK, "Right Stick Button"), - - DEF_GAMEPAD_NAME(LEFTSHOULDER, "Left Shoulder"), - DEF_GAMEPAD_NAME(RIGHTSHOULDER, "Right Shoulder"), - - DEF_GAMEPAD_NAME(DPAD_UP, "D-Pad Up"), - DEF_GAMEPAD_NAME(DPAD_DOWN, "D-Pad Down"), - DEF_GAMEPAD_NAME(DPAD_LEFT, "D-Pad Left"), - DEF_GAMEPAD_NAME(DPAD_RIGHT, "D-Pad Right"), - - DEF_GAMEPAD_NAME(MISC1, "Gamepad Misc. 1"), - DEF_GAMEPAD_NAME(PADDLE1, "Paddle 1"), - DEF_GAMEPAD_NAME(PADDLE2, "Paddle 2"), - DEF_GAMEPAD_NAME(PADDLE3, "Paddle 3"), - DEF_GAMEPAD_NAME(PADDLE4, "Paddle 4"), - DEF_GAMEPAD_NAME(TOUCHPAD, "Touchpad"), - - {KEY_INV_AXES + GAMEPAD_AXIS_LEFTX, "Left Stick \x1C"}, - {KEY_AXES + GAMEPAD_AXIS_LEFTX, "Left Stick \x1D"}, - {KEY_INV_AXES + GAMEPAD_AXIS_LEFTY, "Left Stick \x1A"}, - {KEY_AXES + GAMEPAD_AXIS_LEFTY, "Left Stick \x1B"}, - {KEY_INV_AXES + GAMEPAD_AXIS_RIGHTX, "Right Stick \x1C"}, - {KEY_AXES + GAMEPAD_AXIS_RIGHTX, "Right Stick \x1D"}, - {KEY_INV_AXES + GAMEPAD_AXIS_RIGHTY, "Right Stick \x1A"}, - {KEY_AXES + GAMEPAD_AXIS_RIGHTY, "Right Stick \x1B"}, - - DEF_GAMEPAD_AXIS(TRIGGERLEFT, "Left Trigger"), - DEF_GAMEPAD_AXIS(TRIGGERRIGHT, "Right Trigger"), - -#undef DEF_GAMEPAD_NAME -#undef DEF_GAMEPAD_AXIS }; -#define NUMDISPLAYKEYNAMES (sizeof(displaykeynames) / sizeof(keyname_t)) - static const char *gamecontrolname[NUM_GAMECONTROLS] = { "nothing", // a key/button mapped to GC_NULL has no effect @@ -1168,6 +600,8 @@ static const char *gamecontrolname[NUM_GAMECONTROLS] = "custom3", }; +#define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t)) + // // Detach any keys associated to the given game control // - pass the pointer to the gamecontrol table for the player being edited @@ -1188,7 +622,7 @@ void G_ClearAllControlKeys(void) } // -// Returns the name of a key (or virtual key for mouse and gamepad) +// Returns the name of a key (or virtual key for mouse and joy) // the input value being an keynum // const char *G_KeyNumToName(INT32 keynum) @@ -1211,44 +645,7 @@ const char *G_KeyNumToName(INT32 keynum) return keynames[j].name; // create a name for unknown keys - snprintf(keynamestr, sizeof keynamestr, "KEY%d", keynum); - return keynamestr; -} - -const char *G_GetDisplayNameForKey(INT32 keynum) -{ - static char keynamestr[32]; - - UINT32 j; - - // find a description for special keys - for (j = 0; j < NUMDISPLAYKEYNAMES; j++) - if (displaykeynames[j].keynum == keynum) - return displaykeynames[j].name; - - // return a string with the ascii char if displayable - if (keynum > ' ' && keynum <= 'z' && keynum != KEY_CONSOLE) - { - snprintf(keynamestr, sizeof keynamestr, "%c Key", toupper((char)keynum)); - return keynamestr; - } - - // unnamed mouse buttons - if (keynum >= KEY_MOUSE1 && keynum <= KEY_MOUSE1+7) - { - j = (keynum - KEY_MOUSE1) + 1; - snprintf(keynamestr, sizeof keynamestr, "Mouse Button #%d", j); - return keynamestr; - } - else if (keynum >= KEY_2MOUSE1 && keynum <= KEY_2MOUSE1+7) - { - j = (keynum - KEY_2MOUSE1) + 1; - snprintf(keynamestr, sizeof keynamestr, "Sec. Mouse Button #%d", j); - return keynamestr; - } - - // create a name for unknown keys - snprintf(keynamestr, sizeof keynamestr, "Unknown Key %d", keynum); + sprintf(keynamestr, "KEY%d", keynum); return keynamestr; } @@ -1275,36 +672,6 @@ INT32 G_KeyNameToNum(const char *keystr) return 0; } -const char *G_GamepadTypeToString(gamepadtype_e type) -{ - static const char *names[] = { - "xbox-360", - "xbox-one", - "xbox-series-xs", - "xbox-elite", - "ps3", - "ps4", - "ps5", - "switch-pro", - "switch-joy-con-grip", - "switch-joy-con-left", - "switch-joy-con-right", - "stadia", - "amazon-luna", - "steam-controller", - "virtual", - "unknown" - }; - - return names[type]; -} - -void G_InitGamepads(void) -{ - for (UINT8 i = 0; i < NUM_GAMEPADS; i++) - gamepads[i].num = i; -} - void G_DefineDefaultControls(void) { INT32 i; @@ -1372,36 +739,36 @@ void G_DefineDefaultControls(void) gamecontroldefault[i][GC_VIEWPOINTNEXT][0] = KEY_F12; // Gamepad controls -- same for both schemes - gamecontroldefault[i][GC_JUMP ][1] = GAMEPAD_KEY(A); // A - gamecontroldefault[i][GC_SPIN ][1] = GAMEPAD_KEY(X); // X - gamecontroldefault[i][GC_CUSTOM1 ][1] = GAMEPAD_KEY(B); // B - gamecontroldefault[i][GC_CUSTOM2 ][1] = GAMEPAD_KEY(Y); // Y - gamecontroldefault[i][GC_CUSTOM3 ][1] = GAMEPAD_KEY(LEFTSTICK); // Left Stick - gamecontroldefault[i][GC_CENTERVIEW ][1] = GAMEPAD_KEY(RIGHTSTICK); // Right Stick - gamecontroldefault[i][GC_WEAPONPREV ][1] = GAMEPAD_KEY(LEFTSHOULDER); // LB - gamecontroldefault[i][GC_WEAPONNEXT ][1] = GAMEPAD_KEY(RIGHTSHOULDER); // RB - gamecontroldefault[i][GC_SCREENSHOT ][1] = GAMEPAD_KEY(BACK); // Back - gamecontroldefault[i][GC_SYSTEMMENU ][0] = GAMEPAD_KEY(START); // Start - gamecontroldefault[i][GC_CAMTOGGLE ][1] = GAMEPAD_KEY(DPAD_UP); // D-Pad Up - gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = GAMEPAD_KEY(DPAD_DOWN); // D-Pad Down - gamecontroldefault[i][GC_TOSSFLAG ][1] = GAMEPAD_KEY(DPAD_LEFT); // D-Pad Left - gamecontroldefault[i][GC_SCORES ][1] = GAMEPAD_KEY(DPAD_RIGHT); // D-Pad Right - - // Second player only has gamepad defaults - gamecontrolbisdefault[i][GC_JUMP ][1] = GAMEPAD_KEY(A); // A - gamecontrolbisdefault[i][GC_SPIN ][1] = GAMEPAD_KEY(X); // X - gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = GAMEPAD_KEY(B); // B - gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = GAMEPAD_KEY(Y); // Y - gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = GAMEPAD_KEY(LEFTSTICK); // Left Stick - gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = GAMEPAD_KEY(RIGHTSTICK); // Right Stick - gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = GAMEPAD_KEY(LEFTSHOULDER); // LB - gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = GAMEPAD_KEY(RIGHTSHOULDER); // RB - gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = GAMEPAD_KEY(BACK); // Back - //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = GAMEPAD_KEY(START); // Start - gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = GAMEPAD_KEY(DPAD_UP); // D-Pad Up - gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = GAMEPAD_KEY(DPAD_DOWN); // D-Pad Down - gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = GAMEPAD_KEY(DPAD_LEFT); // D-Pad Left - //gamecontrolbisdefault[i][GC_SCORES ][1] = GAMEPAD_KEY(DPAD_RIGHT); // D-Pad Right + gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+0; // A + gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+2; // X + gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B + gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y + gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick + gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+9; // Right Stick + gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_JOY1+4; // LB + gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_JOY1+5; // RB + gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_JOY1+6; // Back + gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start + gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+0; // D-Pad Up + gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_HAT1+1; // D-Pad Down + gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+2; // D-Pad Left + gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+3; // D-Pad Right + + // Second player controls only have joypad defaults + gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A + gamecontrolbisdefault[i][GC_SPIN ][1] = KEY_2JOY1+2; // X + gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B + gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y + gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick + gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+9; // Right Stick + gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2JOY1+4; // LB + gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2JOY1+5; // RB + gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = KEY_2JOY1+6; // Back + //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start + gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2HAT1+0; // D-Pad Up + gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2HAT1+1; // D-Pad Down + gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+2; // D-Pad Left + //gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2HAT1+3; // D-Pad Right } } diff --git a/src/g_input.h b/src/g_input.h index fe623034a8..400e3fd126 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -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,177 +17,44 @@ #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_input_e; + KEY_MOUSEWHEELUP = KEY_DBL2HAT1 + JOYHATS*4, + KEY_MOUSEWHEELDOWN = KEY_MOUSEWHEELUP + 1, + KEY_2MOUSEWHEELUP = KEY_MOUSEWHEELDOWN + 1, + KEY_2MOUSEWHEELDOWN = KEY_2MOUSEWHEELUP + 1, -#define GAMEPAD_KEY(key) (KEY_GAMEPAD + GAMEPAD_BUTTON_##key) + NUMINPUTS = KEY_2MOUSEWHEELDOWN + 1, +} key_input_e; typedef enum { @@ -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); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 805aa694f8..c037abcd79 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -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; diff --git a/src/i_gamepad.h b/src/i_gamepad.h deleted file mode 100644 index 730109b545..0000000000 --- a/src/i_gamepad.h +++ /dev/null @@ -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__ diff --git a/src/i_joy.h b/src/i_joy.h new file mode 100644 index 0000000000..27584cea6e --- /dev/null +++ b/src/i_joy.h @@ -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__ diff --git a/src/i_system.h b/src/i_system.h index f3ca5aac5f..7153aa7357 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -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); diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 88efc3490c..1710b03552 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -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; } diff --git a/src/m_cheat.c b/src/m_cheat.c index f943774504..89c8009aed 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -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); diff --git a/src/m_menu.c b/src/m_menu.c index 51d13df987..82d0780620 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -41,8 +41,6 @@ #include "v_video.h" #include "i_video.h" -#include "i_gamepad.h" -#include "g_input.h" #include "keys.h" #include "z_zone.h" #include "w_wad.h" @@ -64,6 +62,8 @@ #include "i_sound.h" #include "fastcmp.h" +#include "i_joy.h" // for joystick menu controls + #include "p_saveg.h" // Only for NEWSKINSAVES // Condition Sets @@ -72,6 +72,13 @@ // And just some randomness for the exits. #include "m_random.h" +#if defined(HAVE_SDL) +#include "SDL.h" +#if SDL_VERSION_ATLEAST(2,0,0) +#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG +#endif +#endif + #if defined (__GNUC__) && (__GNUC__ >= 4) #define FIXUPO0 #endif @@ -141,12 +148,7 @@ typedef enum levellist_mode_t levellistmode = LLM_CREATESERVER; UINT8 maplistoption = 0; -static struct -{ - char name[29]; - INT32 index; -} gamepadInfo[MAX_CONNECTED_GAMEPADS + 1]; - +static char joystickInfo[MAX_JOYSTICKS+1][29]; #ifndef NONET static UINT32 serverlistpage; #endif @@ -161,7 +163,6 @@ static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002 static INT16 skullAnimCounter = 10; // skull animation counter static boolean setupcontrols_secondaryplayer; -static consvar_t *setupcontrols_joycvar = NULL; static INT32 (*setupcontrols)[2]; // pointer to the gamecontrols of the player being edited // shhh... what am I doing... nooooo! @@ -310,17 +311,17 @@ menu_t MP_MainDef; menu_t OP_ChangeControlsDef; menu_t OP_MPControlsDef, OP_MiscControlsDef; menu_t OP_P1ControlsDef, OP_P2ControlsDef, OP_MouseOptionsDef; -menu_t OP_Mouse2OptionsDef, OP_Gamepad1Def, OP_Gamepad2Def; +menu_t OP_Mouse2OptionsDef, OP_Joystick1Def, OP_Joystick2Def; menu_t OP_CameraOptionsDef, OP_Camera2OptionsDef; menu_t OP_PlaystyleDef; static void M_VideoModeMenu(INT32 choice); static void M_Setup1PControlsMenu(INT32 choice); static void M_Setup2PControlsMenu(INT32 choice); -static void M_Setup1PGamepadMenu(INT32 choice); -static void M_Setup2PGamepadMenu(INT32 choice); +static void M_Setup1PJoystickMenu(INT32 choice); +static void M_Setup2PJoystickMenu(INT32 choice); static void M_Setup1PPlaystyleMenu(INT32 choice); static void M_Setup2PPlaystyleMenu(INT32 choice); -static void M_AssignGamepad(INT32 choice); +static void M_AssignJoystick(INT32 choice); static void M_ChangeControl(INT32 choice); // Video & Sound @@ -374,8 +375,7 @@ static void M_DrawSetupChoosePlayerMenu(void); static void M_DrawControlsDefMenu(void); static void M_DrawCameraOptionsMenu(void); static void M_DrawPlaystyleMenu(void); -static void M_DrawGamepadMenu(void); -static void M_DrawControlConfigMenu(void); +static void M_DrawControl(void); static void M_DrawMainVideoMenu(void); static void M_DrawVideoMode(void); static void M_DrawColorMenu(void); @@ -386,7 +386,7 @@ static void M_DrawConnectMenu(void); static void M_DrawMPMainMenu(void); static void M_DrawRoomMenu(void); #endif -static void M_DrawGamepadList(void); +static void M_DrawJoystick(void); static void M_DrawSetupMultiPlayerMenu(void); // Handling functions @@ -1084,7 +1084,7 @@ static menuitem_t OP_P1ControlsMenu[] = { {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup1PControlsMenu, 10}, {IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 20}, - {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Gamepad1Def , 30}, + {IT_SUBMENU | IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def , 30}, {IT_SUBMENU | IT_STRING, NULL, "Camera Options...", &OP_CameraOptionsDef, 50}, @@ -1096,7 +1096,7 @@ static menuitem_t OP_P2ControlsMenu[] = { {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup2PControlsMenu, 10}, {IT_SUBMENU | IT_STRING, NULL, "Second Mouse Options...", &OP_Mouse2OptionsDef, 20}, - {IT_SUBMENU | IT_STRING, NULL, "Second Gamepad Options...", &OP_Gamepad2Def , 30}, + {IT_SUBMENU | IT_STRING, NULL, "Second Gamepad Options...", &OP_Joystick2Def , 30}, {IT_SUBMENU | IT_STRING, NULL, "Camera Options...", &OP_Camera2OptionsDef, 50}, @@ -1160,43 +1160,43 @@ static menuitem_t OP_ChangeControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, GC_CUSTOM3 }, }; -static menuitem_t OP_Gamepad1Menu[] = +static menuitem_t OP_Joystick1Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup1PGamepadMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis[0] , 30}, - {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis[0] , 40}, - {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis[0] , 50}, - {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis[0] , 60}, - {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis[0] , 70}, - {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis[0] , 80}, - {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis[0] , 90}, - {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis[0] ,100}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup1PJoystickMenu, 10}, + {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis , 30}, + {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis , 40}, + {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis , 50}, + {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis , 60}, + {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis , 70}, + {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis , 80}, + {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 90}, + {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis ,100}, {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 120}, {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 130}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone[0], 140}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone[0], 150}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone, 140}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone, 150}, }; -static menuitem_t OP_Gamepad2Menu[] = +static menuitem_t OP_Joystick2Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup2PGamepadMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis[1] , 30}, - {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis[1] , 40}, - {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis[1] , 50}, - {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis[1] , 60}, - {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis[1] , 70}, - {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis[1] , 80}, - {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis[1] , 90}, - {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis[1] ,100}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup2PJoystickMenu, 10}, + {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis2 , 30}, + {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis2 , 40}, + {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis2 , 50}, + {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis2 , 60}, + {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis2 , 70}, + {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis2 , 80}, + {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 90}, + {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 ,100}, {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2,120}, {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 130}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone[1],140}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone[1],150}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone2,140}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone2,150}, }; -static menuitem_t OP_GamepadSetMenu[MAX_CONNECTED_GAMEPADS + 1]; +static menuitem_t OP_JoystickSetMenu[1+MAX_JOYSTICKS]; static menuitem_t OP_MouseOptionsMenu[] = { @@ -2093,21 +2093,21 @@ menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE( MTREE3(MN_OP_MAIN, MN_OP_P2CONTROLS, MN_OP_P2MOUSE), "M_CONTRO", OP_Mouse2OptionsMenu, &OP_P2ControlsDef, 35, 30); -menu_t OP_Gamepad1Def = GAMEPADMENUSTYLE( +menu_t OP_Joystick1Def = DEFAULTMENUSTYLE( MTREE3(MN_OP_MAIN, MN_OP_P1CONTROLS, MN_OP_P1JOYSTICK), - "M_CONTRO", OP_Gamepad1Menu, &OP_P1ControlsDef, 50, 30); -menu_t OP_Gamepad2Def = GAMEPADMENUSTYLE( + "M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 50, 30); +menu_t OP_Joystick2Def = DEFAULTMENUSTYLE( MTREE3(MN_OP_MAIN, MN_OP_P2CONTROLS, MN_OP_P2JOYSTICK), - "M_CONTRO", OP_Gamepad2Menu, &OP_P2ControlsDef, 50, 30); + "M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 50, 30); -menu_t OP_GamepadSetDef = +menu_t OP_JoystickSetDef = { MTREE4(MN_OP_MAIN, 0, 0, MN_OP_JOYSTICKSET), // second and third level set on runtime "M_CONTRO", - sizeof (OP_GamepadSetMenu)/sizeof (menuitem_t), - &OP_Gamepad1Def, - OP_GamepadSetMenu, - M_DrawGamepadList, + sizeof (OP_JoystickSetMenu)/sizeof (menuitem_t), + &OP_Joystick1Def, + OP_JoystickSetMenu, + M_DrawJoystick, 60, 40, 0, NULL @@ -3198,28 +3198,13 @@ static void Command_Manual_f(void) itemOn = 0; } -static INT32 RemapGamepadButton(event_t *ev) -{ - switch (ev->key) - { - case GAMEPAD_BUTTON_A: return KEY_ENTER; - case GAMEPAD_BUTTON_B: return KEY_ESCAPE; - case GAMEPAD_BUTTON_X: return KEY_BACKSPACE; - case GAMEPAD_BUTTON_DPAD_UP: return KEY_UPARROW; - case GAMEPAD_BUTTON_DPAD_DOWN: return KEY_DOWNARROW; - case GAMEPAD_BUTTON_DPAD_LEFT: return KEY_LEFTARROW; - case GAMEPAD_BUTTON_DPAD_RIGHT: return KEY_RIGHTARROW; - } - - return KEY_GAMEPAD + ev->key; -} - // // M_Responder // boolean M_Responder(event_t *ev) { INT32 ch = -1; +// INT32 i; static tic_t joywait = 0, mousewait = 0; static INT32 pjoyx = 0, pjoyy = 0; static INT32 pmousex = 0, pmousey = 0; @@ -3237,8 +3222,6 @@ boolean M_Responder(event_t *ev) if (CON_Ready() && gamestate != GS_WAITINGPLAYERS) return false; - boolean useEventHandler = false; - if (noFurtherInput) { // Ignore input after enter/escape/other buttons @@ -3247,69 +3230,80 @@ boolean M_Responder(event_t *ev) } else if (menuactive) { - if (currentMenu->menuitems[itemOn].status == IT_MSGHANDLER) - useEventHandler = currentMenu->menuitems[itemOn].alphaKey == MM_EVENTHANDLER; - if (ev->type == ev_keydown) { keydown++; ch = ev->key; - // added 5-2-98 remap virtual keys (mouse buttons) + // added 5-2-98 remap virtual keys (mouse & joystick buttons) switch (ch) { case KEY_MOUSE1: + case KEY_JOY1: ch = KEY_ENTER; break; + case KEY_JOY1 + 3: + ch = 'n'; + break; case KEY_MOUSE1 + 1: + case KEY_JOY1 + 1: ch = KEY_ESCAPE; break; + case KEY_JOY1 + 2: + ch = KEY_BACKSPACE; + break; + case KEY_HAT1: + ch = KEY_UPARROW; + break; + case KEY_HAT1 + 1: + ch = KEY_DOWNARROW; + break; + case KEY_HAT1 + 2: + ch = KEY_LEFTARROW; + break; + case KEY_HAT1 + 3: + ch = KEY_RIGHTARROW; + break; } } - else if (ev->type == ev_gamepad_down) + else if (ev->type == ev_joystick && ev->key == 0 && joywait < I_GetTime()) { - keydown++; - ch = RemapGamepadButton(ev); - } - else if (ev->type == ev_gamepad_axis && ev->which == 0 && joywait < I_GetTime()) - { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(0); - const INT16 value = G_GamepadAxisEventValue(0, ev->x); - - if (ev->key == GAMEPAD_AXIS_LEFTY) + const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT; + if (ev->y != INT32_MAX) { - if (abs(value) > jdeadzone) + if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone) { - if (value < 0 && pjoyy >= 0) + if (ev->y < 0 && pjoyy >= 0) { ch = KEY_UPARROW; joywait = I_GetTime() + NEWTICRATE/7; } - else if (value > 0 && pjoyy <= 0) + else if (ev->y > 0 && pjoyy <= 0) { ch = KEY_DOWNARROW; joywait = I_GetTime() + NEWTICRATE/7; } - pjoyy = value; + pjoyy = ev->y; } else pjoyy = 0; } - else if (ev->key == GAMEPAD_AXIS_LEFTX) + + if (ev->x != INT32_MAX) { - if (abs(value) > jdeadzone) + if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone) { - if (value < 0 && pjoyx >= 0) + if (ev->x < 0 && pjoyx >= 0) { ch = KEY_LEFTARROW; joywait = I_GetTime() + NEWTICRATE/17; } - else if (value > 0 && pjoyx <= 0) + else if (ev->x > 0 && pjoyx <= 0) { ch = KEY_RIGHTARROW; joywait = I_GetTime() + NEWTICRATE/17; } - pjoyx = value; + pjoyx = ev->x; } else pjoyx = 0; @@ -3345,29 +3339,13 @@ boolean M_Responder(event_t *ev) pmousex = lastx += 30; } } - else if (ev->type == ev_keyup || ev->type == ev_gamepad_up) // Preserve event for other responders + else if (ev->type == ev_keyup) // Preserve event for other responders keydown = 0; } - // Preserve event for other responders - else if (ev->type == ev_keydown || ev->type == ev_gamepad_down) - { + else if (ev->type == ev_keydown) // Preserve event for other responders ch = ev->key; - if (ev->type == ev_gamepad_down) - ch += KEY_GAMEPAD; - } - else if (ev->type == ev_gamepad_axis) - { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(0); - const INT16 value = G_GamepadAxisEventValue(0, ev->x); - - if (value > jdeadzone) - ch = KEY_AXES + ev->key; - else if (value < -jdeadzone) - ch = KEY_INV_AXES + ev->key; - } - - if (!useEventHandler && ch == -1) + if (ch == -1) return false; else if (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1]) // allow remappable ESC key ch = KEY_ESCAPE; @@ -3455,25 +3433,27 @@ boolean M_Responder(event_t *ev) if (currentMenu->menuitems[itemOn].status == IT_MSGHANDLER) { - if (!useEventHandler) + if (currentMenu->menuitems[itemOn].alphaKey != MM_EVENTHANDLER) { - UINT16 type = currentMenu->menuitems[itemOn].alphaKey; - if (type == MM_YESNO && !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER || ch == KEY_DEL)) - return true; - if (routine) - routine(ch); - if (type == MM_YESNO) + if (ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER || ch == KEY_DEL) { + if (routine) + routine(ch); if (stopstopmessage) stopstopmessage = false; else M_StopMessage(0); noFurtherInput = true; + return true; } return true; } else { + // dirty hack: for customising controls, I want only buttons/keys, not moves + if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick + || ev->type == ev_joystick2) + return true; if (routine) { void (*otherroutine)(event_t *sev) = currentMenu->menuitems[itemOn].itemaction; @@ -3739,7 +3719,6 @@ void M_StartControlPanel(void) currentMenu = &SPauseDef; itemOn = spause_continue; - } else // multiplayer { @@ -3784,9 +3763,6 @@ void M_StartControlPanel(void) } CON_ToggleOff(); // move away console - - if (P_AutoPause()) - P_PauseRumble(NULL); } void M_EndModeAttackRun(void) @@ -3815,7 +3791,6 @@ void M_ClearMenus(boolean callexitmenufunc) hidetitlemap = false; I_UpdateMouseGrab(); - P_UnpauseRumble(NULL); } // @@ -3985,10 +3960,10 @@ void M_Init(void) at all if every item just calls the same function, and nothing more. Now just automate the definition. */ - for (i = 0; i < MAX_CONNECTED_GAMEPADS + 1; ++i) + for (i = 0; i <= MAX_JOYSTICKS; ++i) { - OP_GamepadSetMenu[i].status = ( IT_NOTHING|IT_CALL ); - OP_GamepadSetMenu[i].itemaction = M_AssignGamepad; + OP_JoystickSetMenu[i].status = ( IT_NOTHING|IT_CALL ); + OP_JoystickSetMenu[i].itemaction = M_AssignJoystick; } #ifndef NONET @@ -4218,6 +4193,26 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_ W_UnlockCachedPatch(patch); } +// +// Draw border for the savegame description +// +#if 0 // once used for joysticks and savegames, now no longer +static void M_DrawSaveLoadBorder(INT32 x,INT32 y) +{ + INT32 i; + + V_DrawScaledPatch (x-8,y+7,0,W_CachePatchName("M_LSLEFT",PU_PATCH)); + + for (i = 0;i < 24;i++) + { + V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSCNTR",PU_PATCH)); + x += 8; + } + + V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSRGHT",PU_PATCH)); +} +#endif + // horizontally centered text static void M_CentreText(INT32 y, const char *string) { @@ -6156,10 +6151,7 @@ void M_StartMessage(const char *string, void *routine, MessageDef.menuitems[0].text = message; MessageDef.menuitems[0].alphaKey = (UINT8)itemtype; - - if (routine == NULL && itemtype != MM_NOTHING) - itemtype = MM_NOTHING; - + if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING; switch (itemtype) { case MM_NOTHING: @@ -6167,7 +6159,9 @@ void M_StartMessage(const char *string, void *routine, MessageDef.menuitems[0].itemaction = M_StopMessage; break; case MM_YESNO: - case MM_KEYHANDLER: + MessageDef.menuitems[0].status = IT_MSGHANDLER; + MessageDef.menuitems[0].itemaction = routine; + break; case MM_EVENTHANDLER: MessageDef.menuitems[0].status = IT_MSGHANDLER; MessageDef.menuitems[0].itemaction = routine; @@ -6199,6 +6193,7 @@ void M_StartMessage(const char *string, void *routine, MessageDef.lastOn = (INT16)((strlines<<8)+max); + //M_SetupNextMenu(); currentMenu = &MessageDef; itemOn = 0; } @@ -11409,7 +11404,7 @@ static void M_ConnectMenuModChecks(INT32 choice) if (modifiedgame) { - M_StartMessage(M_GetText("You have add-ons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2 will automatically add\neverything you need when you join.\n\n(Press a key)\n"),M_ConnectMenu,MM_KEYHANDLER); + M_StartMessage(M_GetText("You have add-ons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2 will automatically add\neverything you need when you join.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER); return; } @@ -12602,147 +12597,183 @@ static void M_SetupScreenshotMenu(void) item->status = (IT_STRING | IT_CVAR); } -// ============ -// GAMEPAD MENU -// ============ +// ============= +// JOYSTICK MENU +// ============= // Start the controls menu, setting it up for either the console player, // or the secondary splitscreen player -static void M_DrawGamepadList(void) +static void M_DrawJoystick(void) { - INT32 i; - - INT32 compareval = G_GetGamepadDeviceIndex(0); - INT32 compareval2 = G_GetGamepadDeviceIndex(1); + INT32 i, compareval2, compareval; // draw title (or big pic) M_DrawMenuTitle(); - for (i = 0; i < MAX_CONNECTED_GAMEPADS + 1; i++) + for (i = 0; i <= MAX_JOYSTICKS; i++) // See MAX_JOYSTICKS { - M_DrawTextBox(OP_GamepadSetDef.x-8, OP_GamepadSetDef.y+LINEHEIGHT*i-12, 28, 1); + M_DrawTextBox(OP_JoystickSetDef.x-8, OP_JoystickSetDef.y+LINEHEIGHT*i-12, 28, 1); + //M_DrawSaveLoadBorder(OP_JoystickSetDef.x+4, OP_JoystickSetDef.y+1+LINEHEIGHT*i); + +#ifdef JOYSTICK_HOTPLUG + if (atoi(cv_usejoystick2.string) > I_NumJoys()) + compareval2 = atoi(cv_usejoystick2.string); + else + compareval2 = cv_usejoystick2.value; + + if (atoi(cv_usejoystick.string) > I_NumJoys()) + compareval = atoi(cv_usejoystick.string); + else + compareval = cv_usejoystick.value; +#else + compareval2 = cv_usejoystick2.value; + compareval = cv_usejoystick.value; +#endif if ((setupcontrols_secondaryplayer && (i == compareval2)) || (!setupcontrols_secondaryplayer && (i == compareval))) - V_DrawString(OP_GamepadSetDef.x, OP_GamepadSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,gamepadInfo[i].name); + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,joystickInfo[i]); else - V_DrawString(OP_GamepadSetDef.x, OP_GamepadSetDef.y+LINEHEIGHT*i-4,0,gamepadInfo[i].name); + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,0,joystickInfo[i]); if (i == itemOn) { - V_DrawScaledPatch(currentMenu->x - 24, OP_GamepadSetDef.y+LINEHEIGHT*i-4, 0, + V_DrawScaledPatch(currentMenu->x - 24, OP_JoystickSetDef.y+LINEHEIGHT*i-4, 0, W_CachePatchName("M_CURSOR", PU_PATCH)); } } } -boolean M_OnGamepadMenu(void) -{ - return currentMenu == &OP_GamepadSetDef; -} - -void M_UpdateGamepadMenu(void) +void M_SetupJoystickMenu(INT32 choice) { - INT32 i = 0, j = 1; - INT32 n = I_NumGamepads(); + INT32 i = 0; + const char *joyNA = "Unavailable"; + INT32 n = I_NumJoys(); + (void)choice; - strcpy(gamepadInfo[i].name, "None"); - gamepadInfo[i].index = 0; + strcpy(joystickInfo[i], "None"); - for (i = 1; i < MAX_CONNECTED_GAMEPADS + 1; i++) + for (i = 1; i <= MAX_JOYSTICKS; i++) { - if (i <= n && (I_GetGamepadName(i)) != NULL) - strlcpy(gamepadInfo[j].name, I_GetGamepadName(i), sizeof gamepadInfo[j].name); + if (i <= n && (I_GetJoyName(i)) != NULL) + strncpy(joystickInfo[i], I_GetJoyName(i), 28); else - strlcpy(gamepadInfo[j].name, "Unavailable", sizeof gamepadInfo[j].name); - - gamepadInfo[j].index = j; - -#ifdef GAMEPAD_HOTPLUG - // Update cv_usegamepad.string here so that the user can + strcpy(joystickInfo[i], joyNA); + +#ifdef JOYSTICK_HOTPLUG + // We use cv_usejoystick.string as the USER-SET var + // and cv_usejoystick.value as the INTERNAL var + // + // In practice, if cv_usejoystick.string == 0, this overrides + // cv_usejoystick.value and always disables + // + // Update cv_usejoystick.string here so that the user can // properly change this value. - for (INT32 jn = 0; jn < NUM_GAMEPADS; jn++) - { - if (i == cv_usegamepad[jn].value) - CV_SetValue(&cv_usegamepad[jn], i); - } + if (i == cv_usejoystick.value) + CV_SetValue(&cv_usejoystick, i); + if (i == cv_usejoystick2.value) + CV_SetValue(&cv_usejoystick2, i); #endif - - j++; } -} -static void M_SetupGamepadMenu(void) -{ - M_UpdateGamepadMenu(); - M_SetupNextMenu(&OP_GamepadSetDef); - - if (setupcontrols_secondaryplayer) - itemOn = G_GetGamepadDeviceIndex(1); - else - itemOn = G_GetGamepadDeviceIndex(0); + M_SetupNextMenu(&OP_JoystickSetDef); } -static void M_Setup1PGamepadMenu(INT32 choice) +static void M_Setup1PJoystickMenu(INT32 choice) { setupcontrols_secondaryplayer = false; - setupcontrols_joycvar = &cv_usegamepad[0]; - OP_GamepadSetDef.prevMenu = &OP_Gamepad1Def; - OP_GamepadSetDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); - OP_GamepadSetDef.menuid &= ~(((1 << MENUBITS) - 1) << (MENUBITS*2)); - OP_GamepadSetDef.menuid |= MN_OP_P1CONTROLS << MENUBITS; - OP_GamepadSetDef.menuid |= MN_OP_P1JOYSTICK << (MENUBITS*2); - - M_SetupGamepadMenu(); - (void)choice; + OP_JoystickSetDef.prevMenu = &OP_Joystick1Def; + OP_JoystickSetDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); + OP_JoystickSetDef.menuid &= ~(((1 << MENUBITS) - 1) << (MENUBITS*2)); + OP_JoystickSetDef.menuid |= MN_OP_P1CONTROLS << MENUBITS; + OP_JoystickSetDef.menuid |= MN_OP_P1JOYSTICK << (MENUBITS*2); + M_SetupJoystickMenu(choice); } -static void M_Setup2PGamepadMenu(INT32 choice) +static void M_Setup2PJoystickMenu(INT32 choice) { setupcontrols_secondaryplayer = true; - setupcontrols_joycvar = &cv_usegamepad[1]; - OP_GamepadSetDef.prevMenu = &OP_Gamepad2Def; - OP_GamepadSetDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); - OP_GamepadSetDef.menuid &= ~(((1 << MENUBITS) - 1) << (MENUBITS*2)); - OP_GamepadSetDef.menuid |= MN_OP_P2CONTROLS << MENUBITS; - OP_GamepadSetDef.menuid |= MN_OP_P2JOYSTICK << (MENUBITS*2); - - M_SetupGamepadMenu(); - (void)choice; + OP_JoystickSetDef.prevMenu = &OP_Joystick2Def; + OP_JoystickSetDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); + OP_JoystickSetDef.menuid &= ~(((1 << MENUBITS) - 1) << (MENUBITS*2)); + OP_JoystickSetDef.menuid |= MN_OP_P2CONTROLS << MENUBITS; + OP_JoystickSetDef.menuid |= MN_OP_P2JOYSTICK << (MENUBITS*2); + M_SetupJoystickMenu(choice); } -static void M_AssignGamepad(INT32 choice) +static void M_AssignJoystick(INT32 choice) { -#ifdef GAMEPAD_HOTPLUG - INT32 this = gamepadInfo[choice].index; +#ifdef JOYSTICK_HOTPLUG + INT32 oldchoice, oldstringchoice; + INT32 numjoys = I_NumJoys(); - // Detect if other players are using this gamepad index - for (INT32 i = 0; this && i < NUM_GAMEPADS; i++) + if (setupcontrols_secondaryplayer) { - // Ignore yourself - if (i == (INT32)setupcontrols_secondaryplayer) - continue; + oldchoice = oldstringchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; + CV_SetValue(&cv_usejoystick2, choice); - INT32 other = G_GetGamepadDeviceIndex(i); + // Just in case last-minute changes were made to cv_usejoystick.value, + // update the string too + // But don't do this if we're intentionally setting higher than numjoys + if (choice <= numjoys) + { + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - // Ignore gamepads that are disconnected - // (the game will deal with it when they are connected) - if (other > I_NumGamepads()) - continue; + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick2.value; + + if (oldchoice != choice) + { + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick2, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); + + if (oldstringchoice == + (atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) + M_StartMessage("This gamepad is used by another\n" + "player. Reset the gamepad\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } + } + else + { + oldchoice = oldstringchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; + CV_SetValue(&cv_usejoystick, choice); - if (other == this) + // Just in case last-minute changes were made to cv_usejoystick.value, + // update the string too + // But don't do this if we're intentionally setting higher than numjoys + if (choice <= numjoys) { - M_StartMessage("This gamepad is used by another\n" - "player. Reset the gamepad\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - return; + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick.value; + + if (oldchoice != choice) + { + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); + + if (oldstringchoice == + (atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) + M_StartMessage("This gamepad is used by another\n" + "player. Reset the gamepad\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } } } +#else + if (setupcontrols_secondaryplayer) + CV_SetValue(&cv_usejoystick2, choice); + else + CV_SetValue(&cv_usejoystick, choice); #endif - - CV_SetValue(setupcontrols_joycvar, this); } // ============= @@ -12813,26 +12844,10 @@ static void M_Setup2PControlsMenu(INT32 choice) M_SetupNextMenu(&OP_ChangeControlsDef); } -static const char *M_GetKeyName(UINT8 player, INT32 key) -{ - gamepadtype_e type = GAMEPAD_TYPE_UNKNOWN; - if (cv_usegamepad[player].value) - type = gamepads[player].type; - - if (key >= KEY_GAMEPAD && key < KEY_GAMEPAD + NUM_GAMEPAD_BUTTONS) - return G_GetGamepadButtonString(type, key - KEY_GAMEPAD, GAMEPAD_STRING_MENU1); - else if (key >= KEY_AXES && key < KEY_AXES + NUM_GAMEPAD_AXES) - return G_GetGamepadAxisString(type, key - KEY_AXES, GAMEPAD_STRING_MENU1, false); - else if (key >= KEY_INV_AXES && key < KEY_INV_AXES + NUM_GAMEPAD_AXES) - return G_GetGamepadAxisString(type, key - KEY_INV_AXES, GAMEPAD_STRING_MENU1, true); - - return G_GetDisplayNameForKey(key); -} - #define controlheight 18 // Draws the Customise Controls menu -static void M_DrawControlConfigMenu(void) +static void M_DrawControl(void) { char tmp[50]; INT32 x, y, i, max, cursory = 0, iter; @@ -12912,38 +12927,40 @@ static void M_DrawControlConfigMenu(void) if (currentMenu->menuitems[i].status == IT_CONTROL) { - INT32 right = x + V_StringWidth(currentMenu->menuitems[i].text, 0); V_DrawString(x, y, ((i == itemOn) ? V_YELLOWMAP : 0), currentMenu->menuitems[i].text); - keys[0] = setupcontrols[currentMenu->menuitems[i].alphaKey][0]; keys[1] = setupcontrols[currentMenu->menuitems[i].alphaKey][1]; tmp[0] ='\0'; if (keys[0] == KEY_NULL && keys[1] == KEY_NULL) + { strcpy(tmp, "---"); + } else { if (keys[0] != KEY_NULL) - strcat(tmp, M_GetKeyName(setupcontrols_secondaryplayer, keys[0])); + strcat (tmp, G_KeyNumToName (keys[0])); + if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) - strcat(tmp, " or "); + strcat(tmp," or "); + if (keys[1] != KEY_NULL) - strcat(tmp, M_GetKeyName(setupcontrols_secondaryplayer, keys[1])); - } + strcat (tmp, G_KeyNumToName (keys[1])); - INT32 left = BASEVIDWIDTH-currentMenu->x-V_StringWidth(tmp, V_ALLOWLOWERCASE); - if (left - 8 <= right) - V_DrawRightAlignedThinString(BASEVIDWIDTH-currentMenu->x, y+1, V_ALLOWLOWERCASE | V_YELLOWMAP, tmp); - else - V_DrawRightAlignedString(BASEVIDWIDTH-currentMenu->x, y, V_ALLOWLOWERCASE | V_YELLOWMAP, tmp); + + } + V_DrawRightAlignedString(BASEVIDWIDTH-currentMenu->x, y, V_YELLOWMAP, tmp); } + /*else if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2) + V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);*/ else if ((currentMenu->menuitems[i].status == IT_HEADER) && (i != max-1)) M_DrawLevelPlatterHeader(y, currentMenu->menuitems[i].text, true, false); y += SMALLLINEHEIGHT; } - V_DrawScaledPatch(currentMenu->x - 20, cursory, 0, W_CachePatchName("M_CURSOR", PU_PATCH)); + V_DrawScaledPatch(currentMenu->x - 20, cursory, 0, + W_CachePatchName("M_CURSOR", PU_PATCH)); } #undef controlbuffer @@ -12951,55 +12968,55 @@ static void M_DrawControlConfigMenu(void) static INT32 controltochange; static char controltochangetext[33]; -static void M_ChangeControlResponse(event_t *ev) +static void M_ChangecontrolResponse(event_t *ev) { - // dirty hack: for customising controls, I want only buttons/keys, not moves - if (ev->type == ev_mouse || ev->type == ev_mouse2) - return; - - INT32 ch = ev->key; - - // Remap gamepad events - if (ev->type == ev_gamepad_down) - ch += KEY_GAMEPAD; - else if (ev->type == ev_gamepad_axis) - { - const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(ev->which); - const INT16 value = G_GamepadAxisEventValue(ev->which, ev->x); - - if (value > jdeadzone) - ch += KEY_AXES; - else if (value < -jdeadzone) - ch += KEY_INV_AXES; - else - return; - } - else if (ev->type != ev_keydown) - return; + INT32 control; + INT32 found; + INT32 ch = ev->key; // ESCAPE cancels; dummy out PAUSE if (ch != KEY_ESCAPE && ch != KEY_PAUSE) { - INT32 control = controltochange; + + switch (ev->type) + { + // ignore mouse/joy movements, just get buttons + case ev_mouse: + case ev_mouse2: + case ev_joystick: + case ev_joystick2: + ch = KEY_NULL; // no key + break; + + // keypad arrows are converted for the menu in cursor arrows + // so use the event instead of ch + case ev_keydown: + ch = ev->key; + break; + + default: + break; + } + + control = controltochange; // check if we already entered this key - INT32 found = -1; - if (setupcontrols[control][0] == ch) + found = -1; + if (setupcontrols[control][0] ==ch) found = 0; - else if (setupcontrols[control][1] == ch) + else if (setupcontrols[control][1] ==ch) found = 1; - if (found >= 0) { -#define CHECK_DBL(key, length) (ch >= key && ch <= key+length) -#define SET_DBL(key, dblkey) ch-key+dblkey - // replace mouse clicks by double clicks - if (CHECK_DBL(KEY_MOUSE1, MOUSEBUTTONS)) - setupcontrols[control][found] = SET_DBL(KEY_MOUSE1, KEY_DBLMOUSE1); - else if (CHECK_DBL(KEY_2MOUSE1, MOUSEBUTTONS)) - setupcontrols[control][found] = SET_DBL(KEY_2MOUSE1, KEY_DBL2MOUSE1); -#undef CHECK_DBL -#undef SET_DBL + // replace mouse and joy clicks by double clicks + if (ch >= KEY_MOUSE1 && ch <= KEY_MOUSE1+MOUSEBUTTONS) + setupcontrols[control][found] = ch-KEY_MOUSE1+KEY_DBLMOUSE1; + else if (ch >= KEY_JOY1 && ch <= KEY_JOY1+JOYBUTTONS) + setupcontrols[control][found] = ch-KEY_JOY1+KEY_DBLJOY1; + else if (ch >= KEY_2MOUSE1 && ch <= KEY_2MOUSE1+MOUSEBUTTONS) + setupcontrols[control][found] = ch-KEY_2MOUSE1+KEY_DBL2MOUSE1; + else if (ch >= KEY_2JOY1 && ch <= KEY_2JOY1+JOYBUTTONS) + setupcontrols[control][found] = ch-KEY_2JOY1+KEY_DBL2JOY1; } else { @@ -13014,11 +13031,9 @@ static void M_ChangeControlResponse(event_t *ev) found = 0; setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2 } - - G_CheckDoubleUsage(ch, true); + (void)G_CheckDoubleUsage(ch, true); setupcontrols[control][found] = ch; } - S_StartSound(NULL, sfx_strpst); } else if (ch == KEY_PAUSE) @@ -13034,7 +13049,7 @@ static void M_ChangeControlResponse(event_t *ev) sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit is not configurable. \n\nHit another key for\n%s\nESC for Cancel"), controltochangetext); - M_StartMessage(tmp, M_ChangeControlResponse, MM_EVENTHANDLER); + M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); currentMenu->prevMenu = prev; S_StartSound(NULL, sfx_s3k42); @@ -13060,150 +13075,7 @@ static void M_ChangeControl(INT32 choice) currentMenu->menuitems[choice].text); strlcpy(controltochangetext, currentMenu->menuitems[choice].text, 33); - M_StartMessage(tmp, M_ChangeControlResponse, MM_EVENTHANDLER); -} - -static const char *M_GetGamepadAxisName(consvar_t *cv) -{ - switch (cv->value) - { - case 0: - return "None"; - - case 1: // X - return "L. Stick X"; - case 2: // Y - return "L. Stick Y"; - case 3: // X - return "R. Stick X"; - case 4: // Y - return "R. Stick Y"; - - case -1: // X- - return "L. Stick X (inv.)"; - case -2: // Y- - return "L. Stick Y (inv.)"; - case -3: // X- - return "R. Stick X (inv.)"; - case -4: // Y- - return "R. Stick Y (inv.)"; - - case 5: - return "L. Trigger"; - case 6: - return "R. Trigger"; - - default: - return cv->string; - } -} - -static void M_DrawGamepadMenu(void) -{ - INT32 x, y, i, cursory = 0; - INT32 right, left; - - // DRAW MENU - x = currentMenu->x; - y = currentMenu->y; - - // draw title (or big pic) - M_DrawMenuTitle(); - - for (i = 0; i < currentMenu->numitems; i++) - { - if (i == itemOn) - cursory = y; - switch (currentMenu->menuitems[i].status & IT_DISPLAY) - { - case IT_NOTHING: - case IT_DYBIGSPACE: - y += LINEHEIGHT; - break; - case IT_STRING: - case IT_WHITESTRING: - if (currentMenu->menuitems[i].alphaKey) - y = currentMenu->y+currentMenu->menuitems[i].alphaKey; - if (i == itemOn) - cursory = y; - - if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) - V_DrawString(x, y, 0, currentMenu->menuitems[i].text); - else - V_DrawString(x, y, V_YELLOWMAP, currentMenu->menuitems[i].text); - - right = x + V_StringWidth(currentMenu->menuitems[i].text, 0); - - // Cvar specific handling - switch (currentMenu->menuitems[i].status & IT_TYPE) - case IT_CVAR: - { - consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - switch (currentMenu->menuitems[i].status & IT_CVARTYPE) - { - case IT_CV_SLIDER: - M_DrawSlider(x, y, cv, (i == itemOn)); - break; - default: - { - const char *str = cv->string; - INT32 flags = V_YELLOWMAP; - INT32 width = V_StringWidth(str, flags); - - if (cv->PossibleValue == joyaxis_cons_t) - { - str = M_GetGamepadAxisName(cv); - flags |= V_ALLOWLOWERCASE; - - width = V_StringWidth(str, flags); - left = BASEVIDWIDTH - x - width; - - if (left - 16 <= right) - { - width = V_ThinStringWidth(str, flags); - V_DrawRightAlignedThinString(BASEVIDWIDTH - x, y + 1, flags, str); - } - else - V_DrawRightAlignedString(BASEVIDWIDTH - x, y, flags, str); - } - else - V_DrawRightAlignedString(BASEVIDWIDTH - x, y, flags, str); - - if (i == itemOn) - { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - width - (skullAnimCounter/5), y, - '\x1C' | V_YELLOWMAP, false); - V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, - '\x1D' | V_YELLOWMAP, false); - } - break; - } - } - break; - } - y += STRINGHEIGHT; - break; - case IT_TRANSTEXT: - if (currentMenu->menuitems[i].alphaKey) - y = currentMenu->y+currentMenu->menuitems[i].alphaKey; - V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text); - y += SMALLLINEHEIGHT; - break; - case IT_HEADERTEXT: // draws 16 pixels to the left, in yellow text - if (currentMenu->menuitems[i].alphaKey) - y = currentMenu->y+currentMenu->menuitems[i].alphaKey; - - //V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text); - M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false); - y += SMALLLINEHEIGHT; - break; - } - } - - // DRAW THE SKULL CURSOR - V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, - W_CachePatchName("M_CURSOR", PU_PATCH)); - V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); + M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); } static void M_Setup1PPlaystyleMenu(INT32 choice) diff --git a/src/m_menu.h b/src/m_menu.h index 8d023811d2..a7072b0c10 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -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\ diff --git a/src/p_haptic.c b/src/p_haptic.c deleted file mode 100644 index dbfa587379..0000000000 --- a/src/p_haptic.c +++ /dev/null @@ -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); -} diff --git a/src/p_haptic.h b/src/p_haptic.h deleted file mode 100644 index 1bd4f91993..0000000000 --- a/src/p_haptic.h +++ /dev/null @@ -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__ diff --git a/src/p_inter.c b/src/p_inter.c index f3c13e3151..dd3e0f9c27 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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. diff --git a/src/p_local.h b/src/p_local.h index 31a9e6c9d7..2b3020997d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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 �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); diff --git a/src/p_user.c b/src/p_user.c index 4ca4e6c8ad..c3f47f70cf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -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; diff --git a/src/sdl/Sourcefile b/src/sdl/Sourcefile index ef6a8b0dc4..82d5ce0734 100644 --- a/src/sdl/Sourcefile +++ b/src/sdl/Sourcefile @@ -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 diff --git a/src/sdl/i_gamepad.c b/src/sdl/i_gamepad.c deleted file mode 100644 index 69f03d662e..0000000000 --- a/src/sdl/i_gamepad.c +++ /dev/null @@ -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 diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ee082fd5d3..818d0f0c4b 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -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,15 +939,719 @@ 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(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) + { + CONS_Printf("Shutting down joy system\n"); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + I_OutputMsg("I_Joystick: SDL's Joystick system has been shutdown\n"); + } +} + +INT32 I_NumJoys(void) +{ + INT32 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 - if (SDL_WasInit(GAMEPAD_INIT_FLAGS) == GAMEPAD_INIT_FLAGS) +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) { - CONS_Printf("Shutting down game controller subsystems\n"); - SDL_QuitSubSystem(GAMEPAD_INIT_FLAGS); + tempname = SDL_JoystickNameForIndex(joyindex); + if (tempname) + strncpy(joyname, tempname, 255); } + return joyname; } #ifndef NOMUMBLE @@ -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; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 81b20b51e0..6e971a5d8b 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -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.type = ev_keydown; + } + else return; + if (evt.button == SDL_BUTTON_MIDDLE) event.key = KEY_MOUSE1+2; - break; - case SDL_BUTTON_X1: + 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; - break; - case SDL_BUTTON_X2: + else if (evt.button == SDL_BUTTON_X2) event.key = KEY_MOUSE1+4; - break; + 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_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_CONTROLLERDEVICEREMOVED: - I_ControllerDeviceRemoved(); + 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(); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index bb178b233f..6b6e79d975 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -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 -{ - boolean started; // started - int lastindex; // last gamepad ID - - SDL_GameController *dev; - SDL_Joystick *joydev; - - gamepad_t *info; // pointer to gamepad info - - struct { - Uint16 large_magnitude; - Uint16 small_magnitude; - Uint32 expiration, time_left; - } rumble; -} ControllerInfo; - -#define GAMEPAD_INIT_FLAGS (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) - -void I_UpdateControllers(void); - -void I_ControllerDeviceAdded(INT32 which); -void I_ControllerDeviceRemoved(void); +// 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 -void I_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type); -void I_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt); +// So m_menu knows whether to store cv_usejoystick value or string +#define JOYSTICK_HOTPLUG -INT32 I_GetControllerIndex(SDL_GameController *dev); -void I_CloseInactiveController(SDL_GameController *dev); -void I_CloseInactiveHapticDevice(SDL_Haptic *dev); +/** \brief The JoyInfo_s struct -void I_ToggleControllerRumble(boolean unpause); + info about joystick +*/ +typedef struct SDLJoyInfo_s +{ + /// 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; + +} SDLJoyInfo_t; + +/** \brief SDL info about joystick 1 +*/ +extern SDLJoyInfo_t JoyInfo; + +/** \brief joystick axis deadzone +*/ +#define SDL_JDEADZONE 153 +#undef SDL_JDEADZONE + +/** \brief SDL inof about joystick 2 +*/ +extern SDLJoyInfo_t JoyInfo2; + +// So we can call this from i_video event loop +void I_ShutdownJoystick(void); +void I_ShutdownJoystick2(void); + +// Cheat to get the device index for a joystick handle +INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev); void I_GetConsoleEvents(void); -- GitLab