improved support for game controllers and joysticks
authorHolger Schemel <info@artsoft.org>
Fri, 30 Jun 2017 18:25:05 +0000 (20:25 +0200)
committerHolger Schemel <info@artsoft.org>
Fri, 30 Jun 2017 18:25:05 +0000 (20:25 +0200)
src/events.c
src/game.c
src/libgame/joystick.c
src/libgame/joystick.h
src/libgame/sdl.c
src/libgame/sdl.h
src/libgame/system.c
src/libgame/system.h
src/screens.c

index 6dbb1e7154fd6823a9e5d7ebcfaebbfb9c0830d4..fc34d8981bc8dbc41583dd751573be706c60a330 100644 (file)
@@ -247,6 +247,11 @@ void HandleOtherEvents(Event *event)
       break;
 
 #if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+    case SDL_CONTROLLERAXISMOTION:
+    case SDL_CONTROLLERBUTTONDOWN:
+    case SDL_CONTROLLERBUTTONUP:
+#endif
     case SDL_JOYAXISMOTION:
     case SDL_JOYBUTTONDOWN:
     case SDL_JOYBUTTONUP:
@@ -1930,23 +1935,30 @@ static int HandleJoystickForAllPlayers()
 {
   int i;
   int result = 0;
+  boolean no_joysticks_configured = TRUE;
+  boolean use_as_joystick_nr = (game_status != GAME_MODE_PLAYING);
+  static byte joy_action_last[MAX_PLAYERS];
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (setup.input[i].use_joystick)
+      no_joysticks_configured = FALSE;
+
+  /* if no joysticks configured, map connected joysticks to players */
+  if (no_joysticks_configured)
+    use_as_joystick_nr = TRUE;
 
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     byte joy_action = 0;
 
-    /*
-    if (!setup.input[i].use_joystick)
-      continue;
-      */
-
-    joy_action = Joystick(i);
+    joy_action = JoystickExt(i, use_as_joystick_nr);
     result |= joy_action;
 
-    if (!setup.input[i].use_joystick)
-      continue;
+    if ((setup.input[i].use_joystick || no_joysticks_configured) &&
+       joy_action != joy_action_last[i])
+      stored_player[i].action = joy_action;
 
-    stored_player[i].action = joy_action;
+    joy_action_last[i] = joy_action;
   }
 
   return result;
index 8d2ed466dc3be327c5fc1a22de7dfcbff5b8bc59..89e0c110a1e0255bbd22f5d55040666ff66ea1ff 100644 (file)
@@ -1619,7 +1619,6 @@ void GetPlayerConfig()
   setup.sound = (setup.sound_simple || setup.sound_loops || setup.sound_music);
 
   SetAudioMode(setup.sound);
-  InitJoysticks();
 }
 
 int GetElementFromGroupElement(int element)
index 92eec0e352e9f13e84115756556f818d1b0fe2eb..a6a065cddc318a4322279fb8dd20b85d3328b973 100644 (file)
@@ -159,7 +159,7 @@ void CheckJoystickData()
   }
 }
 
-int Joystick(int player_nr)
+int JoystickExt(int player_nr, boolean use_as_joystick_nr)
 {
   int joystick_fd = joystick.fd[player_nr];
   int js_x, js_y;
@@ -167,10 +167,13 @@ int Joystick(int player_nr)
   int left, right, up, down;
   int result = JOY_NO_ACTION;
 
+  if (use_as_joystick_nr)
+    joystick_fd = player_nr;
+
   if (joystick.status != JOYSTICK_ACTIVATED)
     return JOY_NO_ACTION;
 
-  if (joystick_fd < 0 || !setup.input[player_nr].use_joystick)
+  if (joystick_fd < 0)
     return JOY_NO_ACTION;
 
   if (!ReadJoystick(joystick_fd, &js_x, &js_y, &js_b1, &js_b2))
@@ -208,10 +211,15 @@ int Joystick(int player_nr)
   return result;
 }
 
-int JoystickButton(int player_nr)
+int Joystick(int player_nr)
+{
+  return JoystickExt(player_nr, FALSE);
+}
+
+int JoystickButtonExt(int player_nr, boolean use_as_joystick_nr)
 {
   static int last_joy_button[MAX_PLAYERS] = { 0, 0, 0, 0 };
-  int joy_button = (Joystick(player_nr) & JOY_BUTTON);
+  int joy_button = (JoystickExt(player_nr, use_as_joystick_nr) & JOY_BUTTON);
   int result;
 
   if (joy_button)
@@ -233,13 +241,18 @@ int JoystickButton(int player_nr)
   return result;
 }
 
+int JoystickButton(int player_nr)
+{
+  return JoystickButtonExt(player_nr, FALSE);
+}
+
 int AnyJoystick()
 {
   int i;
   int result = 0;
 
   for (i = 0; i < MAX_PLAYERS; i++)
-    result |= Joystick(i);
+    result |= JoystickExt(i, TRUE);
 
   return result;
 }
@@ -251,7 +264,7 @@ int AnyJoystickButton()
 
   for (i = 0; i < MAX_PLAYERS; i++)
   {
-    result = JoystickButton(i);
+    result = JoystickButtonExt(i, TRUE);
     if (result != JOY_BUTTON_NOT_PRESSED)
       break;
   }
index c7f65febe498c88f1c052b11abb82c5861a195f7..f3be29545672d5e2b636ba5b2ec17ab4d3f1c7db 100644 (file)
 /* get these values from the program 'js' from the joystick package, */
 /* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */
 
-#if defined(TARGET_SDL)
-#define JOYSTICK_XLEFT         -32767
+#define JOYSTICK_MAX_AXIS_POS  32767
+
+#define JOYSTICK_XLEFT         -JOYSTICK_MAX_AXIS_POS
 #define JOYSTICK_XMIDDLE       0
-#define JOYSTICK_XRIGHT                32767
-#define JOYSTICK_YUPPER                -32767
+#define JOYSTICK_XRIGHT                +JOYSTICK_MAX_AXIS_POS
+#define JOYSTICK_YUPPER                -JOYSTICK_MAX_AXIS_POS
 #define JOYSTICK_YMIDDLE       0
-#define JOYSTICK_YLOWER                32767
-#else
-#define JOYSTICK_XLEFT         1
-#define JOYSTICK_XMIDDLE       128
-#define JOYSTICK_XRIGHT                255
-#define JOYSTICK_YUPPER                1
-#define JOYSTICK_YMIDDLE       128
-#define JOYSTICK_YLOWER                255
-#endif
+#define JOYSTICK_YLOWER                +JOYSTICK_MAX_AXIS_POS
 
 #define JOYSTICK_PERCENT       25
 
@@ -77,6 +70,7 @@ char *getDeviceNameFromJoystickNr(int);
 
 void CheckJoystickData(void);
 int Joystick(int);
+int JoystickExt(int, boolean);
 int JoystickButton(int);
 int AnyJoystick(void);
 int AnyJoystickButton(void);
index e275149fea202b723e4348394568394fc294f0d7..5586628b40dabf1385a5ae09472828f079e5501b 100644 (file)
@@ -2591,16 +2591,42 @@ void SDLHandleWindowManagerEvent(Event *event)
 /* joystick functions                                                        */
 /* ========================================================================= */
 
-static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
-static int sdl_js_axis[MAX_PLAYERS][2]   = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
-static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+#if defined(TARGET_SDL2)
+static void *sdl_joystick[MAX_PLAYERS];                // game controller or joystick
+#else
+static SDL_Joystick *sdl_joystick[MAX_PLAYERS];        // only joysticks supported
+#endif
+static int sdl_js_axis_raw[MAX_PLAYERS][2];
+static int sdl_js_axis[MAX_PLAYERS][2];
+static int sdl_js_button[MAX_PLAYERS][2];
+static boolean sdl_is_controller[MAX_PLAYERS];
 
 static boolean SDLOpenJoystick(int nr)
 {
   if (nr < 0 || nr > MAX_PLAYERS)
     return FALSE;
 
-  return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
+#if defined(TARGET_SDL2)
+  sdl_is_controller[nr] = SDL_IsGameController(nr);
+#else
+  sdl_is_controller[nr] = FALSE;
+#endif
+
+#if 1
+  Error(ERR_DEBUG, "opening joystick %d (%s)",
+       nr, (sdl_is_controller[nr] ? "game controller" : "joystick"));
+#endif
+
+#if defined(TARGET_SDL2)
+  if (sdl_is_controller[nr])
+    sdl_joystick[nr] = SDL_GameControllerOpen(nr);
+  else
+    sdl_joystick[nr] = SDL_JoystickOpen(nr);
+#else
+  sdl_joystick[nr] = SDL_JoystickOpen(nr);
+#endif
+
+  return (sdl_joystick[nr] != NULL);
 }
 
 static void SDLCloseJoystick(int nr)
@@ -2608,12 +2634,30 @@ static void SDLCloseJoystick(int nr)
   if (nr < 0 || nr > MAX_PLAYERS)
     return;
 
+#if 1
+  Error(ERR_DEBUG, "closing joystick %d", nr);
+#endif
+
+#if defined(TARGET_SDL2)
+  if (sdl_is_controller[nr])
+    SDL_GameControllerClose(sdl_joystick[nr]);
+  else
+    SDL_JoystickClose(sdl_joystick[nr]);
+#else
   SDL_JoystickClose(sdl_joystick[nr]);
+#endif
 
   sdl_joystick[nr] = NULL;
+
+  sdl_js_axis_raw[nr][0] = -1;
+  sdl_js_axis_raw[nr][1] = -1;
+  sdl_js_axis[nr][0] = 0;
+  sdl_js_axis[nr][1] = 0;
+  sdl_js_button[nr][0] = 0;
+  sdl_js_button[nr][1] = 0;
 }
 
-static boolean SDLCheckJoystickOpened(int nr)
+boolean SDLCheckJoystickOpened(int nr)
 {
   if (nr < 0 || nr > MAX_PLAYERS)
     return FALSE;
@@ -2625,23 +2669,142 @@ static boolean SDLCheckJoystickOpened(int nr)
 #endif
 }
 
+static void setJoystickAxis(int nr, int axis_id_raw, int axis_value)
+{
+#if defined(TARGET_SDL2)
+  int axis_id = (axis_id_raw == SDL_CONTROLLER_AXIS_LEFTX ||
+                axis_id_raw == SDL_CONTROLLER_AXIS_RIGHTX ? 0 :
+                axis_id_raw == SDL_CONTROLLER_AXIS_LEFTY ||
+                axis_id_raw == SDL_CONTROLLER_AXIS_RIGHTY ? 1 : -1);
+#else
+  int axis_id = axis_id_raw % 2;
+#endif
+
+  if (axis_id == -1)
+    return;
+
+  // prevent (slightly jittering, but centered) axis A from resetting axis B
+  if (ABS(axis_value) < JOYSTICK_PERCENT * JOYSTICK_MAX_AXIS_POS / 100 &&
+      axis_id_raw != sdl_js_axis_raw[nr][axis_id])
+    return;
+
+  sdl_js_axis[nr][axis_id] = axis_value;
+  sdl_js_axis_raw[nr][axis_id] = axis_id_raw;
+}
+
+static void setJoystickButton(int nr, int button_id_raw, int button_state)
+{
+#if defined(TARGET_SDL2)
+  int button_id = (button_id_raw == SDL_CONTROLLER_BUTTON_A ||
+                  button_id_raw == SDL_CONTROLLER_BUTTON_X ||
+                  button_id_raw == SDL_CONTROLLER_BUTTON_LEFTSHOULDER ||
+                  button_id_raw == SDL_CONTROLLER_BUTTON_LEFTSTICK ||
+                  button_id_raw == SDL_CONTROLLER_BUTTON_RIGHTSTICK ? 0 :
+                  button_id_raw == SDL_CONTROLLER_BUTTON_B ||
+                  button_id_raw == SDL_CONTROLLER_BUTTON_Y ||
+                  button_id_raw == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ? 1 :
+                  -1);
+
+  if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
+    sdl_js_axis[nr][0] = button_state * JOYSTICK_XLEFT;
+  else if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
+    sdl_js_axis[nr][0] = button_state * JOYSTICK_XRIGHT;
+  else if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_UP)
+    sdl_js_axis[nr][1] = button_state * JOYSTICK_YUPPER;
+  else if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
+    sdl_js_axis[nr][1] = button_state * JOYSTICK_YLOWER;
+
+  if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_LEFT ||
+      button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_RIGHT ||
+      button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_UP ||
+      button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
+    sdl_js_axis_raw[nr][0] = sdl_js_axis_raw[nr][1] = -1;
+#else
+  int button_id = button_id_raw % 2;
+#endif
+
+  if (button_id == -1)
+    return;
+
+  sdl_js_button[nr][button_id] = button_state;
+}
+
 void HandleJoystickEvent(Event *event)
 {
   switch(event->type)
   {
+#if defined(TARGET_SDL2)
+    case SDL_CONTROLLERAXISMOTION:
+#if 1
+      Error(ERR_DEBUG, "SDL_CONTROLLERAXISMOTION: device %d, axis %d: %d",
+           event->caxis.which, event->caxis.axis, event->caxis.value);
+#endif
+      setJoystickAxis(event->caxis.which,
+                     event->caxis.axis,
+                     event->caxis.value);
+      break;
+
+    case SDL_CONTROLLERBUTTONDOWN:
+#if 1
+      Error(ERR_DEBUG, "SDL_CONTROLLERBUTTONDOWN: device %d, button %d",
+           event->cbutton.which, event->cbutton.button);
+#endif
+      setJoystickButton(event->cbutton.which,
+                       event->cbutton.button,
+                       TRUE);
+      break;
+
+    case SDL_CONTROLLERBUTTONUP:
+#if 1
+      Error(ERR_DEBUG, "SDL_CONTROLLERBUTTONUP: device %d, button %d",
+           event->cbutton.which, event->cbutton.button);
+#endif
+      setJoystickButton(event->cbutton.which,
+                       event->cbutton.button,
+                       FALSE);
+      break;
+#endif
+
     case SDL_JOYAXISMOTION:
-      if (event->jaxis.axis < 2)
-       sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
+      if (sdl_is_controller[event->jaxis.which])
+       break;
+
+#if 1
+      Error(ERR_DEBUG, "SDL_JOYAXISMOTION: device %d, axis %d: %d",
+           event->jaxis.which, event->jaxis.axis, event->jaxis.value);
+#endif
+      if (event->jaxis.axis < 4)
+       setJoystickAxis(event->jaxis.which,
+                       event->jaxis.axis,
+                       event->jaxis.value);
       break;
 
     case SDL_JOYBUTTONDOWN:
-      if (event->jbutton.button < 2)
-       sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
+      if (sdl_is_controller[event->jaxis.which])
+       break;
+
+#if 1
+      Error(ERR_DEBUG, "SDL_JOYBUTTONDOWN: device %d, button %d",
+           event->jbutton.which, event->jbutton.button);
+#endif
+      if (event->jbutton.button < 4)
+       setJoystickButton(event->jbutton.which,
+                         event->jbutton.button,
+                         TRUE);
       break;
 
     case SDL_JOYBUTTONUP:
-      if (event->jbutton.button < 2)
-       sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
+      if (sdl_is_controller[event->jaxis.which])
+       break;
+
+#if 1
+      Error(ERR_DEBUG, "SDL_JOYBUTTONUP: device %d, button %d",
+           event->jbutton.which, event->jbutton.button);
+#endif
+      if (event->jbutton.button < 4)
+       setJoystickButton(event->jbutton.which,
+                         event->jbutton.button,
+                         FALSE);
       break;
 
     default:
@@ -2653,19 +2816,60 @@ void SDLInitJoysticks()
 {
   static boolean sdl_joystick_subsystem_initialized = FALSE;
   boolean print_warning = !sdl_joystick_subsystem_initialized;
+#if defined(TARGET_SDL2)
+  char *mappings_file = "gamecontrollerdb.txt";
+  int num_mappings;
+#endif
   int i;
 
   if (!sdl_joystick_subsystem_initialized)
   {
     sdl_joystick_subsystem_initialized = TRUE;
 
+#if defined(TARGET_SDL2)
+    SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
+
+    if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0)
+#else
     if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
+#endif
     {
       Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
       return;
     }
+
+#if defined(TARGET_SDL2)
+    num_mappings = SDL_GameControllerAddMappingsFromFile(mappings_file);
+
+    if (num_mappings != -1)
+      Error(ERR_INFO, "%d game controller mapping(s) added", num_mappings);
+    else
+      Error(ERR_WARN, "no game controller mappings found");
+
+    Error(ERR_INFO, "%d joystick(s) found:", SDL_NumJoysticks());
+
+    for (i = 0; i < SDL_NumJoysticks(); i++)
+    {
+      const char *name, *type;
+
+      if (SDL_IsGameController(i))
+      {
+       name = SDL_GameControllerNameForIndex(i);
+       type = "game controller";
+      }
+      else
+      {
+       name = SDL_JoystickNameForIndex(i);
+       type = "joystick";
+      }
+
+      Error(ERR_INFO, "- joystick %d (%s): '%s'",
+           i, type, (name ? name : "(Unknown)"));
+    }
+#endif
   }
 
+  /* assign joysticks from configured to connected joystick for all players */
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     /* get configured joystick for this player */
@@ -2682,26 +2886,19 @@ void SDLInitJoysticks()
 
     /* misuse joystick file descriptor variable to store joystick number */
     joystick.fd[i] = joystick_nr;
+  }
 
-    if (joystick_nr == -1)
-      continue;
-
+  /* now open all connected joysticks (regardless if configured or not) */
+  for (i = 0; i < SDL_NumJoysticks(); i++)
+  {
     /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
-    if (SDLCheckJoystickOpened(joystick_nr))
-      SDLCloseJoystick(joystick_nr);
-
-    if (!setup.input[i].use_joystick)
-      continue;
-
-    if (!SDLOpenJoystick(joystick_nr))
-    {
-      if (print_warning)
-       Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
-
-      continue;
-    }
+    if (SDLCheckJoystickOpened(i))
+      SDLCloseJoystick(i);
 
-    joystick.status = JOYSTICK_ACTIVATED;
+    if (SDLOpenJoystick(i))
+      joystick.status = JOYSTICK_ACTIVATED;
+    else if (print_warning)
+      Error(ERR_WARN, "cannot open joystick %d", i);
   }
 }
 
index c88b6a82818191f7348d792a094e10c97c4de7fd..f9fc1a87b2d6132d4e6b5bfb92ffc2d900c9c681 100644 (file)
@@ -484,6 +484,7 @@ void SDLHandleWindowManagerEvent(Event *);
 void HandleJoystickEvent(Event *);
 void SDLInitJoysticks(void);
 boolean SDLReadJoystick(int, int *, int *, boolean *, boolean *);
+boolean SDLCheckJoystickOpened(int);
 
 void PrepareFadeBitmap(int);
 
index b5de8c9e6959ee11848072c3ec9599f0e52a9850..de59d77a6ce4bf501d8d278fa43f12c29216c617 100644 (file)
@@ -1629,3 +1629,8 @@ boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
 {
   return SDLReadJoystick(nr, x, y, b1, b2);
 }
+
+boolean CheckJoystickOpened(int nr)
+{
+  return SDLCheckJoystickOpened(nr);
+}
index be19fccd8a3fbb201d06623900e4f08d118bc9e0..3fc4eb6cd0eb43cbf1b92f6a94713ab2d53bdb4a 100644 (file)
@@ -1544,5 +1544,6 @@ boolean CheckCloseWindowEvent(ClientMessageEvent *);
 
 void InitJoysticks();
 boolean ReadJoystick(int, int *, int *, boolean *, boolean *);
+boolean CheckJoystickOpened(int);
 
 #endif /* SYSTEM_H */
index dbbd50758440729770eec943d72452c5529157d4..c241ab3e663486490d0278c5e32dc203971fb945 100644 (file)
@@ -1413,7 +1413,6 @@ void DrawMainMenu()
   ExpireSoundLoops(FALSE);
 
   KeyboardAutoRepeatOn();
-  ActivateJoystick();
 
   audio.sound_deactivated = FALSE;
 
@@ -4190,7 +4189,6 @@ void DrawHallOfFame(int highlight_position)
 
   /* (this is needed when called from GameEnd() after winning a game) */
   KeyboardAutoRepeatOn();
-  ActivateJoystick();
 
   /* (this is needed when called from GameEnd() after winning a game) */
   SetDrawDeactivationMask(REDRAW_NONE);
@@ -5239,14 +5237,12 @@ static void execSetupChooseMusic()
   DrawSetupScreen();
 }
 
-#if !defined(PLATFORM_ANDROID)
 static void execSetupInput()
 {
   setup_mode = SETUP_MODE_INPUT;
 
   DrawSetupScreen();
 }
-#endif
 
 static void execSetupShortcuts()
 {
@@ -5310,12 +5306,8 @@ static struct TokenInfo setup_info_main[] =
   { TYPE_ENTER_MENU,   execSetupGraphics,      "Graphics"              },
   { TYPE_ENTER_MENU,   execSetupSound,         "Sound & Music"         },
   { TYPE_ENTER_MENU,   execSetupArtwork,       "Custom Artwork"        },
-#if !defined(PLATFORM_ANDROID)
   { TYPE_ENTER_MENU,   execSetupInput,         "Input Devices"         },
   { TYPE_ENTER_MENU,   execSetupTouch,         "Touch Controls"        },
-#else
-  { TYPE_ENTER_MENU,   execSetupTouch,         "Touch Controls"        },
-#endif
   { TYPE_ENTER_MENU,   execSetupShortcuts,     "Key Shortcuts"         },
   { TYPE_EMPTY,                NULL,                   ""                      },
   { TYPE_LEAVE_MENU,   execExitSetup,          "Exit"                  },
@@ -5956,9 +5948,6 @@ void DrawSetupScreen_Input()
 
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Setup Input");
 
-  DrawTextSCentered(SYSIZE - 20, FONT_TITLE_2,
-                   "Joysticks deactivated on this screen");
-
   for (i = 0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
   {
     if (setup_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
@@ -6030,8 +6019,6 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
   };
   int text_font_nr = (active ? FONT_MENU_1_ACTIVE : FONT_MENU_1);
 
-  InitJoysticks();
-
   custom_key = setup.input[player_nr].key;
 
   DrawText(mSX + 11 * 32, mSY + 2 * 32, int2str(player_nr + 1, 1),
@@ -6045,8 +6032,10 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
   if (setup.input[player_nr].use_joystick)
   {
     char *device_name = setup.input[player_nr].joy.device_name;
-    char *text = joystick_name[getJoystickNrFromDeviceName(device_name)];
-    int font_nr = (joystick.fd[player_nr] < 0 ? FONT_VALUE_OLD : FONT_VALUE_1);
+    int joystick_nr = getJoystickNrFromDeviceName(device_name);
+    boolean joystick_active = CheckJoystickOpened(joystick_nr);
+    char *text = joystick_name[joystick_nr];
+    int font_nr = (joystick_active ? FONT_VALUE_1 : FONT_VALUE_OLD);
 
     DrawText(mSX + 8 * 32, mSY + 3 * 32, text, font_nr);
     DrawText(mSX + 32, mSY + 4 * 32, "Calibrate", text_font_nr);
@@ -6201,10 +6190,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
       else if (y == 2)
       {
        if (setup.input[input_player_nr].use_joystick)
-       {
-         InitJoysticks();
          CalibrateJoystick(input_player_nr);
-       }
        else
          CustomizeKeyboard(input_player_nr);
       }
@@ -6544,8 +6530,6 @@ void CalibrateJoystick(int player_nr)
 
 void DrawSetupScreen()
 {
-  DeactivateJoystick();
-
   if (setup_mode == SETUP_MODE_INPUT)
     DrawSetupScreen_Input();
   else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED)