test/controllermap.c
changeset 10724 5ea5f198879f
parent 10706 71ce5d7d2610
child 10726 893faaa67394
     1.1 --- a/test/controllermap.c	Mon Dec 26 23:02:14 2016 -0500
     1.2 +++ b/test/controllermap.c	Tue Dec 27 01:39:07 2016 -0800
     1.3 @@ -32,7 +32,22 @@
     1.4  #define MARKER_BUTTON 1
     1.5  #define MARKER_AXIS 2
     1.6  
     1.7 -#define BINDING_COUNT (SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_MAX)
     1.8 +enum
     1.9 +{
    1.10 +    SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE,
    1.11 +    SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE,
    1.12 +    SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE,
    1.13 +    SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE,
    1.14 +    SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE,
    1.15 +    SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE,
    1.16 +    SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE,
    1.17 +    SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE,
    1.18 +    SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT,
    1.19 +    SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT,
    1.20 +    SDL_CONTROLLER_BINDING_AXIS_MAX,
    1.21 +};
    1.22 +
    1.23 +#define BINDING_COUNT (SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_MAX)
    1.24  
    1.25  static struct 
    1.26  {
    1.27 @@ -56,12 +71,16 @@
    1.28      { 154, 249, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_DOWN */
    1.29      { 116, 217, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_LEFT */
    1.30      { 186, 217, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_RIGHT */
    1.31 -    {  75, 154, 0.0,   MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_LEFTX */
    1.32 -    {  75, 154, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_LEFTY */
    1.33 -    { 305, 230, 0.0,   MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_RIGHTX */
    1.34 -    { 305, 230, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_RIGHTY */
    1.35 -    {  91,   0, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_TRIGGERLEFT */
    1.36 -    { 375,   0, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_TRIGGERRIGHT */
    1.37 +    {  74, 153, 270.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE */
    1.38 +    {  74, 153, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE */
    1.39 +    {  74, 153, 0.0,   MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE */
    1.40 +    {  74, 153, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE */
    1.41 +    { 306, 231, 270.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE */
    1.42 +    { 306, 231, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE */
    1.43 +    { 306, 231, 0.0,   MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE */
    1.44 +    { 306, 231, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE */
    1.45 +    {  91, -20, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT */
    1.46 +    { 375, -20, 180.0, MARKER_AXIS }, /* SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT */
    1.47  };
    1.48  
    1.49  static int s_arrBindingOrder[BINDING_COUNT] = {
    1.50 @@ -69,16 +88,20 @@
    1.51      SDL_CONTROLLER_BUTTON_B,
    1.52      SDL_CONTROLLER_BUTTON_Y,
    1.53      SDL_CONTROLLER_BUTTON_X,
    1.54 -    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_LEFTX,
    1.55 -    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_LEFTY,
    1.56 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE,
    1.57 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE,
    1.58 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE,
    1.59 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE,
    1.60      SDL_CONTROLLER_BUTTON_LEFTSTICK,
    1.61 -    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_RIGHTX,
    1.62 -    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_RIGHTY,
    1.63 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE,
    1.64 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE,
    1.65 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE,
    1.66 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE,
    1.67      SDL_CONTROLLER_BUTTON_RIGHTSTICK,
    1.68      SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
    1.69 -    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_TRIGGERLEFT,
    1.70 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT,
    1.71      SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
    1.72 -    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
    1.73 +    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT,
    1.74      SDL_CONTROLLER_BUTTON_DPAD_UP,
    1.75      SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
    1.76      SDL_CONTROLLER_BUTTON_DPAD_DOWN,
    1.77 @@ -88,7 +111,40 @@
    1.78      SDL_CONTROLLER_BUTTON_START,
    1.79  };
    1.80  
    1.81 -static SDL_GameControllerButtonBind s_arrBindings[BINDING_COUNT];
    1.82 +typedef struct
    1.83 +{
    1.84 +    SDL_GameControllerBindType bindType;
    1.85 +    union
    1.86 +    {
    1.87 +        int button;
    1.88 +
    1.89 +        struct {
    1.90 +            int axis;
    1.91 +            int axis_min;
    1.92 +            int axis_max;
    1.93 +        } axis;
    1.94 +
    1.95 +        struct {
    1.96 +            int hat;
    1.97 +            int hat_mask;
    1.98 +        } hat;
    1.99 +
   1.100 +    } value;
   1.101 +
   1.102 +} SDL_GameControllerExtendedBind;
   1.103 +
   1.104 +static SDL_GameControllerExtendedBind s_arrBindings[BINDING_COUNT];
   1.105 +
   1.106 +typedef struct
   1.107 +{
   1.108 +    SDL_bool m_bMoving;
   1.109 +    int m_nStartingValue;
   1.110 +    int m_nFarthestValue;
   1.111 +} AxisState;
   1.112 +
   1.113 +static int s_nNumAxes;
   1.114 +static AxisState *s_arrAxisState;
   1.115 +    
   1.116  static int s_iCurrentBinding;
   1.117  static Uint32 s_unPendingAdvanceTime;
   1.118  static SDL_bool s_bBindingComplete;
   1.119 @@ -110,23 +166,6 @@
   1.120      if (transparent) {
   1.121          if (temp->format->palette) {
   1.122              SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
   1.123 -        } else {
   1.124 -            switch (temp->format->BitsPerPixel) {
   1.125 -            case 15:
   1.126 -                SDL_SetColorKey(temp, SDL_TRUE,
   1.127 -                                (*(Uint16 *) temp->pixels) & 0x00007FFF);
   1.128 -                break;
   1.129 -            case 16:
   1.130 -                SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
   1.131 -                break;
   1.132 -            case 24:
   1.133 -                SDL_SetColorKey(temp, SDL_TRUE,
   1.134 -                                (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
   1.135 -                break;
   1.136 -            case 32:
   1.137 -                SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
   1.138 -                break;
   1.139 -            }
   1.140          }
   1.141      }
   1.142  
   1.143 @@ -143,9 +182,22 @@
   1.144      return texture;
   1.145  }
   1.146  
   1.147 -void SetCurrentBinding(int iBinding)
   1.148 +static int
   1.149 +StandardizeAxisValue(int nValue)
   1.150  {
   1.151 -    SDL_GameControllerButtonBind *pBinding;
   1.152 +    if (nValue > SDL_JOYSTICK_AXIS_MAX/2) {
   1.153 +        return SDL_JOYSTICK_AXIS_MAX;
   1.154 +    } else if (nValue < SDL_JOYSTICK_AXIS_MIN/2) {
   1.155 +        return SDL_JOYSTICK_AXIS_MIN;
   1.156 +    } else {
   1.157 +        return 0;
   1.158 +    }
   1.159 +}
   1.160 +
   1.161 +static void
   1.162 +SetCurrentBinding(int iBinding)
   1.163 +{
   1.164 +    SDL_GameControllerExtendedBind *pBinding;
   1.165  
   1.166      if (iBinding < 0) {
   1.167          return;
   1.168 @@ -161,14 +213,15 @@
   1.169      pBinding = &s_arrBindings[s_arrBindingOrder[s_iCurrentBinding]];
   1.170      SDL_zerop(pBinding);
   1.171  
   1.172 +    SDL_memset(s_arrAxisState, 0, s_nNumAxes*sizeof(*s_arrAxisState));
   1.173 +
   1.174      s_unPendingAdvanceTime = 0;
   1.175  }
   1.176  
   1.177 -
   1.178  static void
   1.179 -ConfigureBinding(const SDL_GameControllerButtonBind *pBinding)
   1.180 +ConfigureBinding(const SDL_GameControllerExtendedBind *pBinding)
   1.181  {
   1.182 -    SDL_GameControllerButtonBind *pCurrent;
   1.183 +    SDL_GameControllerExtendedBind *pCurrent;
   1.184      int iIndex;
   1.185      int iCurrentElement = s_arrBindingOrder[s_iCurrentBinding];
   1.186  
   1.187 @@ -221,6 +274,24 @@
   1.188      s_unPendingAdvanceTime = SDL_GetTicks();
   1.189  }
   1.190  
   1.191 +static SDL_bool
   1.192 +BMergeAxisBindings(int iIndex)
   1.193 +{
   1.194 +    SDL_GameControllerExtendedBind *pBindingA = &s_arrBindings[iIndex];
   1.195 +    SDL_GameControllerExtendedBind *pBindingB = &s_arrBindings[iIndex+1];
   1.196 +    if (pBindingA->bindType == SDL_CONTROLLER_BINDTYPE_AXIS &&
   1.197 +        pBindingB->bindType == SDL_CONTROLLER_BINDTYPE_AXIS &&
   1.198 +        pBindingA->value.axis.axis == pBindingB->value.axis.axis) {
   1.199 +        if (pBindingA->value.axis.axis_min == pBindingB->value.axis.axis_min) {
   1.200 +            pBindingA->value.axis.axis_min = pBindingA->value.axis.axis_max;
   1.201 +            pBindingA->value.axis.axis_max = pBindingB->value.axis.axis_max;
   1.202 +            pBindingB->bindType = SDL_CONTROLLER_BINDTYPE_NONE;
   1.203 +            return SDL_TRUE;
   1.204 +        }
   1.205 +    }
   1.206 +    return SDL_FALSE;
   1.207 +}
   1.208 +
   1.209  static void
   1.210  WatchJoystick(SDL_Joystick * joystick)
   1.211  {
   1.212 @@ -279,6 +350,9 @@
   1.213  
   1.214      nJoystickID = SDL_JoystickInstanceID(joystick);
   1.215  
   1.216 +    s_nNumAxes = SDL_JoystickNumAxes(joystick);
   1.217 +    s_arrAxisState = SDL_calloc(s_nNumAxes, sizeof(*s_arrAxisState));
   1.218 +
   1.219      /* Loop, getting joystick events! */
   1.220      while (!done && !s_bBindingComplete) {
   1.221          int iElement = s_arrBindingOrder[s_iCurrentBinding];
   1.222 @@ -326,26 +400,35 @@
   1.223                  break;
   1.224              case SDL_JOYAXISMOTION:
   1.225                  if (event.jaxis.which == nJoystickID) {
   1.226 -                    uint32_t unAxisMask = (1 << event.jaxis.axis);
   1.227 -                    SDL_bool bDeflected = (event.jaxis.value <= -20000 || event.jaxis.value >= 20000);
   1.228 -                    if (bDeflected && !(unDeflectedAxes & unAxisMask)) {
   1.229 -                        SDL_GameControllerButtonBind binding;
   1.230 +                    AxisState *pAxisState = &s_arrAxisState[event.jaxis.axis];
   1.231 +                    int nValue = event.jaxis.value;
   1.232 +                    int nCurrentDistance, nFarthestDistance;
   1.233 +                    if (!pAxisState->m_bMoving) {
   1.234 +                        pAxisState->m_bMoving = SDL_TRUE;
   1.235 +                        pAxisState->m_nStartingValue = nValue;
   1.236 +                        pAxisState->m_nFarthestValue = nValue;
   1.237 +                    }
   1.238 +                    nCurrentDistance = SDL_abs(nValue - pAxisState->m_nStartingValue);
   1.239 +                    nFarthestDistance = SDL_abs(pAxisState->m_nFarthestValue - pAxisState->m_nStartingValue);
   1.240 +                    if (nCurrentDistance > nFarthestDistance) {
   1.241 +                        pAxisState->m_nFarthestValue = nValue;
   1.242 +                    }
   1.243 +                    if (nCurrentDistance < 10000 && nFarthestDistance > 20000) {
   1.244 +                        /* We've gone out and back, let's bind this axis */
   1.245 +                        SDL_GameControllerExtendedBind binding;
   1.246                          SDL_zero(binding);
   1.247                          binding.bindType = SDL_CONTROLLER_BINDTYPE_AXIS;
   1.248 -                        binding.value.axis = event.jaxis.axis;
   1.249 +                        binding.value.axis.axis = event.jaxis.axis;
   1.250 +                        binding.value.axis.axis_min = StandardizeAxisValue(pAxisState->m_nStartingValue);
   1.251 +                        binding.value.axis.axis_max = StandardizeAxisValue(pAxisState->m_nFarthestValue);
   1.252                          ConfigureBinding(&binding);
   1.253                      }
   1.254 -                    if (bDeflected) {
   1.255 -                        unDeflectedAxes |= unAxisMask;
   1.256 -                    } else {
   1.257 -                        unDeflectedAxes &= ~unAxisMask;
   1.258 -                    }
   1.259                  }
   1.260                  break;
   1.261              case SDL_JOYHATMOTION:
   1.262                  if (event.jhat.which == nJoystickID) {
   1.263                      if (event.jhat.value != SDL_HAT_CENTERED) {
   1.264 -                        SDL_GameControllerButtonBind binding;
   1.265 +                        SDL_GameControllerExtendedBind binding;
   1.266                          SDL_zero(binding);
   1.267                          binding.bindType = SDL_CONTROLLER_BINDTYPE_HAT;
   1.268                          binding.value.hat.hat = event.jhat.hat;
   1.269 @@ -358,7 +441,7 @@
   1.270                  break;
   1.271              case SDL_JOYBUTTONDOWN:
   1.272                  if (event.jbutton.which == nJoystickID) {
   1.273 -                    SDL_GameControllerButtonBind binding;
   1.274 +                    SDL_GameControllerExtendedBind binding;
   1.275                      SDL_zero(binding);
   1.276                      binding.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
   1.277                      binding.value.button = event.jbutton.button;
   1.278 @@ -430,7 +513,7 @@
   1.279          SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
   1.280  
   1.281          for (iIndex = 0; iIndex < SDL_arraysize(s_arrBindings); ++iIndex) {
   1.282 -            SDL_GameControllerButtonBind *pBinding = &s_arrBindings[iIndex];
   1.283 +            SDL_GameControllerExtendedBind *pBinding = &s_arrBindings[iIndex];
   1.284              if (pBinding->bindType == SDL_CONTROLLER_BINDTYPE_NONE) {
   1.285                  continue;
   1.286              }
   1.287 @@ -439,8 +522,56 @@
   1.288                  SDL_GameControllerButton eButton = (SDL_GameControllerButton)iIndex;
   1.289                  SDL_strlcat(mapping, SDL_GameControllerGetStringForButton(eButton), SDL_arraysize(mapping));
   1.290              } else {
   1.291 -                SDL_GameControllerAxis eAxis = (SDL_GameControllerAxis)(iIndex - SDL_CONTROLLER_BUTTON_MAX);
   1.292 -                SDL_strlcat(mapping, SDL_GameControllerGetStringForAxis(eAxis), SDL_arraysize(mapping));
   1.293 +                const char *pszAxisName;
   1.294 +                switch (iIndex - SDL_CONTROLLER_BUTTON_MAX) {
   1.295 +                case SDL_CONTROLLER_BINDING_AXIS_LEFTX_NEGATIVE:
   1.296 +                    if (!BMergeAxisBindings(iIndex)) {
   1.297 +                        SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
   1.298 +                    }
   1.299 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTX);
   1.300 +                    break;
   1.301 +                case SDL_CONTROLLER_BINDING_AXIS_LEFTX_POSITIVE:
   1.302 +                    SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
   1.303 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTX);
   1.304 +                    break;
   1.305 +                case SDL_CONTROLLER_BINDING_AXIS_LEFTY_NEGATIVE:
   1.306 +                    if (!BMergeAxisBindings(iIndex)) {
   1.307 +                        SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
   1.308 +                    }
   1.309 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTY);
   1.310 +                    break;
   1.311 +                case SDL_CONTROLLER_BINDING_AXIS_LEFTY_POSITIVE:
   1.312 +                    SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
   1.313 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_LEFTY);
   1.314 +                    break;
   1.315 +                case SDL_CONTROLLER_BINDING_AXIS_RIGHTX_NEGATIVE:
   1.316 +                    if (!BMergeAxisBindings(iIndex)) {
   1.317 +                        SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
   1.318 +                    }
   1.319 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTX);
   1.320 +                    break;
   1.321 +                case SDL_CONTROLLER_BINDING_AXIS_RIGHTX_POSITIVE:
   1.322 +                    SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
   1.323 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTX);
   1.324 +                    break;
   1.325 +                case SDL_CONTROLLER_BINDING_AXIS_RIGHTY_NEGATIVE:
   1.326 +                    if (!BMergeAxisBindings(iIndex)) {
   1.327 +                        SDL_strlcat(mapping, "-", SDL_arraysize(mapping));
   1.328 +                    }
   1.329 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTY);
   1.330 +                    break;
   1.331 +                case SDL_CONTROLLER_BINDING_AXIS_RIGHTY_POSITIVE:
   1.332 +                    SDL_strlcat(mapping, "+", SDL_arraysize(mapping));
   1.333 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_RIGHTY);
   1.334 +                    break;
   1.335 +                case SDL_CONTROLLER_BINDING_AXIS_TRIGGERLEFT:
   1.336 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_TRIGGERLEFT);
   1.337 +                    break;
   1.338 +                case SDL_CONTROLLER_BINDING_AXIS_TRIGGERRIGHT:
   1.339 +                    pszAxisName = SDL_GameControllerGetStringForAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
   1.340 +                    break;
   1.341 +                }
   1.342 +                SDL_strlcat(mapping, pszAxisName, SDL_arraysize(mapping));
   1.343              }
   1.344              SDL_strlcat(mapping, ":", SDL_arraysize(mapping));
   1.345  
   1.346 @@ -450,7 +581,19 @@
   1.347                  SDL_snprintf(pszElement, sizeof(pszElement), "b%d", pBinding->value.button);
   1.348                  break;
   1.349              case SDL_CONTROLLER_BINDTYPE_AXIS:
   1.350 -                SDL_snprintf(pszElement, sizeof(pszElement), "a%d", pBinding->value.axis);
   1.351 +                if (pBinding->value.axis.axis_min == 0 && pBinding->value.axis.axis_max == SDL_JOYSTICK_AXIS_MIN) {
   1.352 +                    /* The negative half axis */
   1.353 +                    SDL_snprintf(pszElement, sizeof(pszElement), "-a%d", pBinding->value.axis.axis);
   1.354 +                } else if (pBinding->value.axis.axis_min == 0 && pBinding->value.axis.axis_max == SDL_JOYSTICK_AXIS_MAX) {
   1.355 +                    /* The positive half axis */
   1.356 +                    SDL_snprintf(pszElement, sizeof(pszElement), "+a%d", pBinding->value.axis.axis);
   1.357 +                } else {
   1.358 +                    SDL_snprintf(pszElement, sizeof(pszElement), "a%d", pBinding->value.axis.axis);
   1.359 +                    if (pBinding->value.axis.axis_min > pBinding->value.axis.axis_max) {
   1.360 +                        /* Invert the axis */
   1.361 +                        SDL_strlcat(pszElement, "~", SDL_arraysize(pszElement));
   1.362 +                    }
   1.363 +                }
   1.364                  break;
   1.365              case SDL_CONTROLLER_BINDTYPE_HAT:
   1.366                  SDL_snprintf(pszElement, sizeof(pszElement), "h%d.%d", pBinding->value.hat.hat, pBinding->value.hat.hat_mask);
   1.367 @@ -467,6 +610,9 @@
   1.368          /* Print to stdout as well so the user can cat the output somewhere */
   1.369          printf("%s\n", mapping);
   1.370      }
   1.371 +
   1.372 +    SDL_free(s_arrAxisState);
   1.373 +    s_arrAxisState = NULL;
   1.374      
   1.375      SDL_DestroyRenderer(screen);
   1.376      SDL_DestroyWindow(window);