Fixed bug 4921 - Do not swap B/X buttons on GameCube controller unless it's requested
authorSam Lantinga <slouken@libsdl.org>
Tue, 10 Mar 2020 16:41:42 -0700
changeset 13602e6a2558ec791
parent 13601 3d3649fe086e
child 13603 78d0bb6f3b8f
Fixed bug 4921 - Do not swap B/X buttons on GameCube controller unless it's requested

Ethan Lee

Basically replicating the solution of the Switch Controller's button label issue. Physical layout should take priority unless it's explicitly requested by the user or application!
src/joystick/hidapi/SDL_hidapi_gamecube.c
     1.1 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c	Tue Mar 10 16:29:28 2020 -0700
     1.2 +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c	Tue Mar 10 16:41:42 2020 -0700
     1.3 @@ -29,6 +29,7 @@
     1.4  #include "SDL_haptic.h"
     1.5  #include "SDL_joystick.h"
     1.6  #include "SDL_gamecontroller.h"
     1.7 +#include "../../SDL_hints_c.h"
     1.8  #include "../SDL_sysjoystick.h"
     1.9  #include "SDL_hidapijoystick_c.h"
    1.10  #include "SDL_hidapi_rumble.h"
    1.11 @@ -47,6 +48,7 @@
    1.12      Uint8 rumble[1+MAX_CONTROLLERS];
    1.13      /* Without this variable, hid_write starts to lag a TON */
    1.14      SDL_bool rumbleUpdate;
    1.15 +    SDL_bool m_bUseButtonLabels;
    1.16  } SDL_DriverGameCube_Context;
    1.17  
    1.18  static SDL_bool
    1.19 @@ -95,6 +97,27 @@
    1.20      return C + (D - C) * (val - A) / (B - A);
    1.21  }
    1.22  
    1.23 +static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
    1.24 +{
    1.25 +    SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
    1.26 +    ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
    1.27 +}
    1.28 +
    1.29 +static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button)
    1.30 +{
    1.31 +    if (ctx->m_bUseButtonLabels) {
    1.32 +        switch (button) {
    1.33 +        case SDL_CONTROLLER_BUTTON_B:
    1.34 +            return SDL_CONTROLLER_BUTTON_X;
    1.35 +        case SDL_CONTROLLER_BUTTON_X:
    1.36 +            return SDL_CONTROLLER_BUTTON_B;
    1.37 +        default:
    1.38 +            break;
    1.39 +        }
    1.40 +    }
    1.41 +    return button;
    1.42 +}
    1.43 +
    1.44  static SDL_bool
    1.45  HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
    1.46  {
    1.47 @@ -164,6 +187,9 @@
    1.48          }
    1.49      }
    1.50  
    1.51 +    SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
    1.52 +                        SDL_GameControllerButtonReportingHintChanged, ctx);
    1.53 +
    1.54      return SDL_TRUE;
    1.55  
    1.56  error:
    1.57 @@ -244,12 +270,12 @@
    1.58              #define READ_BUTTON(off, flag, button) \
    1.59                  SDL_PrivateJoystickButton( \
    1.60                      joystick, \
    1.61 -                    button, \
    1.62 +                    RemapButton(ctx, button), \
    1.63                      (curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED \
    1.64                  );
    1.65              READ_BUTTON(1, 0x01, 0) /* A */
    1.66 -            READ_BUTTON(1, 0x04, 1) /* B */
    1.67 -            READ_BUTTON(1, 0x02, 2) /* X */
    1.68 +            READ_BUTTON(1, 0x02, 1) /* B */
    1.69 +            READ_BUTTON(1, 0x04, 2) /* X */
    1.70              READ_BUTTON(1, 0x08, 3) /* Y */
    1.71              READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */
    1.72              READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */
    1.73 @@ -352,9 +378,14 @@
    1.74  static void
    1.75  HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
    1.76  {
    1.77 +    SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
    1.78 +
    1.79      hid_close(device->dev);
    1.80      device->dev = NULL;
    1.81  
    1.82 +    SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
    1.83 +                        SDL_GameControllerButtonReportingHintChanged, ctx);
    1.84 +
    1.85      SDL_free(device->context);
    1.86      device->context = NULL;
    1.87  }