sdl2-compat: Fix Joystick virtual

From 29bf28e06316eb140325d4e019e0dc4e00bcbffb Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Fri, 3 Feb 2023 20:35:51 +0100
Subject: [PATCH] Fix Joystick virtual

---
 src/sdl2_compat.c | 38 +++++++++++++++++++++++++++++++++++++-
 src/sdl3_syms.h   |  7 +++----
 2 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index 5ef7c67..0f76316 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -4068,7 +4068,6 @@ GetJoystickInstanceFromIndex(int idx)
 
 /* !!! FIXME: when we override SDL_Quit(), we need to free/reset joystick_list and friends*/
 /* !!! FIXME: put a mutex on the joystick and sensor lists. Strictly speaking, this will break if you multithread it, but it doesn't have to crash. */
-/* !!! FIXME: we need to override the virtual joystick stuff, since it returns a device index */
 
 DECLSPEC int SDLCALL
 SDL_NumJoysticks(void)
@@ -4082,6 +4081,22 @@ SDL_NumJoysticks(void)
     return num_joysticks;
 }
 
+static int
+GetIndexFromJoystickInstance(SDL_JoystickID jid) {
+    int i;
+
+    /* Refresh */
+    SDL_NumJoysticks();
+
+    for (i = 0; i < num_joysticks; i++) {
+        if (joystick_list[i] == jid) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+
 DECLSPEC SDL_JoystickGUID SDLCALL
 SDL_JoystickGetDeviceGUID(int idx)
 {
@@ -4221,6 +4236,27 @@ SDL_GameControllerPathForIndex(int idx)
     return jid ? SDL3_GetGamepadInstancePath(jid) : NULL;
 }
 
+DECLSPEC int SDLCALL
+SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nbuttons, int nhats)
+{
+    SDL_JoystickID jid = SDL3_AttachVirtualJoystick(type, naxes, nbuttons, nhats);
+    return GetIndexFromJoystickInstance(jid);
+}
+
+DECLSPEC int SDLCALL
+SDL_JoystickAttachVirtualEx(const SDL_VirtualJoystickDesc *desc)
+{
+    SDL_JoystickID jid = SDL3_AttachVirtualJoystickEx(desc);
+    return GetIndexFromJoystickInstance(jid);
+}
+
+DECLSPEC int SDLCALL
+SDL_JoystickDetachVirtual(SDL_JoystickID instance_id)
+{
+    const SDL_JoystickID jid = GetJoystickInstanceFromIndex(instance_id);
+    return jid ? SDL3_DetachVirtualJoystick(jid) : SDL_FALSE;
+}
+
 
 /* !!! FIXME: when we override SDL_Quit(), we need to free/reset sensor_list */
 
diff --git a/src/sdl3_syms.h b/src/sdl3_syms.h
index e7a8cbd..e4c32a2 100644
--- a/src/sdl3_syms.h
+++ b/src/sdl3_syms.h
@@ -723,10 +723,9 @@ SDL3_SYM_PASSTHROUGH(int,GetAndroidSDKVersion,(void),(),return)
 SDL3_SYM_PASSTHROUGH(int,isupper,(int a),(a),return)
 SDL3_SYM_PASSTHROUGH(int,islower,(int a),(a),return)
 
-/* FIXME: the following three are wrong and can't be passthrough. */
-SDL3_SYM_RENAMED(int,JoystickAttachVirtual,AttachVirtualJoystick,(SDL_JoystickType a, int b, int c, int d),(a,b,c,d),return)
-SDL3_SYM_RENAMED(int,JoystickDetachVirtual,DetachVirtualJoystick,(int a),(a),return)
-SDL3_SYM_RENAMED(int,JoystickAttachVirtualEx,AttachVirtualJoystickEx,(const SDL_VirtualJoystickDesc *a),(a),return)
+SDL3_SYM(SDL_JoystickID,AttachVirtualJoystick,(SDL_JoystickType a, int b, int c, int d),(a,b,c,d),return)
+SDL3_SYM(int,DetachVirtualJoystick,(SDL_JoystickID a),(a),return)
+SDL3_SYM(SDL_JoystickID,AttachVirtualJoystickEx,(const SDL_VirtualJoystickDesc *a),(a),return)
 
 SDL3_SYM_RENAMED(int,JoystickSetVirtualAxis,SetJoystickVirtualAxis,(SDL_Joystick *a, int b, Sint16 c),(a,b,c),return)
 SDL3_SYM_RENAMED(int,JoystickSetVirtualButton,SetJoystickVirtualButton,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return)