diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d03b5df63..3619bee9d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4151,9 +4151,9 @@ static void Command_Version_f(void) // OS // Would be nice to use SDL_GetPlatform for this -#if defined(_WIN32) +#if defined (_WIN32) || defined (_WIN64) CONS_Printf("Windows "); -#elif defined(LINUX) +#elif defined(__linux__) CONS_Printf("Linux "); #elif defined(MACOSX) CONS_Printf("macOS" ); diff --git a/src/m_menu.c b/src/m_menu.c index f961062ba..de18f4a12 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, ...); @@ -8570,7 +8577,7 @@ static void M_ScreenshotOptions(INT32 choice) static void M_DrawJoystick(void) { - INT32 i; + INT32 i, compareval4, compareval3, compareval2, compareval; M_DrawGenericMenu(); @@ -8579,11 +8586,38 @@ 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]); } @@ -8604,6 +8638,25 @@ 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); @@ -8639,14 +8692,140 @@ static void M_Setup4PJoystickMenu(INT32 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/sdl/i_system.c b/src/sdl/i_system.c index 6df47e56b..c8be862de 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -856,6 +856,22 @@ 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) + SDL_JoystickClose(test); + } + + return -1; +} /** \brief Joystick 1 buttons states */ static UINT64 lastjoybuttons = 0; @@ -1047,11 +1063,10 @@ 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 (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { @@ -1059,51 +1074,53 @@ static int joy_open(const char *fname) return -1; } - JoyReset(&JoyInfo); - if (joyindex <= 0) - return 0; + return -1; num_joy = SDL_NumJoysticks(); - if (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)); - - 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)); - return 0; - } - } - else - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - 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()); + 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"); return 0; @@ -1318,11 +1335,10 @@ 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 (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { @@ -1330,47 +1346,49 @@ static int joy_open2(const char *fname) return -1; } - JoyReset(&JoyInfo2); - if (joyindex <= 0) - return 0; + return -1; num_joy = SDL_NumJoysticks(); - if (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)); - - 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)); - return 0; - } - } - else - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - 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); + + // 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_Printf(M_GetText("Couldn't open joystick2: %s\n"), SDL_GetError()); + 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; @@ -1588,11 +1606,10 @@ 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 (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { @@ -1600,54 +1617,56 @@ static int joy_open3(const char *fname) return -1; } - JoyReset(&JoyInfo3); - if (joyindex <= 0) - return 0; + return -1; num_joy = SDL_NumJoysticks(); - if (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)); - - 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)); - return 0; - } - } - else - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - 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); + + // 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) + { + 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_Printf(M_GetText("Couldn't open joystick3: %s\n"), SDL_GetError()); + 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 (joyaxes<2) { - I_OutputMsg("Not enought axes?\n"); - return 0; + I_OutputMsg("Not enought axes?\n"); + return 0; }*/ JoyInfo3.buttons = SDL_JoystickNumButtons(JoyInfo3.dev); @@ -1858,11 +1877,10 @@ 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 (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { @@ -1870,54 +1888,56 @@ static int joy_open4(const char *fname) return -1; } - JoyReset(&JoyInfo4); - if (joyindex <= 0) - return 0; + return -1; num_joy = SDL_NumJoysticks(); - if (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)); - - 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)); - return 0; - } - } - else - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - 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); + + // 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) + { + 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_Printf(M_GetText("Couldn't open joystick4: %s\n"), SDL_GetError()); + 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 (joyaxes<2) { - I_OutputMsg("Not enought axes?\n"); - return 0; + I_OutputMsg("Not enought axes?\n"); + return 0; }*/ JoyInfo4.buttons = SDL_JoystickNumButtons(JoyInfo4.dev); @@ -1941,6 +1961,8 @@ static int joy_open4(const char *fname) // void I_InitJoystick(void) { + SDL_Joystick *newjoy = NULL; + //I_ShutdownJoystick(); //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (M_CheckParm("-nojoy")) @@ -1948,7 +1970,8 @@ void I_InitJoystick(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - CONS_Printf("Initializing joy system\n"); + CONS_Printf("I_InitJoystick()...\n"); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); @@ -1956,9 +1979,16 @@ void I_InitJoystick(void) } } - if (strcmp(cv_usejoystick.string, "0") && joy_open(cv_usejoystick.string) != -1) + 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) { - JoyInfo.oldjoy = atoi(cv_usejoystick.string); + // 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 @@ -1968,10 +1998,15 @@ void I_InitJoystick(void) cv_usejoystick.value = 0; joystick_started = 0; } + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick2(void) { + SDL_Joystick *newjoy = NULL; + //I_ShutdownJoystick2(); //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (M_CheckParm("-nojoy")) @@ -1979,7 +2014,7 @@ void I_InitJoystick2(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - CONS_Printf("Initializing joy system\n"); + CONS_Printf("I_InitJoystick2()...\n"); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); @@ -1987,9 +2022,16 @@ void I_InitJoystick2(void) } } - if (strcmp(cv_usejoystick2.string, "0") && joy_open2(cv_usejoystick2.string) != -1) + 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) { - JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); + // 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 @@ -2000,10 +2042,14 @@ void I_InitJoystick2(void) joystick2_started = 0; } + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick3(void) { + SDL_Joystick *newjoy = NULL; + //I_ShutdownJoystick3(); //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (M_CheckParm("-nojoy")) @@ -2011,7 +2057,7 @@ void I_InitJoystick3(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - CONS_Printf("Initializing joy system\n"); + CONS_Printf("I_InitJoystick3()...\n"); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); @@ -2019,9 +2065,16 @@ void I_InitJoystick3(void) } } - if (strcmp(cv_usejoystick3.string, "0") || joy_open3(cv_usejoystick3.string) != -1) + 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) { - JoyInfo3.oldjoy = atoi(cv_usejoystick3.string); + // 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 @@ -2031,10 +2084,15 @@ void I_InitJoystick3(void) cv_usejoystick3.value = 0; joystick3_started = 0; } + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick4(void) { + SDL_Joystick *newjoy = NULL; + //I_ShutdownJoystick4(); //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (M_CheckParm("-nojoy")) @@ -2042,7 +2100,7 @@ void I_InitJoystick4(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - CONS_Printf("Initializing joy system\n"); + CONS_Printf("I_InitJoystick4()...\n"); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); @@ -2050,9 +2108,16 @@ void I_InitJoystick4(void) } } - if (strcmp(cv_usejoystick4.string, "0") || joy_open4(cv_usejoystick4.string) != -1) + 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) { - JoyInfo4.oldjoy = atoi(cv_usejoystick4.string); + // 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 @@ -2062,6 +2127,9 @@ void I_InitJoystick4(void) cv_usejoystick4.value = 0; joystick4_started = 0; } + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + SDL_JoystickClose(newjoy); } static void I_ShutdownInput(void) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index da4c43196..e0d78abca 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -117,9 +117,6 @@ static INT32 firstEntry = 0; // Total mouse motion X/Y offsets static INT32 mousemovex = 0, mousemovey = 0; -// Keep track of joy unplugged count -static INT32 joyunplugcount = 0; - // SDL vars static SDL_Surface *vidSurface = NULL; static SDL_Surface *bufSurface = NULL; @@ -949,50 +946,407 @@ void I_GetEvent(void) Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); break; case SDL_JOYDEVICEADDED: - CONS_Printf("Joy device %d added\n", evt.jdevice.which); - - // recounts hotplugged joysticks - I_InitJoystick(); - I_InitJoystick2(); - I_InitJoystick3(); - I_InitJoystick4(); - - // update the menu - if (currentMenu == &OP_JoystickSetDef) - M_SetupJoystickMenu(0); - break; - case SDL_JOYDEVICEREMOVED: { - // every time a device is unplugged, the "which" index increments by 1? - INT32 deviceIdx = evt.jdevice.which - joyunplugcount++; + SDL_Joystick *newjoy = SDL_JoystickOpen(evt.jdevice.which); - if (JoyInfo.oldjoy - 1 == deviceIdx) - CONS_Printf("Joy device %d removed%s\n", deviceIdx, " was first joystick"); - else if (JoyInfo2.oldjoy-1 == deviceIdx) - CONS_Printf("Joy device %d removed%s\n", deviceIdx, " was second joystick"); - else if (JoyInfo3.oldjoy - 1 == deviceIdx) - CONS_Printf("Joy device %d removed%s\n", deviceIdx, " was third joystick"); - else if (JoyInfo4.oldjoy - 1 == deviceIdx) - CONS_Printf("Joy device %d removed%s\n", deviceIdx, " was fourth joystick"); - /*CONS_Printf("Joy device %d removed%s\n", deviceIdx, - (JoyInfo.oldjoy-1 == deviceIdx) ? " was first joystick" : - (JoyInfo2.oldjoy-1 == deviceIdx) ? " was second joystick" : "");*/ + CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1); - // I_ShutdownJoystick doesn't shut down the subsystem - // It just fires neutral joy events to clean up the unplugged joy - if (JoyInfo.oldjoy-1 == deviceIdx) - I_ShutdownJoystick(); - if (JoyInfo2.oldjoy-1 == deviceIdx) - I_ShutdownJoystick2(); - if (JoyInfo3.oldjoy - 1 == deviceIdx) - I_ShutdownJoystick3(); - if (JoyInfo4.oldjoy - 1 == deviceIdx) - I_ShutdownJoystick4(); + + // 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)) // PLAYER 1 + && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + { + cv_usejoystick.value = evt.jdevice.which + 1; + + if (JoyInfo2.dev) // update joystick 2's device index + 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 if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick2.value = atoi(cv_usejoystick3.string); + else if (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 (JoyInfo3.dev) // update joystick 3's device index + cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick.value) + cv_usejoystick3.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick3.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick3.value = atoi(cv_usejoystick2.string); + else if (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 (JoyInfo4.dev) // update joystick 4's device index + cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick.value) + cv_usejoystick4.value = atoi(cv_usejoystick4.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick4.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick4.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick4.value = atoi(cv_usejoystick3.string); + else // we tried... + cv_usejoystick4.value = 0; + } + else if (newjoy && (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) // PLAYER 2 + && JoyInfo.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + { + cv_usejoystick2.value = evt.jdevice.which + 1; + + if (JoyInfo.dev) // update joystick 1's device index + 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 if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick.value = atoi(cv_usejoystick3.string); + else if (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 (JoyInfo3.dev) // update joystick 3's device index + cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick.value) + cv_usejoystick3.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick3.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick3.value = atoi(cv_usejoystick2.string); + else if (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 (JoyInfo4.dev) // update joystick 4's device index + cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick.value) + cv_usejoystick4.value = atoi(cv_usejoystick4.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick4.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick4.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick4.value = atoi(cv_usejoystick3.string); + else // we tried... + cv_usejoystick4.value = 0; + } + else if (newjoy && (!JoyInfo3.dev || !SDL_JoystickGetAttached(JoyInfo3.dev)) // PLAYER 3 + && JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + { + cv_usejoystick3.value = evt.jdevice.which + 1; + + if (JoyInfo.dev) // update joystick 1's device index + 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 if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick.value = atoi(cv_usejoystick3.string); + else if (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 (JoyInfo2.dev) // update joystick 2's device index + 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 if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick2.value = atoi(cv_usejoystick3.string); + else if (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 (JoyInfo4.dev) // update joystick 4's device index + cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; + else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick4.string) != cv_usejoystick.value) + cv_usejoystick4.value = atoi(cv_usejoystick4.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick4.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick4.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick4.value = atoi(cv_usejoystick3.string); + else // we tried... + cv_usejoystick4.value = 0; + } + else if (newjoy && (!JoyInfo4.dev || !SDL_JoystickGetAttached(JoyInfo4.dev)) // PLAYER 4 + && JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy) // don't override a currently active device + { + cv_usejoystick4.value = evt.jdevice.which + 1; + + if (JoyInfo.dev) // update joystick 1's device index + 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 if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick.value = atoi(cv_usejoystick3.string); + else if (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 (JoyInfo2.dev) // update joystick 2's device index + 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 if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) + cv_usejoystick2.value = atoi(cv_usejoystick3.string); + else if (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 (JoyInfo3.dev) // update joystick 3's device index + cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; + else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick3.string) != cv_usejoystick.value) + cv_usejoystick3.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick3.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick3.value = atoi(cv_usejoystick2.string); + else if (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; + } + + // 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) + cv_usejoystick.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick3.string); + else if (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_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_usejoystick.string) != JoyInfo.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick3.string); + else if (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_usejoystick3.string) != JoyInfo.oldjoy && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy + && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick3.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy) + cv_usejoystick3.value = atoi(cv_usejoystick2.string); + else if (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_usejoystick4.string) != JoyInfo.oldjoy && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy + && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick4.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy) + cv_usejoystick4.value = atoi(cv_usejoystick3.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(); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index afd88cbaf..674096e56 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 @@ -83,6 +86,10 @@ 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); + +void I_GetConsoleEvents(void); void SDLforceUngrabMouse(void);