From dec7875a6e23212021e4d9080330a42832dfe02a Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Tue, 15 Jun 2021 01:40:19 +0000
Subject: [PATCH] update SDL soruce to 2.0.14

---
 source/test/testgamecontroller.c |  573 +++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 376 insertions(+), 197 deletions(-)

diff --git a/source/test/testgamecontroller.c b/source/test/testgamecontroller.c
index 6ed3105..6522885 100644
--- a/source/test/testgamecontroller.c
+++ b/source/test/testgamecontroller.c
@@ -24,47 +24,187 @@
 
 #ifndef SDL_JOYSTICK_DISABLED
 
-#ifdef __IPHONEOS__
-#define SCREEN_WIDTH    480
-#define SCREEN_HEIGHT    320
-#else
 #define SCREEN_WIDTH    512
 #define SCREEN_HEIGHT   320
-#endif
 
 /* This is indexed by SDL_GameControllerButton. */
 static const struct { int x; int y; } button_positions[] = {
-    {387, 167},  /* A */
-    {431, 132},  /* B */
-    {342, 132},  /* X */
-    {389, 101},  /* Y */
-    {174, 132},  /* BACK */
-    {233, 132},  /* GUIDE */
-    {289, 132},  /* START */
-    {75,  154},  /* LEFTSTICK */
-    {305, 230},  /* RIGHTSTICK */
-    {77,  40},   /* LEFTSHOULDER */
-    {396, 36},   /* RIGHTSHOULDER */
-    {154, 188},  /* DPAD_UP */
-    {154, 249},  /* DPAD_DOWN */
-    {116, 217},  /* DPAD_LEFT */
-    {186, 217},  /* DPAD_RIGHT */
+    {387, 167},  /* SDL_CONTROLLER_BUTTON_A */
+    {431, 132},  /* SDL_CONTROLLER_BUTTON_B */
+    {342, 132},  /* SDL_CONTROLLER_BUTTON_X */
+    {389, 101},  /* SDL_CONTROLLER_BUTTON_Y */
+    {174, 132},  /* SDL_CONTROLLER_BUTTON_BACK */
+    {232, 128},  /* SDL_CONTROLLER_BUTTON_GUIDE */
+    {289, 132},  /* SDL_CONTROLLER_BUTTON_START */
+    {75,  154},  /* SDL_CONTROLLER_BUTTON_LEFTSTICK */
+    {305, 230},  /* SDL_CONTROLLER_BUTTON_RIGHTSTICK */
+    {77,  40},   /* SDL_CONTROLLER_BUTTON_LEFTSHOULDER */
+    {396, 36},   /* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER */
+    {154, 188},  /* SDL_CONTROLLER_BUTTON_DPAD_UP */
+    {154, 249},  /* SDL_CONTROLLER_BUTTON_DPAD_DOWN */
+    {116, 217},  /* SDL_CONTROLLER_BUTTON_DPAD_LEFT */
+    {186, 217},  /* SDL_CONTROLLER_BUTTON_DPAD_RIGHT */
+    {232, 174},  /* SDL_CONTROLLER_BUTTON_MISC1 */
+    {132, 135},  /* SDL_CONTROLLER_BUTTON_PADDLE1 */
+    {330, 135},  /* SDL_CONTROLLER_BUTTON_PADDLE2 */
+    {132, 175},  /* SDL_CONTROLLER_BUTTON_PADDLE3 */
+    {330, 175},  /* SDL_CONTROLLER_BUTTON_PADDLE4 */
 };
 
 /* This is indexed by SDL_GameControllerAxis. */
 static const struct { int x; int y; double angle; } axis_positions[] = {
     {74,  153, 270.0},  /* LEFTX */
-    {74,  153, 0.0},  /* LEFTY */
+    {74,  153,   0.0},  /* LEFTY */
     {306, 231, 270.0},  /* RIGHTX */
-    {306, 231, 0.0},  /* RIGHTY */
-    {91, -20, 0.0},     /* TRIGGERLEFT */
-    {375, -20, 0.0},    /* TRIGGERRIGHT */
+    {306, 231,   0.0},  /* RIGHTY */
+    {91,  -20,   0.0},  /* TRIGGERLEFT */
+    {375, -20,   0.0},  /* TRIGGERRIGHT */
 };
 
+SDL_Window *window = NULL;
 SDL_Renderer *screen = NULL;
 SDL_bool retval = SDL_FALSE;
 SDL_bool done = SDL_FALSE;
-SDL_Texture *background, *button, *axis;
+SDL_bool set_LED = SDL_FALSE;
+SDL_Texture *background_front, *background_back, *button, *axis;
+SDL_GameController *gamecontroller;
+SDL_GameController **gamecontrollers;
+int num_controllers = 0;
+
+static void UpdateWindowTitle()
+{
+    if (!window) {
+        return;
+    }
+
+    if (gamecontroller) {
+        const char *name = SDL_GameControllerName(gamecontroller);
+        const char *serial = SDL_GameControllerGetSerial(gamecontroller);
+        const char *basetitle = "Game Controller Test: ";
+        const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + (serial ? 3 + SDL_strlen(serial) : 0) + 1;
+        char *title = (char *)SDL_malloc(titlelen);
+
+        retval = SDL_FALSE;
+        done = SDL_FALSE;
+
+        if (title) {
+            SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
+            if (serial) {
+                SDL_strlcat(title, " (", titlelen);
+                SDL_strlcat(title, serial, titlelen);
+                SDL_strlcat(title, ")", titlelen);
+            }
+            SDL_SetWindowTitle(window, title);
+            SDL_free(title);
+        }
+    } else {
+        SDL_SetWindowTitle(window, "Waiting for controller...");
+    }
+}
+
+static int FindController(SDL_JoystickID controller_id)
+{
+    int i;
+
+    for (i = 0; i < num_controllers; ++i) {
+        if (controller_id == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontrollers[i]))) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+static void AddController(int device_index, SDL_bool verbose)
+{
+    SDL_JoystickID controller_id = SDL_JoystickGetDeviceInstanceID(device_index);
+    SDL_GameController *controller;
+    SDL_GameController **controllers;
+
+    controller_id = SDL_JoystickGetDeviceInstanceID(device_index);
+    if (controller_id < 0) {
+        SDL_Log("Couldn't get controller ID: %s\n", SDL_GetError());
+        return;
+    }
+
+    if (FindController(controller_id) >= 0) {
+        /* We already have this controller */
+        return;
+    }
+
+    controller = SDL_GameControllerOpen(device_index);
+    if (!controller) {
+        SDL_Log("Couldn't open controller: %s\n", SDL_GetError());
+        return;
+    }
+
+    controllers = (SDL_GameController **)SDL_realloc(gamecontrollers, (num_controllers + 1) * sizeof(*controllers));
+    if (!controllers) {
+        SDL_GameControllerClose(controller);
+        return;
+    }
+
+    controllers[num_controllers++] = controller;
+    gamecontrollers = controllers;
+    gamecontroller = controller;
+
+    if (verbose) {
+        const char *name = SDL_GameControllerName(gamecontroller);
+        SDL_Log("Opened game controller %s\n", name);
+    }
+
+    if (SDL_GameControllerHasSensor(gamecontroller, SDL_SENSOR_ACCEL)) {
+        if (verbose) {
+            SDL_Log("Enabling accelerometer\n");
+        }
+        SDL_GameControllerSetSensorEnabled(gamecontroller, SDL_SENSOR_ACCEL, SDL_TRUE);
+    }
+
+    if (SDL_GameControllerHasSensor(gamecontroller, SDL_SENSOR_GYRO)) {
+        if (verbose) {
+            SDL_Log("Enabling gyro\n");
+        }
+        SDL_GameControllerSetSensorEnabled(gamecontroller, SDL_SENSOR_GYRO, SDL_TRUE);
+    }
+
+    UpdateWindowTitle();
+}
+
+static void SetController(SDL_JoystickID controller)
+{
+    int i = FindController(controller);
+
+    if (i < 0) {
+        return;
+    }
+
+    if (gamecontroller != gamecontrollers[i]) {
+        gamecontroller = gamecontrollers[i];
+        UpdateWindowTitle();
+    }
+}
+
+static void DelController(SDL_JoystickID controller)
+{
+    int i = FindController(controller);
+
+    if (i < 0) {
+        return;
+    }
+
+    SDL_GameControllerClose(gamecontrollers[i]);
+
+    --num_controllers;
+    if (i < num_controllers) {
+        SDL_memcpy(&gamecontrollers[i], &gamecontrollers[i+1], (num_controllers - i) * sizeof(*gamecontrollers));
+    }
+
+    if (num_controllers > 0) {
+        gamecontroller = gamecontrollers[0];
+    } else {
+        gamecontroller = NULL;
+    }
+    UpdateWindowTitle();
+}
 
 static SDL_Texture *
 LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
@@ -94,27 +234,74 @@
     return texture;
 }
 
+static Uint16 ConvertAxisToRumble(Sint16 axis)
+{
+    /* Only start rumbling if the axis is past the halfway point */
+    const Sint16 half_axis = (Sint16)SDL_ceil(SDL_JOYSTICK_AXIS_MAX / 2.0f);
+    if (axis > half_axis) {
+        return (Uint16)(axis - half_axis) * 4;
+    } else {
+        return 0;
+    }
+}
+
 void
 loop(void *arg)
 {
     SDL_Event event;
     int i;
-    SDL_GameController *gamecontroller = (SDL_GameController *)arg;
-
-    /* blank screen, set up for drawing this frame. */
-    SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
-    SDL_RenderClear(screen);
-    SDL_RenderCopy(screen, background, NULL, NULL);
+    SDL_bool showing_front = SDL_TRUE;
 
     while (SDL_PollEvent(&event)) {
         switch (event.type) {
+        case SDL_CONTROLLERDEVICEADDED:
+            SDL_Log("Game controller device %d added.\n", (int) SDL_JoystickGetDeviceInstanceID(event.cdevice.which));
+            AddController(event.cdevice.which, SDL_TRUE);
+            break;
+
+        case SDL_CONTROLLERDEVICEREMOVED:
+            SDL_Log("Game controller device %d removed.\n", (int) event.cdevice.which);
+            DelController(event.cdevice.which);
+            break;
+
+        case SDL_CONTROLLERTOUCHPADDOWN:
+        case SDL_CONTROLLERTOUCHPADMOTION:
+        case SDL_CONTROLLERTOUCHPADUP:
+            SDL_Log("Controller touchpad %d finger %d %s %.2f, %.2f, %.2f\n",
+                event.ctouchpad.touchpad,
+                event.ctouchpad.finger,
+                (event.type == SDL_CONTROLLERTOUCHPADDOWN ? "pressed at" :
+                (event.type == SDL_CONTROLLERTOUCHPADUP ? "released at" :
+                "moved to")),
+                event.ctouchpad.x,
+                event.ctouchpad.y,
+                event.ctouchpad.pressure);
+            break;
+
+        case SDL_CONTROLLERSENSORUPDATE:
+            SDL_Log("Controller sensor %s: %.2f, %.2f, %.2f\n",
+                event.csensor.sensor == SDL_SENSOR_ACCEL ? "accelerometer" :
+                event.csensor.sensor == SDL_SENSOR_GYRO ? "gyro" : "unknown",
+                event.csensor.data[0],
+                event.csensor.data[1],
+                event.csensor.data[2]);
+            break;
+
         case SDL_CONTROLLERAXISMOTION:
+            if (event.caxis.value <= (-SDL_JOYSTICK_AXIS_MAX / 2) || event.caxis.value >= (SDL_JOYSTICK_AXIS_MAX / 2)) {
+                SetController(event.caxis.which);
+            }
             SDL_Log("Controller axis %s changed to %d\n", SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)event.caxis.axis), event.caxis.value);
             break;
+
         case SDL_CONTROLLERBUTTONDOWN:
         case SDL_CONTROLLERBUTTONUP:
+            if (event.type == SDL_CONTROLLERBUTTONDOWN) {
+                SetController(event.cbutton.which);
+            }
             SDL_Log("Controller button %s %s\n", SDL_GameControllerGetStringForButton((SDL_GameControllerButton)event.cbutton.button), event.cbutton.state ? "pressed" : "released");
             break;
+
         case SDL_KEYDOWN:
             if (event.key.keysym.sym != SDLK_ESCAPE) {
                 break;
@@ -128,41 +315,98 @@
         }
     }
 
-    /* Update visual controller state */
-    for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
-        if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
-            const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
-            SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, SDL_FLIP_NONE);
+    if (gamecontroller) {
+        /* Show the back of the controller if the paddles are being held */
+        for (i = SDL_CONTROLLER_BUTTON_PADDLE1; i <= SDL_CONTROLLER_BUTTON_PADDLE4; ++i) {
+            if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
+                showing_front = SDL_FALSE;
+                break;
+            }
         }
     }
 
-    for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
-        const Sint16 deadzone = 8000;  /* !!! FIXME: real deadzone */
-        const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
-        if (value < -deadzone) {
-            const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
-            const double angle = axis_positions[i].angle;
-            SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
-        } else if (value > deadzone) {
-            const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
-            const double angle = axis_positions[i].angle + 180.0;
-            SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
-        }
-    }
+    /* blank screen, set up for drawing this frame. */
+    SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
+    SDL_RenderClear(screen);
+    SDL_RenderCopy(screen, showing_front ? background_front : background_back, NULL, NULL);
 
-    /* Update rumble based on trigger state */
-    {
-        Uint16 low_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) * 2;
-        Uint16 high_frequency_rumble = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) * 2;
-        SDL_GameControllerRumble(gamecontroller, low_frequency_rumble, high_frequency_rumble, 250);
+    if (gamecontroller) {
+        /* Update visual controller state */
+        for (i = 0; i < SDL_CONTROLLER_BUTTON_TOUCHPAD; ++i) {
+            if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
+                SDL_bool on_front = (i < SDL_CONTROLLER_BUTTON_PADDLE1 || i > SDL_CONTROLLER_BUTTON_PADDLE4);
+                if (on_front == showing_front) {
+                    const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
+                    SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, SDL_FLIP_NONE);
+                }
+            }
+        }
+
+        if (showing_front) {
+            for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
+                const Sint16 deadzone = 8000;  /* !!! FIXME: real deadzone */
+                const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
+                if (value < -deadzone) {
+                    const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
+                    const double angle = axis_positions[i].angle;
+                    SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
+                } else if (value > deadzone) {
+                    const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
+                    const double angle = axis_positions[i].angle + 180.0;
+                    SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
+                }
+            }
+        }
+
+        /* Update LED based on left thumbstick position */
+        {
+            Sint16 x = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_LEFTX);
+            Sint16 y = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_LEFTY);
+
+            if (!set_LED) {
+                set_LED = (x < -8000 || x > 8000 || y > 8000);
+            }
+            if (set_LED) {
+                Uint8 r, g, b;
+
+                if (x < 0) {
+                    r = (Uint8)(((int)(~x) * 255) / 32767);
+                    b = 0;
+                } else {
+                    r = 0;
+                    b = (Uint8)(((int)(x) * 255) / 32767);
+                }
+                if (y > 0) {
+                    g = (Uint8)(((int)(y) * 255) / 32767);
+                } else {
+                    g = 0;
+                }
+
+                SDL_GameControllerSetLED(gamecontroller, r, g, b);
+            }
+        }
+
+        /* Update rumble based on trigger state */
+        {
+            Sint16 left = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
+            Sint16 right = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
+            Uint16 low_frequency_rumble = ConvertAxisToRumble(left);
+            Uint16 high_frequency_rumble = ConvertAxisToRumble(right);
+            SDL_GameControllerRumble(gamecontroller, low_frequency_rumble, high_frequency_rumble, 250);
+        }
+
+        /* Update trigger rumble based on thumbstick state */
+        {
+            Sint16 left = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_LEFTY);
+            Sint16 right = SDL_GameControllerGetAxis(gamecontroller, SDL_CONTROLLER_AXIS_RIGHTY);
+            Uint16 left_rumble = ConvertAxisToRumble(~left);
+            Uint16 right_rumble = ConvertAxisToRumble(~right);
+
+            SDL_GameControllerRumbleTriggers(gamecontroller, left_rumble, right_rumble, 250);
+        }
     }
 
     SDL_RenderPresent(screen);
-
-    if (!SDL_GameControllerGetAttached(gamecontroller)) {
-        done = SDL_TRUE;
-        retval = SDL_TRUE;  /* keep going, wait for reattach. */
-    }
 
 #ifdef __EMSCRIPTEN__
     if (done) {
@@ -171,92 +415,17 @@
 #endif
 }
 
-SDL_bool
-WatchGameController(SDL_GameController * gamecontroller)
-{
-    const char *name = SDL_GameControllerName(gamecontroller);
-    const char *basetitle = "Game Controller Test: ";
-    const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
-    char *title = (char *)SDL_malloc(titlelen);
-    SDL_Window *window = NULL;
-
-    retval = SDL_FALSE;
-    done = SDL_FALSE;
-
-    if (title) {
-        SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
-    }
-
-    /* Create a window to display controller state */
-    window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED,
-                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
-                              SCREEN_HEIGHT, 0);
-    SDL_free(title);
-    title = NULL;
-    if (window == NULL) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
-        return SDL_FALSE;
-    }
-
-    screen = SDL_CreateRenderer(window, -1, 0);
-    if (screen == NULL) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
-        SDL_DestroyWindow(window);
-        return SDL_FALSE;
-    }
-
-    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
-    SDL_RenderClear(screen);
-    SDL_RenderPresent(screen);
-    SDL_RaiseWindow(window);
-
-    /* scale for platforms that don't give you the window size you asked for. */
-    SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
-
-    background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
-    button = LoadTexture(screen, "button.bmp", SDL_TRUE);
-    axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
-
-    if (!background || !button || !axis) {
-        SDL_DestroyRenderer(screen);
-        SDL_DestroyWindow(window);
-        return SDL_FALSE;
-    }
-    SDL_SetTextureColorMod(button, 10, 255, 21);
-    SDL_SetTextureColorMod(axis, 10, 255, 21);
-
-    /* !!! FIXME: */
-    /*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/
-
-    /* Print info about the controller we are watching */
-    SDL_Log("Watching controller %s\n",  name ? name : "Unknown Controller");
-
-    /* Loop, getting controller events! */
-#ifdef __EMSCRIPTEN__
-    emscripten_set_main_loop_arg(loop, gamecontroller, 0, 1);
-#else
-    while (!done) {
-        loop(gamecontroller);
-    }
-#endif
-
-    SDL_DestroyRenderer(screen);
-    screen = NULL;
-    background = NULL;
-    button = NULL;
-    axis = NULL;
-    SDL_DestroyWindow(window);
-    return retval;
-}
-
 int
 main(int argc, char *argv[])
 {
     int i;
-    int nController = 0;
-    int retcode = 0;
+    int controller_count = 0;
+    int controller_index = 0;
     char guid[64];
-    SDL_GameController *gamecontroller;
+
+    SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
+    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
+    SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
@@ -270,7 +439,7 @@
     SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
 
     /* Print information about the mappings */
-    if (!argv[1]) {
+    if (argv[1] && SDL_strcmp(argv[1], "--mappings") == 0) {
         SDL_Log("Supported mappings:\n");
         for (i = 0; i < SDL_GameControllerNumMappings(); ++i) {
             char *mapping = SDL_GameControllerMappingForIndex(i);
@@ -290,9 +459,8 @@
         SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
                                   guid, sizeof (guid));
 
-        if ( SDL_IsGameController(i) )
-        {
-            nController++;
+        if (SDL_IsGameController(i)) {
+            controller_count++;
             name = SDL_GameControllerNameForIndex(i);
             switch (SDL_GameControllerTypeForIndex(i)) {
             case SDL_CONTROLLER_TYPE_XBOX360:
@@ -310,10 +478,14 @@
             case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
                 description = "Nintendo Switch Pro Controller";
                 break;
+            case SDL_CONTROLLER_TYPE_VIRTUAL:
+                description = "Virtual Game Controller";
+                break;
             default:
                 description = "Game Controller";
                 break;
             }
+            AddController(i, SDL_FALSE);
         } else {
             name = SDL_JoystickNameForIndex(i);
             description = "Joystick";
@@ -322,64 +494,71 @@
             description, i, name ? name : "Unknown", guid,
             SDL_JoystickGetDeviceVendor(i), SDL_JoystickGetDeviceProduct(i), SDL_JoystickGetDevicePlayerIndex(i));
     }
-    SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks());
+    SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", controller_count, SDL_NumJoysticks());
 
-    if (argv[1]) {
-        SDL_bool reportederror = SDL_FALSE;
-        SDL_bool keepGoing = SDL_TRUE;
-        SDL_Event event;
-        int device = atoi(argv[1]);
-        if (device >= SDL_NumJoysticks()) {
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%i is an invalid joystick index.\n", device);
-            retcode = 1;
-        } else {
-            SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(device),
-                                      guid, sizeof (guid));
-            SDL_Log("Attempting to open device %i, guid %s\n", device, guid);
-            gamecontroller = SDL_GameControllerOpen(device);
-
-            if (gamecontroller != NULL) {
-                SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
-            }
-
-            while (keepGoing) {
-                if (gamecontroller == NULL) {
-                    if (!reportederror) {
-                        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open gamecontroller %d: %s\n", device, SDL_GetError());
-                        retcode = 1;
-                        keepGoing = SDL_FALSE;
-                        reportederror = SDL_TRUE;
-                    }
-                } else {
-                    reportederror = SDL_FALSE;
-                    keepGoing = WatchGameController(gamecontroller);
-                    SDL_GameControllerClose(gamecontroller);
-                }
-
-                gamecontroller = NULL;
-                if (keepGoing) {
-                    SDL_Log("Waiting for attach\n");
-                }
-                while (keepGoing) {
-                    SDL_WaitEvent(&event);
-                    if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
-                        || (event.type == SDL_MOUSEBUTTONDOWN)) {
-                        keepGoing = SDL_FALSE;
-                    } else if (event.type == SDL_CONTROLLERDEVICEADDED) {
-                        gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
-                        if (gamecontroller != NULL) {
-                            SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
-                        }
-                        break;
-                    }
-                }
-            }
-        }
+    /* Create a window to display controller state */
+    window = SDL_CreateWindow("Game Controller Test", SDL_WINDOWPOS_CENTERED,
+                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
+                              SCREEN_HEIGHT, 0);
+    if (window == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
+        return 2;
     }
 
+    screen = SDL_CreateRenderer(window, -1, 0);
+    if (screen == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
+        SDL_DestroyWindow(window);
+        return 2;
+    }
+
+    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
+    SDL_RenderClear(screen);
+    SDL_RenderPresent(screen);
+
+    /* scale for platforms that don't give you the window size you asked for. */
+    SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
+
+    background_front = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
+    background_back = LoadTexture(screen, "controllermap_back.bmp", SDL_FALSE);
+    button = LoadTexture(screen, "button.bmp", SDL_TRUE);
+    axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
+
+    if (!background_front || !background_back || !button || !axis) {
+        SDL_DestroyRenderer(screen);
+        SDL_DestroyWindow(window);
+        return 2;
+    }
+    SDL_SetTextureColorMod(button, 10, 255, 21);
+    SDL_SetTextureColorMod(axis, 10, 255, 21);
+
+    /* !!! FIXME: */
+    /*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/
+
+    if (argv[1] && *argv[1] != '-') {
+        controller_index = SDL_atoi(argv[1]);
+    }
+    if (controller_index < num_controllers) {
+        gamecontroller = gamecontrollers[controller_index];
+    } else {
+        gamecontroller = NULL;
+    }
+    UpdateWindowTitle();
+
+    /* Loop, getting controller events! */
+#ifdef __EMSCRIPTEN__
+    emscripten_set_main_loop_arg(loop, NULL, 0, 1);
+#else
+    while (!done) {
+        loop(NULL);
+    }
+#endif
+
+    SDL_DestroyRenderer(screen);
+    SDL_DestroyWindow(window);
     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
 
-    return retcode;
+    return 0;
 }
 
 #else

--
Gitblit v1.9.3