diff --git a/src/doomdef.h b/src/doomdef.h index b1e7bfb0a..975c920b8 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -304,7 +304,7 @@ typedef enum SKINCOLOR_SLATE, SKINCOLOR_STEEL, SKINCOLOR_JET, - SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl + SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl SKINCOLOR_PERIWINKLE, SKINCOLOR_BLUE, SKINCOLOR_BLUEBERRY, diff --git a/src/g_game.c b/src/g_game.c index 97203b680..23f41564c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -467,7 +467,7 @@ consvar_t cv_brakeaxis = {"joyaxis_brake", "None", CV_SAVE, joyaxis_cons_t, NULL consvar_t cv_aimaxis = {"joyaxis_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_lookaxis = {"joyaxis_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis = {"joyaxis_drift", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_driftaxis = {"joyaxis_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_moveaxis2 = {"joyaxis2_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -475,7 +475,7 @@ consvar_t cv_brakeaxis2 = {"joyaxis2_brake", "None", CV_SAVE, joyaxis_cons_t, NU consvar_t cv_aimaxis2 = {"joyaxis2_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_lookaxis2 = {"joyaxis2_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis2 = {"joyaxis2_drift", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_driftaxis2 = {"joyaxis2_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_turnaxis3 = {"joyaxis3_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_moveaxis3 = {"joyaxis3_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -483,7 +483,7 @@ consvar_t cv_brakeaxis3 = {"joyaxis3_brake", "None", CV_SAVE, joyaxis_cons_t, NU consvar_t cv_aimaxis3 = {"joyaxis3_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_lookaxis3 = {"joyaxis3_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis3 = {"joyaxis3_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis3 = {"joyaxis3_drift", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_driftaxis3 = {"joyaxis3_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_turnaxis4 = {"joyaxis4_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_moveaxis4 = {"joyaxis4_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -491,7 +491,7 @@ consvar_t cv_brakeaxis4 = {"joyaxis4_brake", "None", CV_SAVE, joyaxis_cons_t, NU consvar_t cv_aimaxis4 = {"joyaxis4_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_lookaxis4 = {"joyaxis4_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fireaxis4 = {"joyaxis4_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis4 = {"joyaxis4_drift", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_driftaxis4 = {"joyaxis4_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #if MAXPLAYERS > 16 diff --git a/src/g_input.c b/src/g_input.c index 34ccc9e64..d7b7be91c 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1328,10 +1328,10 @@ void G_Controldefault(UINT8 player) gamecontrol[gc_viewpoint ][1] = KEY_JOY1+3; // Y gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back gamecontrol[gc_systemmenu ][0] = KEY_JOY1+7; // Start - gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up - gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down - gamecontrol[gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left - gamecontrol[gc_scores ][1] = KEY_HAT1+3; // D-Pad Right + //gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up + //gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down // absolutely fucking NOT + gamecontrol[gc_talkkey ][1] = KEY_HAT1+1; // D-Pad Down + gamecontrol[gc_scores ][1] = KEY_HAT1+0; // D-Pad Up } if (player == 0 || player == 2) diff --git a/src/m_menu.c b/src/m_menu.c index 762fbab28..d8b59676f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -67,6 +67,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 + #ifdef PC_DOS #include // for snprintf int snprintf(char *str, size_t n, const char *fmt, ...); @@ -2465,44 +2472,42 @@ boolean M_Responder(event_t *ev) // (but still allow shift keyup so caps doesn't get stuck) return false; } + else if (ev->type == ev_keydown) + { + ch = ev->data1; + + // added 5-2-98 remap virtual keys (mouse & joystick buttons) + switch (ch) + { + case KEY_MOUSE1: + //case KEY_JOY1: + //case KEY_JOY1 + 2: + ch = KEY_ENTER; + break; + /*case KEY_JOY1 + 3: // Brake can function as 'n' for message boxes now. + ch = 'n'; + break;*/ + case KEY_MOUSE1 + 1: + //case KEY_JOY1 + 1: + 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 (menuactive) { - if (ev->type == ev_keydown) - { - ch = ev->data1; - - // 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_joystick && ev->data1 == 0 && joywait < I_GetTime()) + if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) { const INT32 jdeadzone = JOYAXISRANGE/4; if (ev->data3 != INT32_MAX) @@ -2583,6 +2588,8 @@ boolean M_Responder(event_t *ev) return false; else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key ch = KEY_ESCAPE; + else if (ch == gamecontrol[gc_accelerate][0] || ch == gamecontrol[gc_accelerate][1]) + ch = KEY_ENTER; // F-Keys if (!menuactive) @@ -2659,6 +2666,9 @@ boolean M_Responder(event_t *ev) return false; } + if (ch == gamecontrol[gc_brake][0] || ch == gamecontrol[gc_brake][1]) // do this here, otherwise brake opens the menu mid-game + ch = KEY_ESCAPE; + routine = currentMenu->menuitems[itemOn].itemaction; // Handle menuitems which need a specific key handling @@ -2793,6 +2803,7 @@ boolean M_Responder(event_t *ev) return true; case KEY_ESCAPE: + //case KEY_JOY1 + 2: noFurtherInput = true; currentMenu->lastOn = itemOn; if (currentMenu->prevMenu) @@ -8564,7 +8575,7 @@ static void M_ScreenshotOptions(INT32 choice) static void M_DrawJoystick(void) { - INT32 i; + INT32 i, compareval4, compareval3, compareval2, compareval; M_DrawGenericMenu(); @@ -8573,17 +8584,44 @@ static void M_DrawJoystick(void) M_DrawTextBox(OP_JoystickSetDef.x-8, OP_JoystickSetDef.y+LINEHEIGHT*i-12, 28, 1); //M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); - if ((setupcontrolplayer == 4 && (i == cv_usejoystick4.value)) - || (setupcontrolplayer == 3 && (i == cv_usejoystick3.value)) - || (setupcontrolplayer == 2 && (i == cv_usejoystick2.value)) - || (setupcontrolplayer == 1 && (i == cv_usejoystick.value))) - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,recommendedflags,joystickInfo[i]); +#ifdef JOYSTICK_HOTPLUG + if (atoi(cv_usejoystick4.string) > I_NumJoys()) + compareval4 = atoi(cv_usejoystick4.string); + else + compareval4 = cv_usejoystick4.value; + + if (atoi(cv_usejoystick3.string) > I_NumJoys()) + compareval3 = atoi(cv_usejoystick3.string); + else + compareval3 = cv_usejoystick3.value; + + 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 + compareval4 = cv_usejoystick4.value; + compareval3 = cv_usejoystick3.value; + compareval2 = cv_usejoystick2.value; + compareval = cv_usejoystick.value +#endif + + if ((setupcontrolplayer == 4 && (i == compareval4)) + || (setupcontrolplayer == 3 && (i == compareval3)) + || (setupcontrolplayer == 2 && (i == compareval2)) + || (setupcontrolplayer == 1 && (i == compareval))) + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,joystickInfo[i]); else V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,0,joystickInfo[i]); } } -static void M_SetupJoystickMenu(INT32 choice) +void M_SetupJoystickMenu(INT32 choice) { INT32 i = 0; const char *joyNA = "Unavailable"; @@ -8598,6 +8636,25 @@ static void M_SetupJoystickMenu(INT32 choice) strncpy(joystickInfo[i], I_GetJoyName(i), 28); else strcpy(joystickInfo[i], joyNA); + +#ifdef JOYSTICK_HOTPLUG + // We use cv_usejoystick.string as the USER-SET var + // and cv_usejoystick.value as the INTERNAL var + // + // 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. + if (i == cv_usejoystick.value) + CV_SetValue(&cv_usejoystick, i); + if (i == cv_usejoystick2.value) + CV_SetValue(&cv_usejoystick2, i); + if (i == cv_usejoystick3.value) + CV_SetValue(&cv_usejoystick3, i); + if (i == cv_usejoystick4.value) + CV_SetValue(&cv_usejoystick4, i); +#endif } M_SetupNextMenu(&OP_JoystickSetDef); @@ -8626,21 +8683,147 @@ static void M_Setup3PJoystickMenu(INT32 choice) static void M_Setup4PJoystickMenu(INT32 choice) { - setupcontrolplayer = 3; + setupcontrolplayer = 4; OP_JoystickSetDef.prevMenu = &OP_Joystick4Def; M_SetupJoystickMenu(choice); } static void M_AssignJoystick(INT32 choice) { +#ifdef JOYSTICK_HOTPLUG + INT32 oldchoice, oldstringchoice; + INT32 numjoys = I_NumJoys(); + + if (setupcontrolplayer == 4) + { + oldchoice = oldstringchoice = atoi(cv_usejoystick4.string) > numjoys ? atoi(cv_usejoystick4.string) : cv_usejoystick4.value; + CV_SetValue(&cv_usejoystick4, choice); + + // 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_usejoystick4, cv_usejoystick4.value); + + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick4.value; + + if (oldchoice != choice) + { + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick4, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); + + if (oldstringchoice == + (atoi(cv_usejoystick4.string) > numjoys ? atoi(cv_usejoystick4.string) : cv_usejoystick4.value)) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } + } + else if (setupcontrolplayer == 3) + { + oldchoice = oldstringchoice = atoi(cv_usejoystick3.string) > numjoys ? atoi(cv_usejoystick3.string) : cv_usejoystick3.value; + CV_SetValue(&cv_usejoystick3, choice); + + // 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_usejoystick3, cv_usejoystick3.value); + + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick3.value; + + if (oldchoice != choice) + { + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick3, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); + + if (oldstringchoice == + (atoi(cv_usejoystick3.string) > numjoys ? atoi(cv_usejoystick3.string) : cv_usejoystick3.value)) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } + } + else if (setupcontrolplayer == 2) + { + oldchoice = oldstringchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; + CV_SetValue(&cv_usejoystick2, choice); + + // 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); + + // 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 joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } + } + else if (setupcontrolplayer == 1) + { + oldchoice = oldstringchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; + CV_SetValue(&cv_usejoystick, choice); + + // 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_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 joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } + } +#else if (setupcontrolplayer == 4) CV_SetValue(&cv_usejoystick4, choice); else if (setupcontrolplayer == 3) CV_SetValue(&cv_usejoystick3, choice); else if (setupcontrolplayer == 2) CV_SetValue(&cv_usejoystick2, choice); - else + else if (setupcontrolplayer == 1) CV_SetValue(&cv_usejoystick, choice); +#endif } // ============= diff --git a/src/m_menu.h b/src/m_menu.h index 79e14d4b3..9509004b4 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -69,7 +69,6 @@ void M_QuitResponse(INT32 ch); // Determines whether to show a level in the list boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); - // flags for items in the menu // menu handle (what we do when key is pressed #define IT_TYPE 14 // (2+4+8) @@ -173,6 +172,10 @@ extern menu_t *currentMenu; extern menu_t MainDef; extern menu_t SP_LoadDef; +// Call upon joystick hotplug +void M_SetupJoystickMenu(INT32 choice); +extern menu_t OP_JoystickSetDef; + // Stuff for customizing the player select screen typedef struct { diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index bfd897287..f85176183 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -856,6 +856,220 @@ void I_JoyScale4(void) JoyInfo4.scale = Joystick4.bGamepadStyle?1:cv_joyscale4.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 && JoyInfo3.dev != test && JoyInfo4.dev != test) + SDL_JoystickClose(test); + } + + return -1; +} + +// Misleading function: updates device indices for all players BUT the one specified. +// Necessary for SDL_JOYDEVICEADDED events +void I_UpdateJoystickDeviceIndices(INT32 player) +{ + if (player != 1) // This is a fucking mess. + { + ////////////////////////////// + // update joystick 1's device index + ////////////////////////////// + + if (JoyInfo.dev) + cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; + // is cv_usejoystick used? + else if (// don't check JoyInfo or cv_usejoystick; we're currently operating on those + atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick2.value + && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick3.value + && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick4.value) + cv_usejoystick.value = atoi(cv_usejoystick.string); + // is cv_usejoystick2 used? + else if ( // don't check JoyInfo or cv_usejoystick; we're currently operating on those + atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value + && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick3.value + && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick4.value) + cv_usejoystick.value = atoi(cv_usejoystick2.string); + // is cv_usejoystick3 used? + else if (// don't check JoyInfo or cv_usejoystick; we're currently operating on those + atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick2.value + && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick4.value) + cv_usejoystick.value = atoi(cv_usejoystick3.string); + // is cv_usejoystick4 used? + else if (// don't check JoyInfo or cv_usejoystick; we're currently operating on those + atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick2.value + && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick3.value + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick4.value) + cv_usejoystick.value = atoi(cv_usejoystick4.string); + else // we tried... + cv_usejoystick.value = 0; + } + + if (player != 2) + { + ////////////////////////////// + // update joystick 2's device index + ////////////////////////////// + + if (JoyInfo2.dev) + cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; + // is cv_usejoystick2 used? + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick.value + // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those + && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick3.value + && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick4.value) + cv_usejoystick2.value = atoi(cv_usejoystick2.string); + // is cv_usejoystick used? + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value + // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those + && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick3.value + && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick4.value) + cv_usejoystick2.value = atoi(cv_usejoystick.string); + // is cv_usejoystick3 used? + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick.value + // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those + && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick4.value) + cv_usejoystick2.value = atoi(cv_usejoystick3.string); + // is cv_usejoystick4 used? + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick.value + // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those + && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick3.value + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick4.value) + cv_usejoystick2.value = atoi(cv_usejoystick4.string); + else // we tried... + cv_usejoystick2.value = 0; + } + + if (player != 3) + { + ////////////////////////////// + // update joystick 3's device index + ////////////////////////////// + + if (JoyInfo3.dev) + cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + // is cv_usejoystick3 used? + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick.value + && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick2.value + // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick4.value) + cv_usejoystick3.value = atoi(cv_usejoystick3.string); + // is cv_usejoystick used? + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value + && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick2.value + // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those + && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick4.value) + cv_usejoystick3.value = atoi(cv_usejoystick.string); + // is cv_usejoystick2 used? + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick.value + && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value + // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those + && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick4.value) + cv_usejoystick3.value = atoi(cv_usejoystick2.string); + // is cv_usejoystick4 used? + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick.value + && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick2.value + // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick4.value) + cv_usejoystick3.value = atoi(cv_usejoystick4.string); + else // we tried... + cv_usejoystick3.value = 0; + } + + if (player != 4) + { + ////////////////////////////// + // update joystick 4's device index + ////////////////////////////// + + if (JoyInfo4.dev) + cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + // is cv_usejoystick4 used? + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick.value + && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick2.value + && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick3.value) + // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those + cv_usejoystick4.value = atoi(cv_usejoystick4.string); + // is cv_usejoystick used? + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value + && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick2.value + && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick3.value) + // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those + cv_usejoystick4.value = atoi(cv_usejoystick.string); + // is cv_usejoystick2 used? + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick.value + && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value + && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick3.value) + // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those + cv_usejoystick4.value = atoi(cv_usejoystick2.string); + // is cv_usejoystick3 used? + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick.value + && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick2.value + && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those + cv_usejoystick4.value = atoi(cv_usejoystick3.string); + else // we tried... + cv_usejoystick4.value = 0; + } +} + /** \brief Joystick 1 buttons states */ static UINT64 lastjoybuttons = 0; @@ -871,7 +1085,7 @@ static UINT64 lastjoyhats = 0; */ -static void I_ShutdownJoystick(void) +void I_ShutdownJoystick(void) { INT32 i; event_t event; @@ -905,15 +1119,8 @@ static void I_ShutdownJoystick(void) joystick_started = 0; JoyReset(&JoyInfo); - if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started - && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - if (cv_usejoystick.value == 0) - { - I_OutputMsg("I_Joystick: SDL's Joystick system has been shutdown\n"); - } - } + + // don't shut down the subsystem here, because hotplugging } void I_GetJoystickEvents(void) @@ -1054,74 +1261,66 @@ void I_GetJoystickEvents(void) */ -static int joy_open(const char *fname) +static int joy_open(int joyindex) { - int joyindex = atoi(fname); + SDL_Joystick *newdev = NULL; int num_joy = 0; - int i; - if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0) + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return -1; - } - else - { - num_joy = SDL_NumJoysticks(); - } + CONS_Printf(M_GetText("Joystick subsystem not started\n")); + return -1; + } - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - I_ShutdownJoystick(); - return -1; - } - } - else - { - JoyReset(&JoyInfo); - //I_ShutdownJoystick(); - //joy_open(fname); - } + if (joyindex <= 0) + return -1; num_joy = SDL_NumJoysticks(); - if (joyindex <= 0 || num_joy == 0 || JoyInfo.oldjoy == joyindex) + if (num_joy == 0) { -// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); - if (num_joy != 0) - { - CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - } - else - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - if (joyindex <= 0 || num_joy == 0) return 0; + CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); + return -1; } - JoyInfo.dev = SDL_JoystickOpen(joyindex-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_Printf(M_GetText("Couldn't open joystick: %s\n"), SDL_GetError()); - I_ShutdownJoystick(); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: Couldn't open device - %s\n"), SDL_GetError()); return -1; } else { - CONS_Printf(M_GetText("Joystick: %s\n"), SDL_JoystickName(JoyInfo.dev)); + 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) + /* if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); - I_ShutdownJoystick(); return 0; }*/ @@ -1156,7 +1355,7 @@ static UINT64 lastjoy2hats = 0; \return void */ -static void I_ShutdownJoystick2(void) +void I_ShutdownJoystick2(void) { INT32 i; event_t event; @@ -1190,15 +1389,8 @@ static void I_ShutdownJoystick2(void) joystick2_started = 0; JoyReset(&JoyInfo2); - if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started - && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - if (cv_usejoystick2.value == 0) - { - DEBFILE("I_Joystick2: SDL's Joystick system has been shutdown\n"); - } - } + + // don't shut down the subsystem here, because hotplugging } void I_GetJoystick2Events(void) @@ -1341,72 +1533,66 @@ void I_GetJoystick2Events(void) */ -static int joy_open2(const char *fname) +static int joy_open2(int joyindex) { - int joyindex = atoi(fname); + SDL_Joystick *newdev = NULL; int num_joy = 0; - int i; - if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0) + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return -1; - } - else - num_joy = SDL_NumJoysticks(); + CONS_Printf(M_GetText("Joystick subsystem not started\n")); + return -1; + } - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - I_ShutdownJoystick2(); - return -1; - } - } - else - { - JoyReset(&JoyInfo2); - //I_ShutdownJoystick(); - //joy_open(fname); - } + if (joyindex <= 0) + return -1; num_joy = SDL_NumJoysticks(); - if (joyindex <= 0 || num_joy == 0 || JoyInfo2.oldjoy == joyindex) + if (num_joy == 0) { -// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); - if (num_joy != 0) - { - CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - } - else - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - if (joyindex <= 0 || num_joy == 0) return 0; + CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); + return -1; } - JoyInfo2.dev = SDL_JoystickOpen(joyindex-1); + newdev = SDL_JoystickOpen(joyindex-1); - if (!JoyInfo2.dev) + // 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) { - CONS_Printf(M_GetText("Couldn't open joystick2: %s\n"), SDL_GetError()); + 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_Printf(M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev)); + 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) +/* if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); - I_ShutdownJoystick2(); return 0; }*/ @@ -1441,7 +1627,7 @@ static UINT64 lastjoy3hats = 0; \return void */ -static void I_ShutdownJoystick3(void) +void I_ShutdownJoystick3(void) { INT32 i; event_t event; @@ -1473,16 +1659,10 @@ static void I_ShutdownJoystick3(void) D_PostEvent(&event); } + joystick3_started = 0; JoyReset(&JoyInfo3); - if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started - && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - if (cv_usejoystick3.value == 0) - { - DEBFILE("I_Joystick3: SDL's Joystick system has been shutdown\n"); - } - } + + // don't shutdown the subsystem here, because hotplugging } void I_GetJoystick3Events(void) @@ -1624,73 +1804,67 @@ void I_GetJoystick3Events(void) */ -static int joy_open3(const char *fname) +static int joy_open3(int joyindex) { - int joyindex = atoi(fname); + SDL_Joystick *newdev = NULL; int num_joy = 0; - int i; - if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0) + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return -1; - } - else - num_joy = SDL_NumJoysticks(); + CONS_Printf(M_GetText("Joystick subsystem not started\n")); + return -1; + } - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - I_ShutdownJoystick3(); - return -1; - } - } - else - { - JoyReset(&JoyInfo3); - //I_ShutdownJoystick(); - //joy_open(fname); - } + if (joyindex <= 0) + return -1; num_joy = SDL_NumJoysticks(); - if (joyindex <= 0 || num_joy == 0 || JoyInfo3.oldjoy == joyindex) + if (num_joy == 0) { -// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); - if (num_joy != 0) - { - CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - } - else - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - if (joyindex <= 0 || num_joy == 0) return 0; + CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); + return -1; } - JoyInfo3.dev = SDL_JoystickOpen(joyindex-1); + newdev = SDL_JoystickOpen(joyindex - 1); - if (!JoyInfo3.dev) + // 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 (JoyInfo3.dev) { - CONS_Printf(M_GetText("Couldn't open joystick3: %s\n"), SDL_GetError()); + if (JoyInfo3.dev == newdev // same device, nothing to do + || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo3.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, "Joystick3 device is changing; resetting events...\n"); I_ShutdownJoystick3(); + } + + JoyInfo3.dev = newdev; + + if (JoyInfo3.dev == NULL) + { + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick3: couldn't open device - %s\n"), SDL_GetError()); return -1; } else { - CONS_Printf(M_GetText("Joystick3: %s\n"), SDL_JoystickName(JoyInfo3.dev)); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick3: %s\n"), SDL_JoystickName(JoyInfo3.dev)); JoyInfo3.axises = SDL_JoystickNumAxes(JoyInfo3.dev); - if (JoyInfo3.axises > JOYAXISSET*2) - JoyInfo3.axises = JOYAXISSET*2; -/* if (joyaxes < 2) + if (JoyInfo3.axises > JOYAXISSET * 2) + JoyInfo3.axises = JOYAXISSET * 2; + /* if (joyaxes<2) { - I_OutputMsg("Not enought axes?\n"); - I_ShutdownJoystick3(); - return 0; + I_OutputMsg("Not enought axes?\n"); + return 0; }*/ JoyInfo3.buttons = SDL_JoystickNumButtons(JoyInfo3.dev); @@ -1724,7 +1898,7 @@ static UINT64 lastjoy4hats = 0; \return void */ -static void I_ShutdownJoystick4(void) +void I_ShutdownJoystick4(void) { INT32 i; event_t event; @@ -1756,16 +1930,10 @@ static void I_ShutdownJoystick4(void) D_PostEvent(&event); } + joystick4_started = 0; JoyReset(&JoyInfo4); - if (!joystick_started && !joystick2_started && !joystick3_started && !joystick4_started - && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - if (cv_usejoystick4.value == 0) - { - DEBFILE("I_Joystick4: SDL's Joystick system has been shutdown\n"); - } - } + + // don't shutdown the subsystem here, because hotplugging } void I_GetJoystick4Events(void) @@ -1907,73 +2075,67 @@ void I_GetJoystick4Events(void) */ -static int joy_open4(const char *fname) +static int joy_open4(int joyindex) { - int joyindex = atoi(fname); + SDL_Joystick *newdev = NULL; int num_joy = 0; - int i; - if (joystick_started == 0 && joystick2_started == 0 && joystick3_started == 0 && joystick4_started == 0) + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return -1; - } - else - num_joy = SDL_NumJoysticks(); + CONS_Printf(M_GetText("Joystick subsystem not started\n")); + return -1; + } - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - I_ShutdownJoystick4(); - return -1; - } - } - else - { - JoyReset(&JoyInfo4); - //I_ShutdownJoystick(); - //joy_open(fname); - } + if (joyindex <= 0) + return -1; num_joy = SDL_NumJoysticks(); - if (joyindex <= 0 || num_joy == 0 || JoyInfo4.oldjoy == joyindex) + if (num_joy == 0) { -// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); - if (num_joy != 0) - { - CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - } - else - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - if (joyindex <= 0 || num_joy == 0) return 0; + CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); + return -1; } - JoyInfo4.dev = SDL_JoystickOpen(joyindex-1); + newdev = SDL_JoystickOpen(joyindex - 1); - if (!JoyInfo4.dev) + // 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 (JoyInfo4.dev) { - CONS_Printf(M_GetText("Couldn't open joystick4: %s\n"), SDL_GetError()); + if (JoyInfo4.dev == newdev // same device, nothing to do + || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo4.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, "Joystick4 device is changing; resetting events...\n"); I_ShutdownJoystick4(); + } + + JoyInfo4.dev = newdev; + + if (JoyInfo4.dev == NULL) + { + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick4: couldn't open device - %s\n"), SDL_GetError()); return -1; } else { - CONS_Printf(M_GetText("Joystick4: %s\n"), SDL_JoystickName(JoyInfo4.dev)); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick4: %s\n"), SDL_JoystickName(JoyInfo4.dev)); JoyInfo4.axises = SDL_JoystickNumAxes(JoyInfo4.dev); - if (JoyInfo4.axises > JOYAXISSET*2) - JoyInfo4.axises = JOYAXISSET*2; -/* if (joyaxes < 2) + if (JoyInfo4.axises > JOYAXISSET * 2) + JoyInfo4.axises = JOYAXISSET * 2; + /* if (joyaxes<2) { - I_OutputMsg("Not enought axes?\n"); - I_ShutdownJoystick4(); - return 0; + I_OutputMsg("Not enought axes?\n"); + return 0; }*/ JoyInfo4.buttons = SDL_JoystickNumButtons(JoyInfo4.dev); @@ -1986,7 +2148,7 @@ static int joy_open4(const char *fname) JoyInfo4.balls = SDL_JoystickNumBalls(JoyInfo4.dev); - //Joystick4.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo4.dev), "pad"); + //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo4.dev), "pad"); return JoyInfo4.axises; } @@ -1997,91 +2159,199 @@ static int joy_open4(const char *fname) // void I_InitJoystick(void) { - I_ShutdownJoystick(); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (!strcmp(cv_usejoystick.string, "0") || M_CheckParm("-nojoy")) + SDL_Joystick *newjoy = NULL; + + //I_ShutdownJoystick(); + //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + if (M_CheckParm("-nojoy")) return; - if (joy_open(cv_usejoystick.string) != -1) - JoyInfo.oldjoy = atoi(cv_usejoystick.string); + + 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 || JoyInfo3.dev == newjoy || JoyInfo4.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; - return; + joystick_started = 0; } - joystick_started = 1; + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick2(void) { - I_ShutdownJoystick2(); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (!strcmp(cv_usejoystick2.string, "0") || M_CheckParm("-nojoy")) + SDL_Joystick *newjoy = NULL; + + //I_ShutdownJoystick2(); + //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + if (M_CheckParm("-nojoy")) return; - if (joy_open2(cv_usejoystick2.string) != -1) - JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); + + 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 || JoyInfo3.dev == newjoy || JoyInfo4.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; - return; + joystick2_started = 0; } - joystick2_started = 1; + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick3(void) { - I_ShutdownJoystick3(); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (!strcmp(cv_usejoystick3.string, "0") || M_CheckParm("-nojoy")) + SDL_Joystick *newjoy = NULL; + + //I_ShutdownJoystick3(); + //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + if (M_CheckParm("-nojoy")) return; - if (joy_open3(cv_usejoystick3.string) != -1) - JoyInfo3.oldjoy = atoi(cv_usejoystick3.string); + + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) + { + CONS_Printf("I_InitJoystick3()...\n"); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) + { + CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); + return; + } + } + + if (cv_usejoystick3.value) + newjoy = SDL_JoystickOpen(cv_usejoystick3.value - 1); + + if (newjoy && (JoyInfo.dev == newjoy || JoyInfo2.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device + cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + else if (newjoy && joy_open3(cv_usejoystick3.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. + JoyInfo3.oldjoy = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + joystick3_started = 1; + } else { + if (JoyInfo3.oldjoy) + I_ShutdownJoystick3(); cv_usejoystick3.value = 0; - return; + joystick3_started = 0; } - joystick3_started = 1; + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick4(void) { - I_ShutdownJoystick4(); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (!strcmp(cv_usejoystick4.string, "0") || M_CheckParm("-nojoy")) + SDL_Joystick *newjoy = NULL; + + //I_ShutdownJoystick4(); + //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + if (M_CheckParm("-nojoy")) return; - if (joy_open4(cv_usejoystick4.string) != -1) - JoyInfo4.oldjoy = atoi(cv_usejoystick4.string); + + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) + { + CONS_Printf("I_InitJoystick4()...\n"); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) + { + CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); + return; + } + } + + if (cv_usejoystick4.value) + newjoy = SDL_JoystickOpen(cv_usejoystick4.value - 1); + + if (newjoy && (JoyInfo.dev == newjoy || JoyInfo2.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device + cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + else if (newjoy && joy_open4(cv_usejoystick4.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. + JoyInfo4.oldjoy = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + joystick4_started = 1; + } else { + if (JoyInfo4.oldjoy) + I_ShutdownJoystick4(); cv_usejoystick4.value = 0; - return; + joystick4_started = 0; } - joystick4_started = 1; + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } static void I_ShutdownInput(void) { + // 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(); + I_ShutdownJoystick3(); + I_ShutdownJoystick4(); + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { - JoyReset(&JoyInfo); - JoyReset(&JoyInfo2); - JoyReset(&JoyInfo3); - JoyReset(&JoyInfo4); + 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) == 0) - { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1) - numjoy = SDL_NumJoysticks(); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } - else + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) numjoy = SDL_NumJoysticks(); return numjoy; } @@ -2091,18 +2361,9 @@ static char joyname[255]; // MAX_PATH; joystick name is straight from the driver const char *I_GetJoyName(INT32 joyindex) { const char *tempname = NULL; + joyname[0] = 0; joyindex--; //SDL's Joystick System starts at 0, not 1 - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1) - { - tempname = SDL_JoystickNameForIndex(joyindex); - if (tempname) - strncpy(joyname, tempname, 255); - } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } - else + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { tempname = SDL_JoystickNameForIndex(joyindex); if (tempname) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 5e6f2c273..f63e98476 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -72,6 +72,7 @@ #include "../console.h" #include "../command.h" #include "sdlmain.h" +#include "../i_system.h" #ifdef HWRENDER #include "../hardware/hw_main.h" #include "../hardware/hw_drv.h" @@ -951,6 +952,284 @@ void I_GetEvent(void) case SDL_JOYBUTTONDOWN: Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); break; + + //////////////////////////////////////////////////////////// + + case SDL_JOYDEVICEADDED: + { + // OH BOY are you in for a good time! #abominationstation + + 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! + //////////////////////////////////////////////////////////// + + ////////////////////////////// + // PLAYER 1 + ////////////////////////////// + + if (newjoy && (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) + && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + { + cv_usejoystick.value = evt.jdevice.which + 1; + I_UpdateJoystickDeviceIndices(1); + } + + ////////////////////////////// + // PLAYER 2 + ////////////////////////////// + + else if (newjoy && (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) + && JoyInfo.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + { + cv_usejoystick2.value = evt.jdevice.which + 1; + I_UpdateJoystickDeviceIndices(2); + } + + ////////////////////////////// + // PLAYER 3 + ////////////////////////////// + + else if (newjoy && (!JoyInfo3.dev || !SDL_JoystickGetAttached(JoyInfo3.dev)) + && JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + { + cv_usejoystick3.value = evt.jdevice.which + 1; + I_UpdateJoystickDeviceIndices(3); + } + + ////////////////////////////// + // PLAYER 4 + ////////////////////////////// + + else if (newjoy && (!JoyInfo4.dev || !SDL_JoystickGetAttached(JoyInfo4.dev)) + && JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy) // don't override a currently active device + { + cv_usejoystick4.value = evt.jdevice.which + 1; + I_UpdateJoystickDeviceIndices(4); + } + + //////////////////////////////////////////////////////////// + // 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); + + if (!strcmp(cv_usejoystick3.string, "0") || !cv_usejoystick3.value) + cv_usejoystick3.value = 0; + else if (atoi(cv_usejoystick3.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick3.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick3, cv_usejoystick3.value); + + if (!strcmp(cv_usejoystick4.string, "0") || !cv_usejoystick4.value) + cv_usejoystick4.value = 0; + else if (atoi(cv_usejoystick4.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick4.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick4, cv_usejoystick4.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(); + I_InitJoystick3(); + I_InitJoystick4(); + + //////////////////////////////////////////////////////////// + + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy); + + // update the menu + if (currentMenu == &OP_JoystickSetDef) + M_SetupJoystickMenu(0); + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); + } + break; + + //////////////////////////////////////////////////////////// + + case SDL_JOYDEVICEREMOVED: + if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev)) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick1 removed, device index: %d\n", JoyInfo.oldjoy); + I_ShutdownJoystick(); + } + + if (JoyInfo2.dev && !SDL_JoystickGetAttached(JoyInfo2.dev)) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick2 removed, device index: %d\n", JoyInfo2.oldjoy); + I_ShutdownJoystick2(); + } + + if (JoyInfo3.dev && !SDL_JoystickGetAttached(JoyInfo3.dev)) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick3 removed, device index: %d\n", JoyInfo3.oldjoy); + I_ShutdownJoystick3(); + } + + if (JoyInfo4.dev && !SDL_JoystickGetAttached(JoyInfo4.dev)) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick4 removed, device index: %d\n", JoyInfo4.oldjoy); + I_ShutdownJoystick4(); + } + + //////////////////////////////////////////////////////////// + // 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 + && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick4.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_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick4.string); + else // we tried... + cv_usejoystick2.value = 0; + + if (JoyInfo3.dev) + cv_usejoystick3.value = JoyInfo3.oldjoy = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick4.string); + else // we tried... + cv_usejoystick3.value = 0; + + if (JoyInfo4.dev) + cv_usejoystick4.value = JoyInfo4.oldjoy = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick4.string); + else // we tried... + cv_usejoystick4.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); + + if (!strcmp(cv_usejoystick3.string, "0")) + cv_usejoystick3.value = 0; + else if (atoi(cv_usejoystick3.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick3.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick3, cv_usejoystick3.value); + + if (!strcmp(cv_usejoystick4.string, "0")) + cv_usejoystick4.value = 0; + else if (atoi(cv_usejoystick4.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick4.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick4, cv_usejoystick4.value); + + //////////////////////////////////////////////////////////// + + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy); + + // update the menu + if (currentMenu == &OP_JoystickSetDef) + M_SetupJoystickMenu(0); + break; case SDL_QUIT: I_Quit(); M_QuitResponse('y'); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 93588ebba..0bc771a71 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -31,6 +31,9 @@ extern SDL_bool framebuffer; #define SDL2STUB() CONS_Printf("SDL2: stubbed: %s:%d\n", __func__, __LINE__) #endif +// So m_menu knows whether to store cv_usejoystick value or string +#define JOYSTICK_HOTPLUG + /** \brief The JoyInfo_s struct info about joystick @@ -77,6 +80,20 @@ extern SDLJoyInfo_t JoyInfo4; void I_GetConsoleEvents(void); +// So we can call this from i_video event loop +void I_ShutdownJoystick(void); +void I_ShutdownJoystick2(void); +void I_ShutdownJoystick3(void); +void I_ShutdownJoystick4(void); + +// Cheat to get the device index for a joystick handle +INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev); + +// Quick thing to make SDL_JOYDEVICEADDED events less of an abomination +void I_UpdateJoystickDeviceIndices(INT32 player); + +void I_GetConsoleEvents(void); + void SDLforceUngrabMouse(void); // Needed for some WIN32 functions