Mac and Linux SDL2 binary snapshots
Edward Rudd
2020-05-02 03f8528315fa46c95991a34f3325d7b33ae5538c
source/src/joystick/SDL_gamecontroller.c
@@ -1,6 +1,6 @@
/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
@@ -42,7 +42,9 @@
/* Many controllers turn the center button into an instantaneous button press */
#define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS   250
#define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
#define SDL_CONTROLLER_PLATFORM_FIELD   "platform:"
#define SDL_CONTROLLER_SDKGE_FIELD      "sdk>=:"
#define SDL_CONTROLLER_SDKLE_FIELD      "sdk<=:"
/* a list of currently opened game controllers */
static SDL_GameController *SDL_gamecontrollers = NULL;
@@ -202,13 +204,14 @@
{
    int i, num_events;
    SDL_Event *events;
    SDL_bool isstack;
    num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
    if (num_events <= 0) {
        return;
    }
    events = SDL_stack_alloc(SDL_Event, num_events);
    events = SDL_small_alloc(SDL_Event, num_events, &isstack);
    if (!events) {
        return;
    }
@@ -219,7 +222,7 @@
    }
    SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
    SDL_stack_free(events);
    SDL_small_free(events, isstack);
}
static SDL_bool HasSameOutput(SDL_ExtendedGameControllerBind *a, SDL_ExtendedGameControllerBind *b)
@@ -641,8 +644,8 @@
    int i = 0;
    const char *pchPos = pchString;
    SDL_zero(szGameButton);
    SDL_zero(szJoystickButton);
    SDL_zeroa(szGameButton);
    SDL_zeroa(szJoystickButton);
    while (pchPos && *pchPos) {
        if (*pchPos == ':') {
@@ -654,8 +657,8 @@
            i = 0;
            bGameButton = SDL_TRUE;
            SDL_PrivateGameControllerParseElement(gamecontroller, szGameButton, szJoystickButton);
            SDL_zero(szGameButton);
            SDL_zero(szJoystickButton);
            SDL_zeroa(szGameButton);
            SDL_zeroa(szJoystickButton);
        } else if (bGameButton) {
            if (i >= sizeof(szGameButton)) {
@@ -675,8 +678,10 @@
        pchPos++;
    }
    SDL_PrivateGameControllerParseElement(gamecontroller, szGameButton, szJoystickButton);
    /* No more values if the string was terminated by a comma. Don't report an error. */
    if (szGameButton[0] != '\0' || szJoystickButton[0] != '\0') {
        SDL_PrivateGameControllerParseElement(gamecontroller, szGameButton, szJoystickButton);
    }
}
/*
@@ -688,7 +693,9 @@
    gamecontroller->name = pchName;
    gamecontroller->num_bindings = 0;
    SDL_memset(gamecontroller->last_match_axis, 0, gamecontroller->joystick->naxes * sizeof(*gamecontroller->last_match_axis));
    if (gamecontroller->joystick->naxes) {
        SDL_memset(gamecontroller->last_match_axis, 0, gamecontroller->joystick->naxes * sizeof(*gamecontroller->last_match_axis));
    }
    SDL_PrivateGameControllerParseControllerConfigString(gamecontroller, pchMapping);
@@ -876,7 +883,7 @@
            for ( pPrevMapping = s_pSupportedControllers, pCurrMapping = pPrevMapping->next;
                  pCurrMapping; 
                  pPrevMapping = pCurrMapping, pCurrMapping = pCurrMapping->next ) {
                continue;
                /* continue; */
            }
            pPrevMapping->next = pControllerMapping;
        } else {
@@ -994,6 +1001,17 @@
    if (axis_mask & (1 << SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) {
        SDL_strlcat(mapping_string, "righttrigger:a5,", sizeof(mapping_string));
    }
    /* Remove trailing comma */
    {
        int pos = (int)SDL_strlen(mapping_string) - 1;
        if (pos >= 0) {
            if (mapping_string[pos] == ',') {
                mapping_string[pos] = '\0';
            }
        }
    }
    return SDL_PrivateAddMappingForGUID(guid, mapping_string,
                      &existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT);
}
@@ -1014,7 +1032,7 @@
            /* The Linux driver xpad.c maps the wireless dpad to buttons */
            SDL_bool existing;
            mapping = SDL_PrivateAddMappingForGUID(guid,
"none,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"none,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3",
                          &existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT);
        }
    }
@@ -1120,7 +1138,7 @@
                }
            }
        }
        line = line_end + 1;
    }
@@ -1145,6 +1163,27 @@
    if (!mappingString) {
        return SDL_InvalidParamError("mappingString");
    }
#ifdef ANDROID
    { /* Extract and verify the SDK version */
        const char *tmp;
        tmp = SDL_strstr(mappingString, SDL_CONTROLLER_SDKGE_FIELD);
        if (tmp != NULL) {
            tmp += SDL_strlen(SDL_CONTROLLER_SDKGE_FIELD);
            if (!(SDL_GetAndroidSDKVersion() >= SDL_atoi(tmp))) {
                return SDL_SetError("SDK version %d < minimum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp));
            }
        }
        tmp = SDL_strstr(mappingString, SDL_CONTROLLER_SDKLE_FIELD);
        if (tmp != NULL) {
            tmp += SDL_strlen(SDL_CONTROLLER_SDKLE_FIELD);
            if (!(SDL_GetAndroidSDKVersion() <= SDL_atoi(tmp))) {
                return SDL_SetError("SDK version %d > maximum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp));
            }
        }
    }
#endif
    pchGUID = SDL_PrivateGetControllerGUIDFromMappingString(mappingString);
    if (!pchGUID) {
@@ -1307,15 +1346,17 @@
/*
 * Fill the given buffer with the expected controller mapping filepath. 
 * Usually this will just be CONTROLLER_MAPPING_FILE, but for Android,
 * we want to get the internal storage path.
 * Usually this will just be SDL_HINT_GAMECONTROLLERCONFIG_FILE, but for
 * Android, we want to get the internal storage path.
 */
static SDL_bool SDL_GetControllerMappingFilePath(char *path, size_t size)
{
#ifdef CONTROLLER_MAPPING_FILE
#define STRING(X) SDL_STRINGIFY_ARG(X)
    return SDL_strlcpy(path, STRING(CONTROLLER_MAPPING_FILE), size) < size;
#elif defined(__ANDROID__)
    const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERCONFIG_FILE);
    if (hint && *hint) {
        return SDL_strlcpy(path, hint, size) < size;
    }
#if defined(__ANDROID__)
    return SDL_snprintf(path, size, "%s/controller_map.txt", SDL_AndroidGetInternalStoragePath()) < size;
#else
    return SDL_FALSE;
@@ -1395,6 +1436,16 @@
/**
 *  Get the type of a game controller.
 */
SDL_GameControllerType
SDL_GameControllerTypeForIndex(int joystick_index)
{
    return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetDeviceGUID(joystick_index), SDL_JoystickNameForIndex(joystick_index));
}
/**
 *  Get the mapping of a game controller.
 *  This can be called before any controllers are opened.
 *  If no mapping can be found, this function returns NULL.
@@ -1464,6 +1515,13 @@
    Uint16 product;
    Uint16 version;
    Uint32 vidpid;
#if defined(__LINUX__)
    if (name && SDL_strstr(name, "Controller Motion Sensors")) {
        /* Don't treat the PS3 and PS4 motion controls as a separate game controller */
        return SDL_TRUE;
    }
#endif
    if (SDL_allowed_controllers.num_entries == 0 &&
        SDL_ignored_controllers.num_entries == 0) {
@@ -1635,6 +1693,8 @@
                        float normalized_value = (float)(value - binding->input.axis.axis_min) / (binding->input.axis.axis_max - binding->input.axis.axis_min);
                        value = binding->output.axis.axis_min + (int)(normalized_value * (binding->output.axis.axis_max - binding->output.axis.axis_min));
                    }
                } else {
                    value = 0;
                }
            } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) {
                value = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button);
@@ -1716,10 +1776,25 @@
    }
}
SDL_GameControllerType
SDL_GameControllerGetType(SDL_GameController *gamecontroller)
{
    return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(SDL_GameControllerGetJoystick(gamecontroller)), SDL_JoystickName(SDL_GameControllerGetJoystick(gamecontroller)));
}
int
SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller)
{
    return SDL_JoystickGetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller));
}
/**
 *  Set the player index of an opened game controller
 */
void
SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index)
{
    SDL_JoystickSetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller), player_index);
}
Uint16
@@ -1766,7 +1841,7 @@
/*
 * Find the SDL_GameController that owns this instance id
 * Return the SDL_GameController associated with an instance id.
 */
SDL_GameController *
SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
@@ -1787,6 +1862,19 @@
}
/**
 * Return the SDL_GameController associated with a player index.
 */
SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index)
{
    SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index);
    if (joystick) {
        return SDL_GameControllerFromInstanceID(joystick->instance_id);
    }
    return NULL;
}
/*
 * Get the SDL joystick layer binding for this controller axis mapping
 */