Bläddra i källkod

Merge branch 'main' into 12.x

Sasha Szpakowski 2 år sedan
förälder
incheckning
da21872b01
100 ändrade filer med 2101 tillägg och 1314 borttagningar
  1. 2 2
      CMakeLists.txt
  2. 1 1
      libs/LuaJIT/.relver
  3. 1 3
      libs/LuaJIT/doc/extensions.html
  4. 4 1
      libs/LuaJIT/doc/install.html
  5. 2 1
      libs/LuaJIT/doc/running.html
  6. 4 4
      libs/LuaJIT/dynasm/dasm_arm64.lua
  7. 10 11
      libs/LuaJIT/src/host/buildvm_peobj.c
  8. 2 2
      libs/LuaJIT/src/jit/bcsave.lua
  9. 1 1
      libs/LuaJIT/src/jit/dis_arm64.lua
  10. 4 1
      libs/LuaJIT/src/lib_base.c
  11. 1 1
      libs/LuaJIT/src/lib_ffi.c
  12. 6 1
      libs/LuaJIT/src/lj_api.c
  13. 1 1
      libs/LuaJIT/src/lj_asm_arm.h
  14. 33 18
      libs/LuaJIT/src/lj_asm_arm64.h
  15. 2 1
      libs/LuaJIT/src/lj_asm_x86.h
  16. 4 0
      libs/LuaJIT/src/lj_carith.c
  17. 17 1
      libs/LuaJIT/src/lj_ccall.c
  18. 1 5
      libs/LuaJIT/src/lj_crecord.c
  19. 4 2
      libs/LuaJIT/src/lj_ctype.h
  20. 1 1
      libs/LuaJIT/src/lj_def.h
  21. 1 1
      libs/LuaJIT/src/lj_dispatch.c
  22. 31 9
      libs/LuaJIT/src/lj_emit_arm64.h
  23. 40 11
      libs/LuaJIT/src/lj_err.c
  24. 11 12
      libs/LuaJIT/src/lj_ffrecord.c
  25. 2 2
      libs/LuaJIT/src/lj_ir.h
  26. 1 1
      libs/LuaJIT/src/lj_ircall.h
  27. 6 0
      libs/LuaJIT/src/lj_iropt.h
  28. 1 1
      libs/LuaJIT/src/lj_opt_dce.c
  29. 4 4
      libs/LuaJIT/src/lj_opt_fold.c
  30. 9 5
      libs/LuaJIT/src/lj_record.c
  31. 23 4
      libs/LuaJIT/src/lj_state.c
  32. 1 0
      libs/LuaJIT/src/lj_state.h
  33. 2 0
      libs/LuaJIT/src/lj_target_arm64.h
  34. 16 10
      libs/LuaJIT/src/lj_trace.c
  35. 14 1
      libs/LuaJIT/src/msvcbuild.bat
  36. 115 92
      libs/LuaJIT/src/vm_arm64.dasc
  37. 1 0
      libs/LuaJIT/src/vm_mips64.dasc
  38. 30 12
      libs/SDL2/CMakeLists.txt
  39. 1 1
      libs/SDL2/Makefile.os2
  40. 1 1
      libs/SDL2/Makefile.w32
  41. 1 1
      libs/SDL2/SDL2.spec
  42. 1 1
      libs/SDL2/VERSION.txt
  43. 1 1
      libs/SDL2/VisualC/pkg-support/cmake/sdl2-config.cmake
  44. 7 0
      libs/SDL2/WhatsNew.txt
  45. 2 2
      libs/SDL2/Xcode/SDL/Info-Framework.plist
  46. 6 6
      libs/SDL2/Xcode/SDL/SDL.xcodeproj/project.pbxproj
  47. 1 1
      libs/SDL2/Xcode/SDL/pkg-support/SDL.info
  48. 10 10
      libs/SDL2/android-project/app/build.gradle
  49. 0 1
      libs/SDL2/android-project/app/src/main/AndroidManifest.xml
  50. 16 18
      libs/SDL2/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
  51. 1 1
      libs/SDL2/android-project/build.gradle
  52. 1 1
      libs/SDL2/android-project/gradle/wrapper/gradle-wrapper.properties
  53. 52 13
      libs/SDL2/build-scripts/config.guess
  54. 146 76
      libs/SDL2/build-scripts/config.sub
  55. 18 0
      libs/SDL2/cmake/sdlchecks.cmake
  56. 4 0
      libs/SDL2/cmake/sdlplatform.cmake
  57. 4 42
      libs/SDL2/configure
  58. 4 27
      libs/SDL2/configure.ac
  59. 7 7
      libs/SDL2/docs/README-android.md
  60. 1 1
      libs/SDL2/docs/README-cmake.md
  61. 1 1
      libs/SDL2/docs/README-emscripten.md
  62. 1 1
      libs/SDL2/docs/README-os2.md
  63. 2 0
      libs/SDL2/include/SDL_assert.h
  64. 1 1
      libs/SDL2/include/SDL_atomic.h
  65. 2 0
      libs/SDL2/include/SDL_config.h.cmake
  66. 20 0
      libs/SDL2/include/SDL_hints.h
  67. 1 1
      libs/SDL2/include/SDL_render.h
  68. 2 2
      libs/SDL2/include/SDL_revision.h
  69. 1 1
      libs/SDL2/include/SDL_version.h
  70. 2 2
      libs/SDL2/src/SDL.c
  71. 10 2
      libs/SDL2/src/SDL_assert.c
  72. 2 0
      libs/SDL2/src/audio/emscripten/SDL_emscriptenaudio.c
  73. 220 69
      libs/SDL2/src/audio/os2/SDL_os2audio.c
  74. 3 2
      libs/SDL2/src/audio/os2/SDL_os2audio.h
  75. 2 0
      libs/SDL2/src/audio/qsa/SDL_qsa_audio.c
  76. 0 1
      libs/SDL2/src/core/linux/SDL_fcitx.c
  77. 13 0
      libs/SDL2/src/core/windows/SDL_windows.h
  78. 24 7
      libs/SDL2/src/events/SDL_keyboard.c
  79. 3 0
      libs/SDL2/src/events/SDL_keyboard_c.h
  80. 2 2
      libs/SDL2/src/file/SDL_rwops.c
  81. 3 3
      libs/SDL2/src/hidapi/linux/hid.c
  82. 1 0
      libs/SDL2/src/joystick/SDL_gamecontroller.c
  83. 4 10
      libs/SDL2/src/joystick/SDL_gamecontrollerdb.h
  84. 15 1
      libs/SDL2/src/joystick/SDL_joystick.c
  85. 87 76
      libs/SDL2/src/joystick/hidapi/SDL_hidapi_ps4.c
  86. 122 81
      libs/SDL2/src/joystick/hidapi/SDL_hidapi_ps5.c
  87. 3 3
      libs/SDL2/src/joystick/linux/SDL_sysjoystick.c
  88. 477 450
      libs/SDL2/src/joystick/os2/SDL_os2joystick.c
  89. 1 0
      libs/SDL2/src/joystick/sort_controllers.py
  90. 175 34
      libs/SDL2/src/joystick/windows/SDL_rawinputjoystick.c
  91. 2 2
      libs/SDL2/src/joystick/windows/SDL_rawinputjoystick_c.h
  92. 162 108
      libs/SDL2/src/joystick/windows/SDL_windows_gaming_input.c
  93. 14 7
      libs/SDL2/src/joystick/windows/SDL_xinputjoystick.c
  94. 1 1
      libs/SDL2/src/main/windows/SDL_windows_main.c
  95. 4 4
      libs/SDL2/src/main/windows/version.rc
  96. 3 5
      libs/SDL2/src/misc/emscripten/SDL_sysurl.c
  97. 13 0
      libs/SDL2/src/misc/unix/SDL_sysurl.c
  98. 1 1
      libs/SDL2/src/render/SDL_render.c
  99. 1 1
      libs/SDL2/src/render/direct3d11/SDL_render_d3d11.c
  100. 6 1
      libs/SDL2/src/render/direct3d12/SDL_render_d3d12.c

+ 2 - 2
CMakeLists.txt

@@ -198,12 +198,12 @@ endif()
 
 
 set(MEGA_ZLIB_VER "1.2.12")
 set(MEGA_ZLIB_VER "1.2.12")
 set(MEGA_LUA51_VER "5.1.5")
 set(MEGA_LUA51_VER "5.1.5")
-set(MEGA_LUAJIT_VER "2.1.0-1c27912")
+set(MEGA_LUAJIT_VER "2.1.0-e826d0c")
 set(MEGA_LIBOGG_VER "1.3.2")
 set(MEGA_LIBOGG_VER "1.3.2")
 set(MEGA_LIBVORBIS_VER "1.3.5")
 set(MEGA_LIBVORBIS_VER "1.3.5")
 set(MEGA_LIBTHEORA_VER "1.1.1")
 set(MEGA_LIBTHEORA_VER "1.1.1")
 set(MEGA_FREETYPE_VER "2.12.0")
 set(MEGA_FREETYPE_VER "2.12.0")
-set(MEGA_SDL2_VER "2.28.1")
+set(MEGA_SDL2_VER "2.28.4")
 set(MEGA_OPENAL_VER "1.22.0")
 set(MEGA_OPENAL_VER "1.22.0")
 set(MEGA_MODPLUG_VER "0.8.8.4")
 set(MEGA_MODPLUG_VER "0.8.8.4")
 
 

+ 1 - 1
libs/LuaJIT/.relver

@@ -1 +1 @@
-1694316387
+1697887905

+ 1 - 3
libs/LuaJIT/doc/extensions.html

@@ -426,9 +426,7 @@ the toolchain used to compile LuaJIT:
 on the C stack. The contents of the C++ exception object
 on the C stack. The contents of the C++ exception object
 pass through unmodified.</li>
 pass through unmodified.</li>
 <li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
 <li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
-The corresponding Lua error message can be retrieved from the Lua stack.<br>
-For MSVC for Windows 64 bit this requires compilation of your C++ code
-with <tt>/EHa</tt>.</li>
+The corresponding Lua error message can be retrieved from the Lua stack.</li>
 <li>Throwing Lua errors across C++ frames is safe. C++ destructors
 <li>Throwing Lua errors across C++ frames is safe. C++ destructors
 will be called.</li>
 will be called.</li>
 </ul>
 </ul>

+ 4 - 1
libs/LuaJIT/doc/install.html

@@ -203,7 +203,7 @@ Or install Microsoft's Visual Studio (MSVC).
 </p>
 </p>
 <h3>Building with MSVC</h3>
 <h3>Building with MSVC</h3>
 <p>
 <p>
-Open a "Visual Studio Command Prompt" (either x86 or x64), <tt>cd</tt> to the
+Open a "Visual Studio Command Prompt" (x86, x64 or ARM64), <tt>cd</tt> to the
 directory with the source code and run these commands:
 directory with the source code and run these commands:
 </p>
 </p>
 <pre class="code">
 <pre class="code">
@@ -214,6 +214,9 @@ msvcbuild
 Check the <tt>msvcbuild.bat</tt> file for more options.
 Check the <tt>msvcbuild.bat</tt> file for more options.
 Then follow the installation instructions below.
 Then follow the installation instructions below.
 </p>
 </p>
+<p>
+For an x64 to ARM64 cross-build run this first: <tt>vcvarsall.bat x64_arm64</tt>
+</p>
 <h3>Building with MinGW or Cygwin</h3>
 <h3>Building with MinGW or Cygwin</h3>
 <p>
 <p>
 Open a command prompt window and make sure the MinGW or Cygwin programs
 Open a command prompt window and make sure the MinGW or Cygwin programs

+ 2 - 1
libs/LuaJIT/doc/running.html

@@ -120,7 +120,8 @@ file name:
 </p>
 </p>
 <ul>
 <ul>
 <li><tt>c</tt> &mdash; C source file, exported bytecode data.</li>
 <li><tt>c</tt> &mdash; C source file, exported bytecode data.</li>
-<li><tt>h</tt> &mdash; C header file, static bytecode data.</li>
+<li><tt>cc</tt> &mdash; C++ source file, exported bytecode data.</li>
+<li><tt>h</tt> &mdash; C/C++ header file, static bytecode data.</li>
 <li><tt>obj</tt> or <tt>o</tt> &mdash; Object file, exported bytecode data
 <li><tt>obj</tt> or <tt>o</tt> &mdash; Object file, exported bytecode data
 (OS- and architecture-specific).</li>
 (OS- and architecture-specific).</li>
 <li><tt>raw</tt> or any other extension &mdash; Raw bytecode file (portable).
 <li><tt>raw</tt> or any other extension &mdash; Raw bytecode file (portable).

+ 4 - 4
libs/LuaJIT/dynasm/dasm_arm64.lua

@@ -549,7 +549,7 @@ end
 local function parse_load_pair(params, nparams, n, op)
 local function parse_load_pair(params, nparams, n, op)
   if params[n+2] then werror("too many operands") end
   if params[n+2] then werror("too many operands") end
   local pn, p2 = params[n], params[n+1]
   local pn, p2 = params[n], params[n+1]
-  local scale = shr(op, 30) == 0 and 2 or 3
+  local scale = 2 + shr(op, 31 - band(shr(op, 26), 1))
   local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
   local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
   if not p1 then
   if not p1 then
     if not p2 then
     if not p2 then
@@ -806,8 +806,8 @@ map_op = {
   ["ldrsw_*"] = "98000000DxB|b8800000DxL",
   ["ldrsw_*"] = "98000000DxB|b8800000DxL",
   -- NOTE: ldur etc. are handled by ldr et al.
   -- NOTE: ldur etc. are handled by ldr et al.
 
 
-  ["stp_*"]   = "28000000DAwP|a8000000DAxP|2c000000DAsP|6c000000DAdP",
-  ["ldp_*"]   = "28400000DAwP|a8400000DAxP|2c400000DAsP|6c400000DAdP",
+  ["stp_*"]   = "28000000DAwP|a8000000DAxP|2c000000DAsP|6c000000DAdP|ac000000DAqP",
+  ["ldp_*"]   = "28400000DAwP|a8400000DAxP|2c400000DAsP|6c400000DAdP|ac400000DAqP",
   ["ldpsw_*"] = "68400000DAxP",
   ["ldpsw_*"] = "68400000DAxP",
 
 
   -- Branches.
   -- Branches.
@@ -942,7 +942,7 @@ local function parse_template(params, template, nparams, pos)
 	werror("bad register type")
 	werror("bad register type")
       end
       end
       parse_reg_type = false
       parse_reg_type = false
-    elseif p == "x" or p == "w" or p == "d" or p == "s" then
+    elseif p == "x" or p == "w" or p == "d" or p == "s" or p == "q" then
       if parse_reg_type ~= p then
       if parse_reg_type ~= p then
 	werror("register size mismatch")
 	werror("register size mismatch")
       end
       end

+ 10 - 11
libs/LuaJIT/src/host/buildvm_peobj.c

@@ -9,7 +9,7 @@
 #include "buildvm.h"
 #include "buildvm.h"
 #include "lj_bc.h"
 #include "lj_bc.h"
 
 
-#if LJ_TARGET_WINDOWS
+#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
 
 
 /* Context for PE object emitter. */
 /* Context for PE object emitter. */
 static char *strtab;
 static char *strtab;
@@ -354,15 +354,15 @@ void emit_peobj(BuildCtx *ctx)
 #define CBE16(x)	(*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2)
 #define CBE16(x)	(*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2)
 #define CALLOC_S(s)	(*p++ = ((s) >> 4))  /* s < 512 */
 #define CALLOC_S(s)	(*p++ = ((s) >> 4))  /* s < 512 */
 #define CSAVE_FPLR(o)	(*p++ = 0x40 | ((o) >> 3))  /* o <= 504 */
 #define CSAVE_FPLR(o)	(*p++ = 0x40 | ((o) >> 3))  /* o <= 504 */
-#define CSAVE_REGP(r,o)	CBE16(0xc800 | (((r)-19)<< 6) | ((o) >> 3))
+#define CSAVE_REGP(r,o)	CBE16(0xc800 | (((r) - 19) << 6) | ((o) >> 3))
 #define CSAVE_REGS(r1,r2,o1) do { \
 #define CSAVE_REGS(r1,r2,o1) do { \
   int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \
   int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \
 } while (0)
 } while (0)
+#define CSAVE_REGPX(r,o) CBE16(0xcc00 | (((r) - 19) << 6) | (~(o) >> 3))
 #define CSAVE_FREGP(r,o) CBE16(0xd800 | (((r) - 8) << 6) | ((o) >> 3))
 #define CSAVE_FREGP(r,o) CBE16(0xd800 | (((r) - 8) << 6) | ((o) >> 3))
 #define CSAVE_FREGS(r1,r2,o1) do { \
 #define CSAVE_FREGS(r1,r2,o1) do { \
   int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \
   int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \
 } while (0)
 } while (0)
-#define CSAVE_REGX(r,o)	CBE16(0xd400 | (((r) - 19) << 5) | (~(o) >> 3))
 #define CADD_FP(s)	CBE16(0xe200 | ((s) >> 3))  /* s < 8*256 */
 #define CADD_FP(s)	CBE16(0xe200 | ((s) >> 3))  /* s < 8*256 */
 #define CODE_NOP	0xe3
 #define CODE_NOP	0xe3
 #define CODE_END	0xe4
 #define CODE_END	0xe4
@@ -373,11 +373,11 @@ void emit_peobj(BuildCtx *ctx)
 
 
     /* Unwind codes for .text section with handler. */
     /* Unwind codes for .text section with handler. */
     p = uwc;
     p = uwc;
-    CALLOC_S(208);		/* +1 */
-    CSAVE_FPLR(192);		/* +1 */
     CADD_FP(192);		/* +2 */
     CADD_FP(192);		/* +2 */
-    CSAVE_REGS(19, 28, 184);	/* +5*2 */
-    CSAVE_FREGS(8, 15, 104);	/* +4*2 */
+    CSAVE_REGS(19, 28, 176);	/* +5*2 */
+    CSAVE_FREGS(8, 15, 96);	/* +4*2 */
+    CSAVE_FPLR(192);		/* +1 */
+    CALLOC_S(208);		/* +1 */
     CEND_ALIGN;			/* +1 +1 -> 24 */
     CEND_ALIGN;			/* +1 +1 -> 24 */
 
 
     u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2);
     u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2);
@@ -389,11 +389,10 @@ void emit_peobj(BuildCtx *ctx)
 
 
     /* Unwind codes for vm_ffi_call without handler. */
     /* Unwind codes for vm_ffi_call without handler. */
     p = uwc;
     p = uwc;
-    CSAVE_FPLR(16);		/* +1 */
     CADD_FP(16);		/* +2 */
     CADD_FP(16);		/* +2 */
-    CSAVE_REGX(19, -24);	/* +2 */
-    CSAVE_REGX(20, -32);	/* +2 */
-    CEND_ALIGN;			/* +1 +0 -> 8 */
+    CSAVE_FPLR(16);		/* +1 */
+    CSAVE_REGPX(19, -32);	/* +2 */
+    CEND_ALIGN;			/* +1 +2 -> 8 */
 
 
     u32 = ((8u >> 2) << 27) | (((uint32_t)ctx->codesz - fcofs) >> 2);
     u32 = ((8u >> 2) << 27) | (((uint32_t)ctx->codesz - fcofs) >> 2);
     owrite(ctx, &u32, 4);
     owrite(ctx, &u32, 4);

+ 2 - 2
libs/LuaJIT/src/jit/bcsave.lua

@@ -38,7 +38,7 @@ Save LuaJIT bytecode: luajit -b[options] input output
   --        Stop handling options.
   --        Stop handling options.
   -         Use stdin as input and/or stdout as output.
   -         Use stdin as input and/or stdout as output.
 
 
-File types: c h obj o raw (default)
+File types: c cc h obj o raw (default)
 ]]
 ]]
   os.exit(1)
   os.exit(1)
 end
 end
@@ -81,7 +81,7 @@ end
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 
 
 local map_type = {
 local map_type = {
-  raw = "raw", c = "c", h = "h", o = "obj", obj = "obj",
+  raw = "raw", c = "c", cc = "c", h = "h", o = "obj", obj = "obj",
 }
 }
 
 
 local map_arch = {
 local map_arch = {

+ 1 - 1
libs/LuaJIT/src/jit/dis_arm64.lua

@@ -948,7 +948,7 @@ local function disass_ins(ctx)
     elseif p == "U" then
     elseif p == "U" then
       local rn = map_regs.x[band(rshift(op, 5), 31)]
       local rn = map_regs.x[band(rshift(op, 5), 31)]
       local sz = band(rshift(op, 30), 3)
       local sz = band(rshift(op, 30), 3)
-      local imm12 = lshift(arshift(lshift(op, 10), 20), sz)
+      local imm12 = lshift(rshift(lshift(op, 10), 20), sz)
       if imm12 ~= 0 then
       if imm12 ~= 0 then
 	x = "["..rn..", #"..imm12.."]"
 	x = "["..rn..", #"..imm12.."]"
       else
       else

+ 4 - 1
libs/LuaJIT/src/lib_base.c

@@ -616,7 +616,10 @@ static int ffh_resume(lua_State *L, lua_State *co, int wrap)
     setstrV(L, L->base-LJ_FR2, lj_err_str(L, em));
     setstrV(L, L->base-LJ_FR2, lj_err_str(L, em));
     return FFH_RES(2);
     return FFH_RES(2);
   }
   }
-  lj_state_growstack(co, (MSize)(L->top - L->base));
+  if (lj_state_cpgrowstack(co, (MSize)(L->top - L->base)) != LUA_OK) {
+    cTValue *msg = --co->top;
+    lj_err_callermsg(L, strVdata(msg));
+  }
   return FFH_RETRY;
   return FFH_RETRY;
 }
 }
 
 

+ 1 - 1
libs/LuaJIT/src/lib_ffi.c

@@ -746,7 +746,7 @@ LJLIB_CF(ffi_abi)	LJLIB_REC(.)
     "\003win"
     "\003win"
 #endif
 #endif
 #if LJ_ABI_PAUTH
 #if LJ_ABI_PAUTH
-    "\007pauth"
+    "\005pauth"
 #endif
 #endif
 #if LJ_TARGET_UWP
 #if LJ_TARGET_UWP
     "\003uwp"
     "\003uwp"

+ 6 - 1
libs/LuaJIT/src/lj_api.c

@@ -104,7 +104,12 @@ LUA_API int lua_checkstack(lua_State *L, int size)
   if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) {
   if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) {
     return 0;  /* Stack overflow. */
     return 0;  /* Stack overflow. */
   } else if (size > 0) {
   } else if (size > 0) {
-    lj_state_checkstack(L, (MSize)size);
+    int avail = (int)(mref(L->maxstack, TValue) - L->top);
+    if (size > avail &&
+	lj_state_cpgrowstack(L, (MSize)(size - avail)) != LUA_OK) {
+      L->top--;
+      return 0;  /* Out of memory. */
+    }
   }
   }
   return 1;
   return 1;
 }
 }

+ 1 - 1
libs/LuaJIT/src/lj_asm_arm.h

@@ -2255,7 +2255,7 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
   }
   }
   if (nslots > as->evenspill)  /* Leave room for args in stack slots. */
   if (nslots > as->evenspill)  /* Leave room for args in stack slots. */
     as->evenspill = nslots;
     as->evenspill = nslots;
-  return REGSP_HINT(RID_RET);
+  return REGSP_HINT(irt_isfp(ir->t) ? RID_FPRET : RID_RET);
 }
 }
 
 
 static void asm_setup_target(ASMState *as)
 static void asm_setup_target(ASMState *as)

+ 33 - 18
libs/LuaJIT/src/lj_asm_arm64.h

@@ -222,7 +222,8 @@ static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
     return A64F_M(ir->r);
     return A64F_M(ir->r);
   } else if (irref_isk(ref)) {
   } else if (irref_isk(ref)) {
     int64_t k = get_k64val(as, ref);
     int64_t k = get_k64val(as, ref);
-    uint32_t m = logical ? emit_isk13(k, irt_is64(ir->t)) : emit_isk12(k);
+    uint32_t m = logical ? emit_isk13(k, irt_is64(ir->t)) :
+			   emit_isk12(irt_is64(ir->t) ? k : (int32_t)k);
     if (m)
     if (m)
       return m;
       return m;
   } else if (mayfuse(as, ref)) {
   } else if (mayfuse(as, ref)) {
@@ -432,6 +433,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
   for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++)
   for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++)
     as->cost[gpr] = REGCOST(~0u, ASMREF_L);
     as->cost[gpr] = REGCOST(~0u, ASMREF_L);
   gpr = REGARG_FIRSTGPR;
   gpr = REGARG_FIRSTGPR;
+#if LJ_HASFFI && LJ_ABI_WIN
+  if ((ci->flags & CCI_VARARG)) {
+    fpr = REGARG_LASTFPR+1;
+  }
+#endif
   for (n = 0; n < nargs; n++) { /* Setup args. */
   for (n = 0; n < nargs; n++) { /* Setup args. */
     IRRef ref = args[n];
     IRRef ref = args[n];
     IRIns *ir = IR(ref);
     IRIns *ir = IR(ref);
@@ -442,6 +448,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
 		     "reg %d not free", fpr);  /* Must have been evicted. */
 		     "reg %d not free", fpr);  /* Must have been evicted. */
 	  ra_leftov(as, fpr, ref);
 	  ra_leftov(as, fpr, ref);
 	  fpr++;
 	  fpr++;
+#if LJ_HASFFI && LJ_ABI_WIN
+	} else if ((ci->flags & CCI_VARARG) && (gpr <= REGARG_LASTGPR)) {
+	  Reg rf = ra_alloc1(as, ref, RSET_FPR);
+	  emit_dn(as, A64I_FMOV_R_D, gpr++, rf & 31);
+#endif
 	} else {
 	} else {
 	  Reg r = ra_alloc1(as, ref, RSET_FPR);
 	  Reg r = ra_alloc1(as, ref, RSET_FPR);
 	  int32_t al = spalign;
 	  int32_t al = spalign;
@@ -776,7 +787,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
   int destused = ra_used(ir);
   int destused = ra_used(ir);
   Reg dest = ra_dest(as, ir, allow);
   Reg dest = ra_dest(as, ir, allow);
   Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest));
   Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest));
-  Reg key = 0, tmp = RID_TMP, type = RID_NONE, tkey;
+  Reg tmp = RID_TMP, type = RID_NONE, key, tkey;
   IRRef refkey = ir->op2;
   IRRef refkey = ir->op2;
   IRIns *irkey = IR(refkey);
   IRIns *irkey = IR(refkey);
   int isk = irref_isk(refkey);
   int isk = irref_isk(refkey);
@@ -786,26 +797,22 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
   MCLabel l_end, l_loop;
   MCLabel l_end, l_loop;
   rset_clear(allow, tab);
   rset_clear(allow, tab);
 
 
-  /* Allocate registers outside of the loop. */
-  if (irkey->o != IR_KNUM || !(k = emit_isk12((int64_t)ir_knum(irkey)->u64))) {
-    key = ra_alloc1(as, refkey, irt_isnum(kt) ? RSET_FPR : allow);
-    rset_clear(allow, key);
-  }
-  if (!isk) {
-    tkey = ra_scratch(as, allow);
-    rset_clear(allow, tkey);
-  } else if (irt_isnum(kt)) {
-    tkey = key; /* Assumes -0.0 is already canonicalized to +0.0. */
-  } else {
+  /* Allocate register for tkey outside of the loop. */
+  if (isk) {
     int64_t kk;
     int64_t kk;
     if (irt_isaddr(kt)) {
     if (irt_isaddr(kt)) {
       kk = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
       kk = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
+    } else if (irt_isnum(kt)) {
+      kk = (int64_t)ir_knum(irkey)->u64;
+      /* Assumes -0.0 is already canonicalized to +0.0. */
     } else {
     } else {
       lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
       lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
       kk = ~((int64_t)~irt_toitype(kt) << 47);
       kk = ~((int64_t)~irt_toitype(kt) << 47);
     }
     }
-    tkey = ra_allock(as, kk, allow);
-    rset_clear(allow, tkey);
+    k = emit_isk12(kk);
+    tkey = k ? 0 : ra_allock(as, kk, allow);
+  } else {
+    tkey = ra_scratch(as, allow);
   }
   }
 
 
   /* Key not found in chain: jump to exit (if merged) or load niltv. */
   /* Key not found in chain: jump to exit (if merged) or load niltv. */
@@ -838,10 +845,13 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
   /* Construct tkey as canonicalized or tagged key. */
   /* Construct tkey as canonicalized or tagged key. */
   if (!isk) {
   if (!isk) {
     if (irt_isnum(kt)) {
     if (irt_isnum(kt)) {
+      key = ra_alloc1(as, refkey, RSET_FPR);
       emit_dnm(as, A64I_CSELx | A64F_CC(CC_EQ), tkey, RID_ZERO, tkey);
       emit_dnm(as, A64I_CSELx | A64F_CC(CC_EQ), tkey, RID_ZERO, tkey);
+      /* A64I_FMOV_R_D from key to tkey done below. */
     } else {
     } else {
       lj_assertA(irt_isaddr(kt), "bad HREF key type");
       lj_assertA(irt_isaddr(kt), "bad HREF key type");
-      type = ra_allock(as, irt_toitype(kt) << 15, allow);
+      key = ra_alloc1(as, refkey, allow);
+      type = ra_allock(as, irt_toitype(kt) << 15, rset_clear(allow, key));
       emit_dnm(as, A64I_ADDx | A64F_SH(A64SH_LSL, 32), tkey, key, type);
       emit_dnm(as, A64I_ADDx | A64F_SH(A64SH_LSL, 32), tkey, key, type);
     }
     }
   }
   }
@@ -1943,6 +1953,9 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
     int ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
     int ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
     int spofs = 0, spalign = LJ_TARGET_OSX ? 0 : 7, nslots;
     int spofs = 0, spalign = LJ_TARGET_OSX ? 0 : 7, nslots;
     asm_collectargs(as, ir, ci, args);
     asm_collectargs(as, ir, ci, args);
+#if LJ_ABI_WIN
+    if ((ci->flags & CCI_VARARG)) nfpr = 0;
+#endif
     for (i = 0; i < nargs; i++) {
     for (i = 0; i < nargs; i++) {
       int al = spalign;
       int al = spalign;
       if (!args[i]) {
       if (!args[i]) {
@@ -1954,7 +1967,9 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
 #endif
 #endif
       } else if (irt_isfp(IR(args[i])->t)) {
       } else if (irt_isfp(IR(args[i])->t)) {
 	if (nfpr > 0) { nfpr--; continue; }
 	if (nfpr > 0) { nfpr--; continue; }
-#if LJ_TARGET_OSX
+#if LJ_ABI_WIN
+	if ((ci->flags & CCI_VARARG) && ngpr > 0) { ngpr--; continue; }
+#elif LJ_TARGET_OSX
 	al |= irt_isnum(IR(args[i])->t) ? 7 : 3;
 	al |= irt_isnum(IR(args[i])->t) ? 7 : 3;
 #endif
 #endif
       } else {
       } else {
@@ -1970,7 +1985,7 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
       as->evenspill = nslots;
       as->evenspill = nslots;
   }
   }
 #endif
 #endif
-  return REGSP_HINT(RID_RET);
+  return REGSP_HINT(irt_isfp(ir->t) ? RID_FPRET : RID_RET);
 }
 }
 
 
 static void asm_setup_target(ASMState *as)
 static void asm_setup_target(ASMState *as)

+ 2 - 1
libs/LuaJIT/src/lj_asm_x86.h

@@ -140,7 +140,8 @@ static IRRef asm_fuseabase(ASMState *as, IRRef ref)
     }
     }
   } else if (irb->o == IR_ADD && irref_isk(irb->op2)) {
   } else if (irb->o == IR_ADD && irref_isk(irb->op2)) {
     /* Fuse base offset (vararg load). */
     /* Fuse base offset (vararg load). */
-    as->mrm.ofs = IR(irb->op2)->i;
+    IRIns *irk = IR(irb->op2);
+    as->mrm.ofs = irk->o == IR_KINT ? irk->i : (int32_t)ir_kint64(irk)->u64;
     return irb->op1;
     return irb->op1;
   }
   }
   return ref;  /* Otherwise use the given array base. */
   return ref;  /* Otherwise use the given array base. */

+ 4 - 0
libs/LuaJIT/src/lj_carith.c

@@ -44,9 +44,13 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca)
 	p = (uint8_t *)cdata_getptr(p, ct->size);
 	p = (uint8_t *)cdata_getptr(p, ct->size);
 	if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
 	if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
       } else if (ctype_isfunc(ct->info)) {
       } else if (ctype_isfunc(ct->info)) {
+	CTypeID id0 = i ? ctype_typeid(cts, ca->ct[0]) : 0;
 	p = (uint8_t *)*(void **)p;
 	p = (uint8_t *)*(void **)p;
 	ct = ctype_get(cts,
 	ct = ctype_get(cts,
 	  lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR));
 	  lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR));
+	if (i) {  /* cts->tab may have been reallocated. */
+	  ca->ct[0] = ctype_get(cts, id0);
+	}
       }
       }
       if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
       if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
       ca->ct[i] = ct;
       ca->ct[i] = ct;

+ 17 - 1
libs/LuaJIT/src/lj_ccall.c

@@ -985,6 +985,14 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
     fid = ctf->sib;
     fid = ctf->sib;
   }
   }
 
 
+#if LJ_TARGET_ARM64 && LJ_ABI_WIN
+  if ((ct->info & CTF_VARARG)) {
+    nsp -= maxgpr * CTSIZE_PTR;  /* May end up with negative nsp. */
+    ngpr = maxgpr;
+    nfpr = CCALL_NARG_FPR;
+  }
+#endif
+
   /* Walk through all passed arguments. */
   /* Walk through all passed arguments. */
   for (o = L->base+1, narg = 1; o < top; o++, narg++) {
   for (o = L->base+1, narg = 1; o < top; o++, narg++) {
     CTypeID did;
     CTypeID did;
@@ -1035,9 +1043,14 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
 	align = CTSIZE_PTR-1;
 	align = CTSIZE_PTR-1;
       nsp = (nsp + align) & ~align;
       nsp = (nsp + align) & ~align;
     }
     }
+#if LJ_TARGET_ARM64 && LJ_ABI_WIN
+    /* A negative nsp points into cc->gpr. Blame MS for their messy ABI. */
+    dp = ((uint8_t *)cc->stack) + (int32_t)nsp;
+#else
     dp = ((uint8_t *)cc->stack) + nsp;
     dp = ((uint8_t *)cc->stack) + nsp;
+#endif
     nsp += CCALL_PACK_STACKARG ? sz : n * CTSIZE_PTR;
     nsp += CCALL_PACK_STACKARG ? sz : n * CTSIZE_PTR;
-    if (nsp > CCALL_SIZE_STACK) {  /* Too many arguments. */
+    if ((int32_t)nsp > CCALL_SIZE_STACK) {  /* Too many arguments. */
     err_nyi:
     err_nyi:
       lj_err_caller(L, LJ_ERR_FFI_NYICALL);
       lj_err_caller(L, LJ_ERR_FFI_NYICALL);
     }
     }
@@ -1099,6 +1112,9 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
 #endif
 #endif
   }
   }
   if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG);  /* Too few arguments. */
   if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG);  /* Too few arguments. */
+#if LJ_TARGET_ARM64 && LJ_ABI_WIN
+  if ((int32_t)nsp < 0) nsp = 0;
+#endif
 
 
 #if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP)
 #if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP)
   cc->nfpr = nfpr;  /* Required for vararg functions. */
   cc->nfpr = nfpr;  /* Required for vararg functions. */

+ 1 - 5
libs/LuaJIT/src/lj_crecord.c

@@ -1118,12 +1118,8 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
     ngpr = 1;
     ngpr = 1;
   else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
   else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
     ngpr = 2;
     ngpr = 2;
-#elif LJ_TARGET_ARM64
-#if LJ_ABI_WIN
-#error "NYI: ARM64 Windows ABI calling conventions"
-#elif LJ_TARGET_OSX
+#elif LJ_TARGET_ARM64 && LJ_TARGET_OSX
   int ngpr = CCALL_NARG_GPR;
   int ngpr = CCALL_NARG_GPR;
-#endif
 #endif
 #endif
 
 
   /* Skip initial attributes. */
   /* Skip initial attributes. */

+ 4 - 2
libs/LuaJIT/src/lj_ctype.h

@@ -276,6 +276,8 @@ typedef struct CTState {
 #define CTTYDEFP(_)
 #define CTTYDEFP(_)
 #endif
 #endif
 
 
+#define CTF_LONG_IF8		(CTF_LONG * (sizeof(long) == 8))
+
 /* Common types. */
 /* Common types. */
 #define CTTYDEF(_) \
 #define CTTYDEF(_) \
   _(NONE,		0,	CT_ATTRIB, CTATTRIB(CTA_BAD)) \
   _(NONE,		0,	CT_ATTRIB, CTATTRIB(CTA_BAD)) \
@@ -289,8 +291,8 @@ typedef struct CTState {
   _(UINT16,		2,	CT_NUM, CTF_UNSIGNED|CTALIGN(1)) \
   _(UINT16,		2,	CT_NUM, CTF_UNSIGNED|CTALIGN(1)) \
   _(INT32,		4,	CT_NUM, CTALIGN(2)) \
   _(INT32,		4,	CT_NUM, CTALIGN(2)) \
   _(UINT32,		4,	CT_NUM, CTF_UNSIGNED|CTALIGN(2)) \
   _(UINT32,		4,	CT_NUM, CTF_UNSIGNED|CTALIGN(2)) \
-  _(INT64,		8,	CT_NUM, CTF_LONG|CTALIGN(3)) \
-  _(UINT64,		8,	CT_NUM, CTF_UNSIGNED|CTF_LONG|CTALIGN(3)) \
+  _(INT64,		8,	CT_NUM, CTF_LONG_IF8|CTALIGN(3)) \
+  _(UINT64,		8,	CT_NUM, CTF_UNSIGNED|CTF_LONG_IF8|CTALIGN(3)) \
   _(FLOAT,		4,	CT_NUM, CTF_FP|CTALIGN(2)) \
   _(FLOAT,		4,	CT_NUM, CTF_FP|CTALIGN(2)) \
   _(DOUBLE,		8,	CT_NUM, CTF_FP|CTALIGN(3)) \
   _(DOUBLE,		8,	CT_NUM, CTF_FP|CTALIGN(3)) \
   _(COMPLEX_FLOAT,	8,	CT_ARRAY, CTF_COMPLEX|CTALIGN(2)|CTID_FLOAT) \
   _(COMPLEX_FLOAT,	8,	CT_ARRAY, CTF_COMPLEX|CTALIGN(2)|CTID_FLOAT) \

+ 1 - 1
libs/LuaJIT/src/lj_def.h

@@ -69,7 +69,7 @@ typedef unsigned int uintptr_t;
 #define LJ_MAX_UPVAL	60		/* Max. # of upvalues. */
 #define LJ_MAX_UPVAL	60		/* Max. # of upvalues. */
 
 
 #define LJ_MAX_IDXCHAIN	100		/* __index/__newindex chain limit. */
 #define LJ_MAX_IDXCHAIN	100		/* __index/__newindex chain limit. */
-#define LJ_STACK_EXTRA	(5+2*LJ_FR2)	/* Extra stack space (metamethods). */
+#define LJ_STACK_EXTRA	(5+3*LJ_FR2)	/* Extra stack space (metamethods). */
 
 
 #define LJ_NUM_CBPAGE	1		/* Number of FFI callback pages. */
 #define LJ_NUM_CBPAGE	1		/* Number of FFI callback pages. */
 
 

+ 1 - 1
libs/LuaJIT/src/lj_dispatch.c

@@ -453,7 +453,7 @@ static int call_init(lua_State *L, GCfunc *fn)
     int numparams = pt->numparams;
     int numparams = pt->numparams;
     int gotparams = (int)(L->top - L->base);
     int gotparams = (int)(L->top - L->base);
     int need = pt->framesize;
     int need = pt->framesize;
-    if ((pt->flags & PROTO_VARARG)) need += 1+gotparams;
+    if ((pt->flags & PROTO_VARARG)) need += 1+LJ_FR2+gotparams;
     lj_state_checkstack(L, (MSize)need);
     lj_state_checkstack(L, (MSize)need);
     numparams -= gotparams;
     numparams -= gotparams;
     return numparams >= 0 ? numparams : 0;
     return numparams >= 0 ? numparams : 0;

+ 31 - 9
libs/LuaJIT/src/lj_emit_arm64.h

@@ -124,9 +124,9 @@ static LJ_AINLINE uint32_t emit_lso_pair_candidate(A64Ins ai, int ofs, int sc)
   }
   }
 }
 }
 
 
-static void emit_lso(ASMState *as, A64Ins ai, Reg rd, Reg rn, int64_t ofs)
+static void emit_lso(ASMState *as, A64Ins ai, Reg rd, Reg rn, int64_t ofs64)
 {
 {
-  int ot = emit_checkofs(ai, ofs), sc = (ai >> 30) & 3;
+  int ot = emit_checkofs(ai, ofs64), sc = (ai >> 30) & 3, ofs = (int)ofs64;
   lj_assertA(ot, "load/store offset %d out of range", ofs);
   lj_assertA(ot, "load/store offset %d out of range", ofs);
   /* Combine LDR/STR pairs to LDP/STP. */
   /* Combine LDR/STR pairs to LDP/STP. */
   if ((sc == 2 || sc == 3) &&
   if ((sc == 2 || sc == 3) &&
@@ -193,6 +193,32 @@ static int emit_kdelta(ASMState *as, Reg rd, uint64_t k, int is64)
   return 0;  /* Failed. */
   return 0;  /* Failed. */
 }
 }
 
 
+#define glofs(as, k) \
+  ((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g))
+#define mcpofs(as, k) \
+  ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1)))
+#define checkmcpofs(as, k) \
+  (A64F_S_OK(mcpofs(as, k)>>2, 19))
+
+/* Try to form a const as ADR or ADRP or ADRP + ADD. */
+static int emit_kadrp(ASMState *as, Reg rd, uint64_t k)
+{
+  A64Ins ai = A64I_ADR;
+  int64_t ofs = mcpofs(as, k);
+  if (!A64F_S_OK((uint64_t)ofs, 21)) {
+    uint64_t kpage = k & ~0xfffull;
+    MCode *adrp = as->mcp - 1 - (k != kpage);
+    ofs = (int64_t)(kpage - ((uint64_t)adrp & ~0xfffull)) >> 12;
+    if (!A64F_S_OK(ofs, 21))
+      return 0;  /* Failed. */
+    if (k != kpage)
+      emit_dn(as, (A64I_ADDx^A64I_K12)|A64F_U12(k - kpage), rd, rd);
+    ai = A64I_ADRP;
+  }
+  emit_d(as, ai|(((uint32_t)ofs&3)<<29)|A64F_S19(ofs>>2), rd);
+  return 1;
+}
+
 static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
 static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
 {
 {
   int zeros = 0, ones = 0, neg, lshift = 0;
   int zeros = 0, ones = 0, neg, lshift = 0;
@@ -213,6 +239,9 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
     if (emit_kdelta(as, rd, u64, is64)) {
     if (emit_kdelta(as, rd, u64, is64)) {
       return;
       return;
     }
     }
+    if (emit_kadrp(as, rd, u64)) {  /* Either 1 or 2 ins. */
+      return;
+    }
   }
   }
   if (neg) {
   if (neg) {
     u64 = ~u64;
     u64 = ~u64;
@@ -240,13 +269,6 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
 /* Load a 64 bit constant into a GPR. */
 /* Load a 64 bit constant into a GPR. */
 #define emit_loadu64(as, rd, i)	emit_loadk(as, rd, i)
 #define emit_loadu64(as, rd, i)	emit_loadk(as, rd, i)
 
 
-#define glofs(as, k) \
-  ((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g))
-#define mcpofs(as, k) \
-  ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1)))
-#define checkmcpofs(as, k) \
-  (A64F_S_OK(mcpofs(as, k)>>2, 19))
-
 static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
 static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
 
 
 /* Get/set from constant pointer. */
 /* Get/set from constant pointer. */

+ 40 - 11
libs/LuaJIT/src/lj_err.c

@@ -174,12 +174,15 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
     case FRAME_PCALL:  /* FF pcall() frame. */
     case FRAME_PCALL:  /* FF pcall() frame. */
     case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
     case FRAME_PCALLH:  /* FF pcall() frame inside hook. */
       if (errcode) {
       if (errcode) {
+	global_State *g;
 	if (errcode == LUA_YIELD) {
 	if (errcode == LUA_YIELD) {
 	  frame = frame_prevd(frame);
 	  frame = frame_prevd(frame);
 	  break;
 	  break;
 	}
 	}
+	g = G(L);
+	setgcref(g->cur_L, obj2gco(L));
 	if (frame_typep(frame) == FRAME_PCALL)
 	if (frame_typep(frame) == FRAME_PCALL)
-	  hook_leave(G(L));
+	  hook_leave(g);
 	L->base = frame_prevd(frame) + 1;
 	L->base = frame_prevd(frame) + 1;
 	L->cframe = cf;
 	L->cframe = cf;
 	unwindstack(L, L->base);
 	unwindstack(L, L->base);
@@ -209,11 +212,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
 ** from 3rd party docs or must be found by trial-and-error. They really
 ** from 3rd party docs or must be found by trial-and-error. They really
 ** don't want you to write your own language-specific exception handler
 ** don't want you to write your own language-specific exception handler
 ** or to interact gracefully with MSVC. :-(
 ** or to interact gracefully with MSVC. :-(
-**
-** Apparently MSVC doesn't call C++ destructors for foreign exceptions
-** unless you compile your C++ code with /EHa. Unfortunately this means
-** catch (...) also catches things like access violations. The use of
-** _set_se_translator doesn't really help, because it requires /EHa, too.
 */
 */
 
 
 #define WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
@@ -261,6 +259,8 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,
 {
 {
 #if LJ_TARGET_X86
 #if LJ_TARGET_X86
   void *cf = (char *)f - CFRAME_OFS_SEH;
   void *cf = (char *)f - CFRAME_OFS_SEH;
+#elif LJ_TARGET_ARM64
+  void *cf = (char *)f - CFRAME_SIZE;
 #else
 #else
   void *cf = f;
   void *cf = f;
 #endif
 #endif
@@ -268,11 +268,25 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,
   int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
   int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
 		LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
 		LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
   if ((rec->ExceptionFlags & 6)) {  /* EH_UNWINDING|EH_EXIT_UNWIND */
   if ((rec->ExceptionFlags & 6)) {  /* EH_UNWINDING|EH_EXIT_UNWIND */
+    if (rec->ExceptionCode == STATUS_LONGJUMP &&
+	rec->ExceptionRecord &&
+	LJ_EXCODE_CHECK(rec->ExceptionRecord->ExceptionCode)) {
+      errcode = LJ_EXCODE_ERRCODE(rec->ExceptionRecord->ExceptionCode);
+      if ((rec->ExceptionFlags & 0x20)) {  /* EH_TARGET_UNWIND */
+	/* Unwinding is about to finish; revert the ExceptionCode so that
+	** RtlRestoreContext does not try to restore from a _JUMP_BUFFER.
+	*/
+	rec->ExceptionCode = 0;
+      }
+    }
     /* Unwind internal frames. */
     /* Unwind internal frames. */
     err_unwind(L, cf, errcode);
     err_unwind(L, cf, errcode);
   } else {
   } else {
     void *cf2 = err_unwind(L, cf, 0);
     void *cf2 = err_unwind(L, cf, 0);
     if (cf2) {  /* We catch it, so start unwinding the upper frames. */
     if (cf2) {  /* We catch it, so start unwinding the upper frames. */
+#if !LJ_TARGET_X86
+      EXCEPTION_RECORD rec2;
+#endif
       if (rec->ExceptionCode == LJ_MSVC_EXCODE ||
       if (rec->ExceptionCode == LJ_MSVC_EXCODE ||
 	  rec->ExceptionCode == LJ_GCC_EXCODE) {
 	  rec->ExceptionCode == LJ_GCC_EXCODE) {
 #if !LJ_TARGET_CYGWIN
 #if !LJ_TARGET_CYGWIN
@@ -295,14 +309,29 @@ LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,
 	(void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);
 	(void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);
       /* lj_vm_rtlunwind does not return. */
       /* lj_vm_rtlunwind does not return. */
 #else
 #else
+      if (LJ_EXCODE_CHECK(rec->ExceptionCode)) {
+	/* For unwind purposes, wrap the EXCEPTION_RECORD in something that
+	** looks like a longjmp, so that MSVC will execute C++ destructors in
+	** the frames we unwind over. ExceptionInformation[0] should really
+	** contain a _JUMP_BUFFER*, but hopefully nobody is looking too closely
+	** at this point.
+	*/
+	rec2.ExceptionCode = STATUS_LONGJUMP;
+	rec2.ExceptionRecord = rec;
+	rec2.ExceptionAddress = 0;
+	rec2.NumberParameters = 1;
+	rec2.ExceptionInformation[0] = (ULONG_PTR)ctx;
+	rec = &rec2;
+      }
       /* Unwind the stack and call all handlers for all lower C frames
       /* Unwind the stack and call all handlers for all lower C frames
       ** (including ourselves) again with EH_UNWINDING set. Then set
       ** (including ourselves) again with EH_UNWINDING set. Then set
-      ** stack pointer = cf, result = errcode and jump to the specified target.
+      ** stack pointer = f, result = errcode and jump to the specified target.
       */
       */
-      RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
-			       lj_vm_unwind_ff_eh :
-			       lj_vm_unwind_c_eh),
-		  rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);
+      RtlUnwindEx(f, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
+			      lj_vm_unwind_ff_eh :
+			      lj_vm_unwind_c_eh),
+		  rec, (void *)(uintptr_t)errcode, dispatch->ContextRecord,
+		  dispatch->HistoryTable);
       /* RtlUnwindEx should never return. */
       /* RtlUnwindEx should never return. */
 #endif
 #endif
     }
     }

+ 11 - 12
libs/LuaJIT/src/lj_ffrecord.c

@@ -1130,7 +1130,7 @@ static TRef recff_sbufx_check(jit_State *J, RecordFFData *rd, ptrdiff_t arg)
 /* Emit BUFHDR for write to extended string buffer. */
 /* Emit BUFHDR for write to extended string buffer. */
 static TRef recff_sbufx_write(jit_State *J, TRef ud)
 static TRef recff_sbufx_write(jit_State *J, TRef ud)
 {
 {
-  TRef trbuf = emitir(IRT(IR_ADD, IRT_PGC), ud, lj_ir_kint(J, sizeof(GCudata)));
+  TRef trbuf = emitir(IRT(IR_ADD, IRT_PGC), ud, lj_ir_kintpgc(J, sizeof(GCudata)));
   return emitir(IRT(IR_BUFHDR, IRT_PGC), trbuf, IRBUFHDR_WRITE);
   return emitir(IRT(IR_BUFHDR, IRT_PGC), trbuf, IRBUFHDR_WRITE);
 }
 }
 
 
@@ -1164,20 +1164,19 @@ static void LJ_FASTCALL recff_buffer_method_reset(jit_State *J, RecordFFData *rd
   SBufExt *sbx = bufV(&rd->argv[0]);
   SBufExt *sbx = bufV(&rd->argv[0]);
   int iscow = (int)sbufiscow(sbx);
   int iscow = (int)sbufiscow(sbx);
   TRef trl = recff_sbufx_get_L(J, ud);
   TRef trl = recff_sbufx_get_L(J, ud);
-  TRef trcow = emitir(IRT(IR_BAND, IRT_IGC), trl, lj_ir_kint(J, SBUF_FLAG_COW));
-  TRef zero = lj_ir_kint(J, 0);
-  emitir(IRTG(iscow ? IR_NE : IR_EQ, IRT_IGC), trcow, zero);
+  TRef trcow = emitir(IRT(IR_BAND, IRT_IGC), trl, lj_ir_kintpgc(J, SBUF_FLAG_COW));
+  TRef zeropgc = lj_ir_kintpgc(J, 0);
+  emitir(IRTG(iscow ? IR_NE : IR_EQ, IRT_IGC), trcow, zeropgc);
   if (iscow) {
   if (iscow) {
-    trl = emitir(IRT(IR_BXOR, IRT_IGC), trl,
-		 LJ_GC64 ? lj_ir_kint64(J, SBUF_FLAG_COW) :
-			   lj_ir_kint(J, SBUF_FLAG_COW));
-    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, zero);
-    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_E, zero);
-    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_B, zero);
+    TRef zerop = lj_ir_kintp(J, 0);
+    trl = emitir(IRT(IR_BXOR, IRT_IGC), trl, lj_ir_kintpgc(J, SBUF_FLAG_COW));
+    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, zerop);
+    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_E, zerop);
+    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_B, zerop);
     recff_sbufx_set_L(J, ud, trl);
     recff_sbufx_set_L(J, ud, trl);
     emitir(IRT(IR_FSTORE, IRT_PGC),
     emitir(IRT(IR_FSTORE, IRT_PGC),
-	   emitir(IRT(IR_FREF, IRT_PGC), ud, IRFL_SBUF_REF), zero);
-    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, zero);
+	   emitir(IRT(IR_FREF, IRT_PGC), ud, IRFL_SBUF_REF), zeropgc);
+    recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, zerop);
   } else {
   } else {
     TRef trb = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_B);
     TRef trb = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_B);
     recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, trb);
     recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, trb);

+ 2 - 2
libs/LuaJIT/src/lj_ir.h

@@ -76,8 +76,8 @@
   \
   \
   _(ABS,	N , ref, ref) \
   _(ABS,	N , ref, ref) \
   _(LDEXP,	N , ref, ref) \
   _(LDEXP,	N , ref, ref) \
-  _(MIN,	C , ref, ref) \
-  _(MAX,	C , ref, ref) \
+  _(MIN,	N , ref, ref) \
+  _(MAX,	N , ref, ref) \
   _(FPMATH,	N , ref, lit) \
   _(FPMATH,	N , ref, lit) \
   \
   \
   /* Overflow-checking arithmetic ops. */ \
   /* Overflow-checking arithmetic ops. */ \

+ 1 - 1
libs/LuaJIT/src/lj_ircall.h

@@ -63,7 +63,7 @@ typedef struct CCallInfo {
 /* Helpers for conditional function definitions. */
 /* Helpers for conditional function definitions. */
 #define IRCALLCOND_ANY(x)		x
 #define IRCALLCOND_ANY(x)		x
 
 
-#if LJ_TARGET_X86ORX64
+#if LJ_TARGET_X86ORX64 || LJ_TARGET_ARM64
 #define IRCALLCOND_FPMATH(x)		NULL
 #define IRCALLCOND_FPMATH(x)		NULL
 #else
 #else
 #define IRCALLCOND_FPMATH(x)		x
 #define IRCALLCOND_FPMATH(x)		x

+ 6 - 0
libs/LuaJIT/src/lj_iropt.h

@@ -56,6 +56,12 @@ LJ_FUNC TRef lj_ir_ktrace(jit_State *J);
 #define lj_ir_kintp(J, k)	lj_ir_kint(J, (int32_t)(k))
 #define lj_ir_kintp(J, k)	lj_ir_kint(J, (int32_t)(k))
 #endif
 #endif
 
 
+#if LJ_GC64
+#define lj_ir_kintpgc		lj_ir_kintp
+#else
+#define lj_ir_kintpgc		lj_ir_kint
+#endif
+
 static LJ_AINLINE TRef lj_ir_knum(jit_State *J, lua_Number n)
 static LJ_AINLINE TRef lj_ir_knum(jit_State *J, lua_Number n)
 {
 {
   TValue tv;
   TValue tv;

+ 1 - 1
libs/LuaJIT/src/lj_opt_dce.c

@@ -44,12 +44,12 @@ static void dce_propagate(jit_State *J)
     IRIns *ir = IR(ins);
     IRIns *ir = IR(ins);
     if (irt_ismarked(ir->t)) {
     if (irt_ismarked(ir->t)) {
       irt_clearmark(ir->t);
       irt_clearmark(ir->t);
-      pchain[ir->o] = &ir->prev;
     } else if (!ir_sideeff(ir)) {
     } else if (!ir_sideeff(ir)) {
       *pchain[ir->o] = ir->prev;  /* Reroute original instruction chain. */
       *pchain[ir->o] = ir->prev;  /* Reroute original instruction chain. */
       lj_ir_nop(ir);
       lj_ir_nop(ir);
       continue;
       continue;
     }
     }
+    pchain[ir->o] = &ir->prev;
     if (ir->op1 >= REF_FIRST) irt_setmark(IR(ir->op1)->t);
     if (ir->op1 >= REF_FIRST) irt_setmark(IR(ir->op1)->t);
     if (ir->op2 >= REF_FIRST) irt_setmark(IR(ir->op2)->t);
     if (ir->op2 >= REF_FIRST) irt_setmark(IR(ir->op2)->t);
   }
   }

+ 4 - 4
libs/LuaJIT/src/lj_opt_fold.c

@@ -377,10 +377,10 @@ static uint64_t kfold_int64arith(jit_State *J, uint64_t k1, uint64_t k2,
   case IR_BOR: k1 |= k2; break;
   case IR_BOR: k1 |= k2; break;
   case IR_BXOR: k1 ^= k2; break;
   case IR_BXOR: k1 ^= k2; break;
   case IR_BSHL: k1 <<= (k2 & 63); break;
   case IR_BSHL: k1 <<= (k2 & 63); break;
-  case IR_BSHR: k1 = (int32_t)((uint32_t)k1 >> (k2 & 63)); break;
-  case IR_BSAR: k1 >>= (k2 & 63); break;
-  case IR_BROL: k1 = (int32_t)lj_rol((uint32_t)k1, (k2 & 63)); break;
-  case IR_BROR: k1 = (int32_t)lj_ror((uint32_t)k1, (k2 & 63)); break;
+  case IR_BSHR: k1 >>= (k2 & 63); break;
+  case IR_BSAR: k1 = (uint64_t)((int64_t)k1 >> (k2 & 63)); break;
+  case IR_BROL: k1 = lj_rol(k1, (k2 & 63)); break;
+  case IR_BROR: k1 = lj_ror(k1, (k2 & 63)); break;
   default: lj_assertJ(0, "bad IR op %d", op); break;
   default: lj_assertJ(0, "bad IR op %d", op); break;
   }
   }
 #else
 #else

+ 9 - 5
libs/LuaJIT/src/lj_record.c

@@ -1781,7 +1781,7 @@ noconstify:
 	emitir(IRTG(IR_EQ, IRT_PGC),
 	emitir(IRTG(IR_EQ, IRT_PGC),
 	       REF_BASE,
 	       REF_BASE,
 	       emitir(IRT(IR_ADD, IRT_PGC), uref,
 	       emitir(IRT(IR_ADD, IRT_PGC), uref,
-		      lj_ir_kint(J, (slot - 1 - LJ_FR2) * -8)));
+		      lj_ir_kintpgc(J, (slot - 1 - LJ_FR2) * -8)));
 	slot -= (int32_t)J->baseslot;  /* Note: slot number may be negative! */
 	slot -= (int32_t)J->baseslot;  /* Note: slot number may be negative! */
 	if (val == 0) {
 	if (val == 0) {
 	  return getslot(J, slot);
 	  return getslot(J, slot);
@@ -1794,7 +1794,7 @@ noconstify:
     }
     }
     emitir(IRTG(IR_UGT, IRT_PGC),
     emitir(IRTG(IR_UGT, IRT_PGC),
 	   emitir(IRT(IR_SUB, IRT_PGC), uref, REF_BASE),
 	   emitir(IRT(IR_SUB, IRT_PGC), uref, REF_BASE),
-	   lj_ir_kint(J, (J->baseslot + J->maxslot) * 8));
+	   lj_ir_kintpgc(J, (J->baseslot + J->maxslot) * 8));
   } else {
   } else {
     needbarrier = 1;
     needbarrier = 1;
     uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_PGC), fn, uv));
     uref = tref_ref(emitir(IRTG(IR_UREFC, IRT_PGC), fn, uv));
@@ -1972,7 +1972,8 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
 	  emitir(IRTGI(IR_EQ), fr,
 	  emitir(IRTGI(IR_EQ), fr,
 		 lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1)));
 		 lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1)));
 	vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
 	vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
-	vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8*(1+LJ_FR2)));
+	vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase,
+		       lj_ir_kintpgc(J, frofs-8*(1+LJ_FR2)));
 	for (i = 0; i < nload; i++) {
 	for (i = 0; i < nload; i++) {
 	  IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
 	  IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
 	  J->base[dst+i] = lj_record_vload(J, vbase, (MSize)i, t);
 	  J->base[dst+i] = lj_record_vload(J, vbase, (MSize)i, t);
@@ -1991,8 +1992,11 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
       TRef tr = TREF_NIL;
       TRef tr = TREF_NIL;
       ptrdiff_t idx = lj_ffrecord_select_mode(J, tridx, &J->L->base[dst-1]);
       ptrdiff_t idx = lj_ffrecord_select_mode(J, tridx, &J->L->base[dst-1]);
       if (idx < 0) goto nyivarg;
       if (idx < 0) goto nyivarg;
-      if (idx != 0 && !tref_isinteger(tridx))
+      if (idx != 0 && !tref_isinteger(tridx)) {
+	if (tref_isstr(tridx))
+	  tridx = emitir(IRTG(IR_STRTO, IRT_NUM), tridx, 0);
 	tridx = emitir(IRTGI(IR_CONV), tridx, IRCONV_INT_NUM|IRCONV_INDEX);
 	tridx = emitir(IRTGI(IR_CONV), tridx, IRCONV_INT_NUM|IRCONV_INDEX);
+      }
       if (idx != 0 && tref_isk(tridx)) {
       if (idx != 0 && tref_isk(tridx)) {
 	emitir(IRTGI(idx <= nvararg ? IR_GE : IR_LT),
 	emitir(IRTGI(idx <= nvararg ? IR_GE : IR_LT),
 	       fr, lj_ir_kint(J, frofs+8*(int32_t)idx));
 	       fr, lj_ir_kint(J, frofs+8*(int32_t)idx));
@@ -2020,7 +2024,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
 	IRType t;
 	IRType t;
 	TRef aref, vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
 	TRef aref, vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
 	vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase,
 	vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase,
-		       lj_ir_kint(J, frofs-(8<<LJ_FR2)));
+		       lj_ir_kintpgc(J, frofs-(8<<LJ_FR2)));
 	t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]);
 	t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]);
 	aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx);
 	aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx);
 	tr = lj_record_vload(J, aref, 0, t);
 	tr = lj_record_vload(J, aref, 0, t);

+ 23 - 4
libs/LuaJIT/src/lj_state.c

@@ -103,8 +103,17 @@ void lj_state_shrinkstack(lua_State *L, MSize used)
 void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
 void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
 {
 {
   MSize n;
   MSize n;
-  if (L->stacksize > LJ_STACK_MAXEX)  /* Overflow while handling overflow? */
-    lj_err_throw(L, LUA_ERRERR);
+  if (L->stacksize >= LJ_STACK_MAXEX) {
+    /* 4. Throw 'error in error handling' when we are _over_ the limit. */
+    if (L->stacksize > LJ_STACK_MAXEX)
+      lj_err_throw(L, LUA_ERRERR);  /* Does not invoke an error handler. */
+    /* 1. We are _at_ the limit after the last growth. */
+    if (L->status < LUA_ERRRUN) {  /* 2. Throw 'stack overflow'. */
+      L->status = LUA_ERRRUN;  /* Prevent ending here again for pushed msg. */
+      lj_err_msg(L, LJ_ERR_STKOV);  /* May invoke an error handler. */
+    }
+    /* 3. Add space (over the limit) for pushed message and error handler. */
+  }
   n = L->stacksize + need;
   n = L->stacksize + need;
   if (n > LJ_STACK_MAX) {
   if (n > LJ_STACK_MAX) {
     n += 2*LUA_MINSTACK;
     n += 2*LUA_MINSTACK;
@@ -114,8 +123,6 @@ void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
       n = LJ_STACK_MAX;
       n = LJ_STACK_MAX;
   }
   }
   resizestack(L, n);
   resizestack(L, n);
-  if (L->stacksize >= LJ_STACK_MAXEX)
-    lj_err_msg(L, LJ_ERR_STKOV);
 }
 }
 
 
 void LJ_FASTCALL lj_state_growstack1(lua_State *L)
 void LJ_FASTCALL lj_state_growstack1(lua_State *L)
@@ -123,6 +130,18 @@ void LJ_FASTCALL lj_state_growstack1(lua_State *L)
   lj_state_growstack(L, 1);
   lj_state_growstack(L, 1);
 }
 }
 
 
+static TValue *cpgrowstack(lua_State *co, lua_CFunction dummy, void *ud)
+{
+  UNUSED(dummy);
+  lj_state_growstack(co, *(MSize *)ud);
+  return NULL;
+}
+
+int LJ_FASTCALL lj_state_cpgrowstack(lua_State *L, MSize need)
+{
+  return lj_vm_cpcall(L, NULL, &need, cpgrowstack);
+}
+
 /* Allocate basic stack for new state. */
 /* Allocate basic stack for new state. */
 static void stack_init(lua_State *L1, lua_State *L)
 static void stack_init(lua_State *L1, lua_State *L)
 {
 {

+ 1 - 0
libs/LuaJIT/src/lj_state.h

@@ -18,6 +18,7 @@ LJ_FUNC void lj_state_relimitstack(lua_State *L);
 LJ_FUNC void lj_state_shrinkstack(lua_State *L, MSize used);
 LJ_FUNC void lj_state_shrinkstack(lua_State *L, MSize used);
 LJ_FUNCA void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need);
 LJ_FUNCA void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need);
 LJ_FUNC void LJ_FASTCALL lj_state_growstack1(lua_State *L);
 LJ_FUNC void LJ_FASTCALL lj_state_growstack1(lua_State *L);
+LJ_FUNC int LJ_FASTCALL lj_state_cpgrowstack(lua_State *L, MSize need);
 
 
 static LJ_AINLINE void lj_state_checkstack(lua_State *L, MSize need)
 static LJ_AINLINE void lj_state_checkstack(lua_State *L, MSize need)
 {
 {

+ 2 - 0
libs/LuaJIT/src/lj_target_arm64.h

@@ -234,6 +234,8 @@ typedef enum A64Ins {
   A64I_MOVZx = 0xd2800000,
   A64I_MOVZx = 0xd2800000,
   A64I_MOVNw = 0x12800000,
   A64I_MOVNw = 0x12800000,
   A64I_MOVNx = 0x92800000,
   A64I_MOVNx = 0x92800000,
+  A64I_ADR = 0x10000000,
+  A64I_ADRP = 0x90000000,
 
 
   A64I_LDRB = 0x39400000,
   A64I_LDRB = 0x39400000,
   A64I_LDRH = 0x79400000,
   A64I_LDRH = 0x79400000,

+ 16 - 10
libs/LuaJIT/src/lj_trace.c

@@ -613,21 +613,27 @@ static int trace_abort(jit_State *J)
     J->cur.link = 0;
     J->cur.link = 0;
     J->cur.linktype = LJ_TRLINK_NONE;
     J->cur.linktype = LJ_TRLINK_NONE;
     lj_vmevent_send(L, TRACE,
     lj_vmevent_send(L, TRACE,
-      TValue *frame;
+      cTValue *bot = tvref(L->stack)+LJ_FR2;
+      cTValue *frame;
       const BCIns *pc;
       const BCIns *pc;
-      GCfunc *fn;
+      BCPos pos = 0;
       setstrV(L, L->top++, lj_str_newlit(L, "abort"));
       setstrV(L, L->top++, lj_str_newlit(L, "abort"));
       setintV(L->top++, traceno);
       setintV(L->top++, traceno);
       /* Find original Lua function call to generate a better error message. */
       /* Find original Lua function call to generate a better error message. */
-      frame = J->L->base-1;
-      pc = J->pc;
-      while (!isluafunc(frame_func(frame))) {
-	pc = (frame_iscont(frame) ? frame_contpc(frame) : frame_pc(frame)) - 1;
-	frame = frame_prev(frame);
+      for (frame = J->L->base-1, pc = J->pc; ; frame = frame_prev(frame)) {
+	if (isluafunc(frame_func(frame))) {
+	  pos = proto_bcpos(funcproto(frame_func(frame)), pc);
+	  break;
+	} else if (frame_prev(frame) <= bot) {
+	  break;
+	} else if (frame_iscont(frame)) {
+	  pc = frame_contpc(frame) - 1;
+	} else {
+	  pc = frame_pc(frame) - 1;
+	}
       }
       }
-      fn = frame_func(frame);
-      setfuncV(L, L->top++, fn);
-      setintV(L->top++, proto_bcpos(funcproto(fn), pc));
+      setfuncV(L, L->top++, frame_func(frame));
+      setintV(L->top++, pos);
       copyTV(L, L->top++, restorestack(L, errobj));
       copyTV(L, L->top++, restorestack(L, errobj));
       copyTV(L, L->top++, &J->errinfo);
       copyTV(L, L->top++, &J->errinfo);
     );
     );

+ 14 - 1
libs/LuaJIT/src/msvcbuild.bat

@@ -27,12 +27,15 @@
 @set BUILDTYPE=release
 @set BUILDTYPE=release
 @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
 @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
 
 
+@setlocal
+@call :SETHOSTVARS
 %LJCOMPILE% host\minilua.c
 %LJCOMPILE% host\minilua.c
 @if errorlevel 1 goto :BAD
 @if errorlevel 1 goto :BAD
 %LJLINK% /out:minilua.exe minilua.obj
 %LJLINK% /out:minilua.exe minilua.obj
 @if errorlevel 1 goto :BAD
 @if errorlevel 1 goto :BAD
 if exist minilua.exe.manifest^
 if exist minilua.exe.manifest^
   %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe
   %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe
+@endlocal
 
 
 @set DASMFLAGS=-D WIN -D JIT -D FFI -D ENDIAN_LE -D FPU -D P64
 @set DASMFLAGS=-D WIN -D JIT -D FFI -D ENDIAN_LE -D FPU -D P64
 @set LJARCH=x64
 @set LJARCH=x64
@@ -46,6 +49,7 @@ if exist minilua.exe.manifest^
 :NO32
 :NO32
 @if "%VSCMD_ARG_TGT_ARCH%" neq "arm64" goto :X64
 @if "%VSCMD_ARG_TGT_ARCH%" neq "arm64" goto :X64
 @set DASC=vm_arm64.dasc
 @set DASC=vm_arm64.dasc
+@set DASMTARGET=-D LUAJIT_TARGET=LUAJIT_ARCH_ARM64
 @set LJARCH=arm64
 @set LJARCH=arm64
 @goto :DA
 @goto :DA
 :X64
 :X64
@@ -60,12 +64,15 @@ minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h %DASC%
 if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt )
 if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt )
 minilua host\genversion.lua
 minilua host\genversion.lua
 
 
-%LJCOMPILE% /I "." /I %DASMDIR% host\buildvm*.c
+@setlocal
+@call :SETHOSTVARS
+%LJCOMPILE% /I "." /I %DASMDIR% %DASMTARGET% host\buildvm*.c
 @if errorlevel 1 goto :BAD
 @if errorlevel 1 goto :BAD
 %LJLINK% /out:buildvm.exe buildvm*.obj
 %LJLINK% /out:buildvm.exe buildvm*.obj
 @if errorlevel 1 goto :BAD
 @if errorlevel 1 goto :BAD
 if exist buildvm.exe.manifest^
 if exist buildvm.exe.manifest^
   %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe
   %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe
+@endlocal
 
 
 buildvm -m peobj -o lj_vm.obj
 buildvm -m peobj -o lj_vm.obj
 @if errorlevel 1 goto :BAD
 @if errorlevel 1 goto :BAD
@@ -124,6 +131,12 @@ if exist luajit.exe.manifest^
 @echo.
 @echo.
 @echo === Successfully built LuaJIT for Windows/%LJARCH% ===
 @echo === Successfully built LuaJIT for Windows/%LJARCH% ===
 
 
+@goto :END
+:SETHOSTVARS
+@if "%VSCMD_ARG_HOST_ARCH%_%VSCMD_ARG_TGT_ARCH%" equ "x64_arm64" (
+  call "%VSINSTALLDIR%Common7\Tools\VsDevCmd.bat" -arch=%VSCMD_ARG_HOST_ARCH% -no_logo
+  echo on
+)
 @goto :END
 @goto :END
 :BAD
 :BAD
 @echo.
 @echo.

+ 115 - 92
libs/LuaJIT/src/vm_arm64.dasc

@@ -113,13 +113,37 @@
 |
 |
 |.define TMPDofs,	#24
 |.define TMPDofs,	#24
 |
 |
+|.if WIN
+|// Windows unwind data is suited to r1 stored first.
+|.macro stp_unwind, r1, r2, where
+|  stp r1, r2, where
+|.endmacro
+|.macro ldp_unwind, r1, r2, where
+|  ldp r1, r2, where
+|.endmacro
+|.macro ldp_unwind, r1, r2, where, post_index
+|  ldp r1, r2, where, post_index
+|.endmacro
+|.else
+|// Otherwise store r2 first for compact unwind info (OSX).
+|.macro stp_unwind, r1, r2, where
+|  stp r2, r1, where
+|.endmacro
+|.macro ldp_unwind, r1, r2, where
+|  ldp r2, r1, where
+|.endmacro
+|.macro ldp_unwind, r1, r2, where, post_index
+|  ldp r2, r1, where, post_index
+|.endmacro
+|.endif
+|
 |.macro save_, gpr1, gpr2, fpr1, fpr2
 |.macro save_, gpr1, gpr2, fpr1, fpr2
-|  stp d..fpr2, d..fpr1, [sp, # SAVE_FPR_+(14-fpr1)*8]
-|  stp x..gpr2, x..gpr1, [sp, # SAVE_GPR_+(27-gpr1)*8]
+|  stp_unwind d..fpr1, d..fpr2, [sp, # SAVE_FPR_+(14-fpr1)*8]
+|  stp_unwind x..gpr1, x..gpr2, [sp, # SAVE_GPR_+(27-gpr1)*8]
 |.endmacro
 |.endmacro
 |.macro rest_, gpr1, gpr2, fpr1, fpr2
 |.macro rest_, gpr1, gpr2, fpr1, fpr2
-|  ldp d..fpr2, d..fpr1, [sp, # SAVE_FPR_+(14-fpr1)*8]
-|  ldp x..gpr2, x..gpr1, [sp, # SAVE_GPR_+(27-gpr1)*8]
+|  ldp_unwind d..fpr1, d..fpr2, [sp, # SAVE_FPR_+(14-fpr1)*8]
+|  ldp_unwind x..gpr1, x..gpr2, [sp, # SAVE_GPR_+(27-gpr1)*8]
 |.endmacro
 |.endmacro
 |
 |
 |.macro saveregs
 |.macro saveregs
@@ -127,14 +151,14 @@
 |  sub sp, sp, # CFRAME_SPACE
 |  sub sp, sp, # CFRAME_SPACE
 |  stp fp, lr, [sp, # SAVE_FP_LR_]
 |  stp fp, lr, [sp, # SAVE_FP_LR_]
 |  add fp, sp, # SAVE_FP_LR_
 |  add fp, sp, # SAVE_FP_LR_
-|  stp x20, x19, [sp, # SAVE_GPR_+(27-19)*8]
+|  stp_unwind x19, x20, [sp, # SAVE_GPR_+(27-19)*8]
 |  save_ 21, 22, 8, 9
 |  save_ 21, 22, 8, 9
 |  save_ 23, 24, 10, 11
 |  save_ 23, 24, 10, 11
 |  save_ 25, 26, 12, 13
 |  save_ 25, 26, 12, 13
 |  save_ 27, 28, 14, 15
 |  save_ 27, 28, 14, 15
 |.endmacro
 |.endmacro
 |.macro restoreregs
 |.macro restoreregs
-|  ldp x20, x19, [sp, # SAVE_GPR_+(27-19)*8]
+|  ldp_unwind x19, x20, [sp, # SAVE_GPR_+(27-19)*8]
 |  rest_ 21, 22, 8, 9
 |  rest_ 21, 22, 8, 9
 |  rest_ 23, 24, 10, 11
 |  rest_ 23, 24, 10, 11
 |  rest_ 25, 26, 12, 13
 |  rest_ 25, 26, 12, 13
@@ -267,8 +291,17 @@
 |  blo target
 |  blo target
 |.endmacro
 |.endmacro
 |
 |
+|.macro init_constants
+|  movn TISNIL, #0
+|  movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
+|  movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
+|.endmacro
+|
 |.macro mov_false, reg; movn reg, #0x8000, lsl #32; .endmacro
 |.macro mov_false, reg; movn reg, #0x8000, lsl #32; .endmacro
 |.macro mov_true, reg; movn reg, #0x0001, lsl #48; .endmacro
 |.macro mov_true, reg; movn reg, #0x0001, lsl #48; .endmacro
+|.macro mov_nil, reg; mov reg, TISNIL; .endmacro
+|.macro cmp_nil, reg; cmp reg, TISNIL; .endmacro
+|.macro add_TISNUM, dst, src; add dst, src, TISNUM; .endmacro
 |
 |
 #define GL_J(field)	(GG_G2J + (int)offsetof(jit_State, field))
 #define GL_J(field)	(GG_G2J + (int)offsetof(jit_State, field))
 |
 |
@@ -406,26 +439,26 @@ static void build_subroutines(BuildCtx *ctx)
   |
   |
   |->vm_unwind_c:			// Unwind C stack, return from vm_pcall.
   |->vm_unwind_c:			// Unwind C stack, return from vm_pcall.
   |  // (void *cframe, int errcode)
   |  // (void *cframe, int errcode)
+  |  add fp, CARG1, # SAVE_FP_LR_
   |  mov sp, CARG1
   |  mov sp, CARG1
   |  mov CRET1, CARG2
   |  mov CRET1, CARG2
-  |->vm_unwind_c_eh:			// Landing pad for external unwinder.
   |  ldr L, SAVE_L
   |  ldr L, SAVE_L
-  |   mv_vmstate TMP0w, C
   |  ldr GL, L->glref
   |  ldr GL, L->glref
+  |->vm_unwind_c_eh:			// Landing pad for external unwinder.
+  |   mv_vmstate TMP0w, C
   |   st_vmstate TMP0w
   |   st_vmstate TMP0w
   |  b ->vm_leave_unw
   |  b ->vm_leave_unw
   |
   |
   |->vm_unwind_ff:			// Unwind C stack, return from ff pcall.
   |->vm_unwind_ff:			// Unwind C stack, return from ff pcall.
   |  // (void *cframe)
   |  // (void *cframe)
-  |  and sp, CARG1, #CFRAME_RAWMASK
-  |->vm_unwind_ff_eh:			// Landing pad for external unwinder.
+  |  add fp, CARG1, # SAVE_FP_LR_
+  |  mov sp, CARG1
   |  ldr L, SAVE_L
   |  ldr L, SAVE_L
-  |    movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
-  |    movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
-  |    movn TISNIL, #0
+  |    init_constants
+  |   ldr GL, L->glref			// Setup pointer to global state.
+  |->vm_unwind_ff_eh:			// Landing pad for external unwinder.
   |    mov RC, #16			// 2 results: false + error message.
   |    mov RC, #16			// 2 results: false + error message.
   |  ldr BASE, L->base
   |  ldr BASE, L->base
-  |   ldr GL, L->glref			// Setup pointer to global state.
   |    mov_false TMP0
   |    mov_false TMP0
   |  sub RA, BASE, #8			// Results start at BASE-8.
   |  sub RA, BASE, #8			// Results start at BASE-8.
   |  ldr PC, [BASE, FRAME_PC]		// Fetch PC of previous frame.
   |  ldr PC, [BASE, FRAME_PC]		// Fetch PC of previous frame.
@@ -486,11 +519,9 @@ static void build_subroutines(BuildCtx *ctx)
   |  str L, GL->cur_L
   |  str L, GL->cur_L
   |  mov RA, BASE
   |  mov RA, BASE
   |   ldp BASE, CARG1, L->base
   |   ldp BASE, CARG1, L->base
-  |    movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
-  |    movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
+  |    init_constants
   |  ldr PC, [BASE, FRAME_PC]
   |  ldr PC, [BASE, FRAME_PC]
   |     strb wzr, L->status
   |     strb wzr, L->status
-  |    movn TISNIL, #0
   |   sub RC, CARG1, BASE
   |   sub RC, CARG1, BASE
   |  ands CARG1, PC, #FRAME_TYPE
   |  ands CARG1, PC, #FRAME_TYPE
   |   add RC, RC, #8
   |   add RC, RC, #8
@@ -526,10 +557,8 @@ static void build_subroutines(BuildCtx *ctx)
   |3:  // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
   |3:  // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
   |  str L, GL->cur_L
   |  str L, GL->cur_L
   |  ldp RB, CARG1, L->base		// RB = old base (for vmeta_call).
   |  ldp RB, CARG1, L->base		// RB = old base (for vmeta_call).
-  |    movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
-  |    movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
   |  add PC, PC, BASE
   |  add PC, PC, BASE
-  |    movn TISNIL, #0
+  |    init_constants
   |  sub PC, PC, RB			// PC = frame delta + frame type
   |  sub PC, PC, RB			// PC = frame delta + frame type
   |   sub NARGS8:RC, CARG1, BASE
   |   sub NARGS8:RC, CARG1, BASE
   |    st_vmstate ST_INTERP
   |    st_vmstate ST_INTERP
@@ -638,7 +667,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  b >1
   |  b >1
   |
   |
   |->vmeta_tgetb:			// RB = table, RC = index
   |->vmeta_tgetb:			// RB = table, RC = index
-  |  add RC, RC, TISNUM
+  |  add_TISNUM RC, RC
   |   add CARG2, BASE, RB, lsl #3
   |   add CARG2, BASE, RB, lsl #3
   |   add CARG3, sp, TMPDofs
   |   add CARG3, sp, TMPDofs
   |  str RC, TMPD
   |  str RC, TMPD
@@ -673,7 +702,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  sxtw CARG2, TMP1w
   |  sxtw CARG2, TMP1w
   |  bl extern lj_tab_getinth		// (GCtab *t, int32_t key)
   |  bl extern lj_tab_getinth		// (GCtab *t, int32_t key)
   |  // Returns cTValue * or NULL.
   |  // Returns cTValue * or NULL.
-  |  mov TMP0, TISNIL
+  |  mov_nil TMP0
   |  cbz CRET1, ->BC_TGETR_Z
   |  cbz CRET1, ->BC_TGETR_Z
   |  ldr TMP0, [CRET1]
   |  ldr TMP0, [CRET1]
   |  b ->BC_TGETR_Z
   |  b ->BC_TGETR_Z
@@ -696,7 +725,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  b >1
   |  b >1
   |
   |
   |->vmeta_tsetb:			// RB = table, RC = index
   |->vmeta_tsetb:			// RB = table, RC = index
-  |  add RC, RC, TISNUM
+  |  add_TISNUM RC, RC
   |   add CARG2, BASE, RB, lsl #3
   |   add CARG2, BASE, RB, lsl #3
   |   add CARG3, sp, TMPDofs
   |   add CARG3, sp, TMPDofs
   |  str RC, TMPD
   |  str RC, TMPD
@@ -1010,7 +1039,7 @@ static void build_subroutines(BuildCtx *ctx)
   |1:  // Field metatable must be at same offset for GCtab and GCudata!
   |1:  // Field metatable must be at same offset for GCtab and GCudata!
   |  ldr TAB:RB, TAB:CARG1->metatable
   |  ldr TAB:RB, TAB:CARG1->metatable
   |2:
   |2:
-  |   mov CARG1, TISNIL
+  |   mov_nil CARG1
   |   ldr STR:RC, GL->gcroot[GCROOT_MMNAME+MM_metatable]
   |   ldr STR:RC, GL->gcroot[GCROOT_MMNAME+MM_metatable]
   |  cbz TAB:RB, ->fff_restv
   |  cbz TAB:RB, ->fff_restv
   |  ldr TMP1w, TAB:RB->hmask
   |  ldr TMP1w, TAB:RB->hmask
@@ -1032,7 +1061,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  movk CARG1, #(LJ_TTAB>>1)&0xffff, lsl #48
   |  movk CARG1, #(LJ_TTAB>>1)&0xffff, lsl #48
   |  b ->fff_restv
   |  b ->fff_restv
   |5:
   |5:
-  |  cmp TMP0, TISNIL
+  |  cmp_nil TMP0
   |  bne ->fff_restv
   |  bne ->fff_restv
   |  b <4
   |  b <4
   |
   |
@@ -1132,8 +1161,8 @@ static void build_subroutines(BuildCtx *ctx)
   |  cbnz TAB:CARG2, ->fff_fallback
   |  cbnz TAB:CARG2, ->fff_fallback
 #endif
 #endif
   |  mov RC, #(3+1)*8
   |  mov RC, #(3+1)*8
-  |  stp CARG1, TISNIL, [BASE, #-8]
-  |   str CFUNC:CARG4, [BASE, #-16]
+  |  stp CFUNC:CARG4, CARG1, [BASE, #-16]
+  |   str TISNIL, [BASE]
   |  b ->fff_res
   |  b ->fff_res
   |
   |
   |.ffunc_2 ipairs_aux
   |.ffunc_2 ipairs_aux
@@ -1145,14 +1174,14 @@ static void build_subroutines(BuildCtx *ctx)
   |  add CARG2w, CARG2w, #1
   |  add CARG2w, CARG2w, #1
   |  cmp CARG2w, TMP1w
   |  cmp CARG2w, TMP1w
   |    ldr PC, [BASE, FRAME_PC]
   |    ldr PC, [BASE, FRAME_PC]
-  |     add TMP2, CARG2, TISNUM
+  |     add_TISNUM TMP2, CARG2
   |   mov RC, #(0+1)*8
   |   mov RC, #(0+1)*8
   |     str TMP2, [BASE, #-16]
   |     str TMP2, [BASE, #-16]
   |  bhs >2				// Not in array part?
   |  bhs >2				// Not in array part?
   |  ldr TMP0, [CARG3, CARG2, lsl #3]
   |  ldr TMP0, [CARG3, CARG2, lsl #3]
   |1:
   |1:
   |   mov TMP1, #(2+1)*8
   |   mov TMP1, #(2+1)*8
-  |   cmp TMP0, TISNIL
+  |   cmp_nil TMP0
   |  str TMP0, [BASE, #-8]
   |  str TMP0, [BASE, #-8]
   |   csel RC, RC, TMP1, eq
   |   csel RC, RC, TMP1, eq
   |  b ->fff_res
   |  b ->fff_res
@@ -1175,8 +1204,8 @@ static void build_subroutines(BuildCtx *ctx)
   |  cbnz TAB:CARG2, ->fff_fallback
   |  cbnz TAB:CARG2, ->fff_fallback
 #endif
 #endif
   |  mov RC, #(3+1)*8
   |  mov RC, #(3+1)*8
-  |  stp CARG1, TISNUM, [BASE, #-8]
-  |   str CFUNC:CARG4, [BASE, #-16]
+  |  stp CFUNC:CARG4, CARG1, [BASE, #-16]
+  |   str TISNUM, [BASE]
   |  b ->fff_res
   |  b ->fff_res
   |
   |
   |//-- Base library: catch errors ----------------------------------------
   |//-- Base library: catch errors ----------------------------------------
@@ -1366,7 +1395,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  eor CARG2w, CARG1w, CARG1w, asr #31
   |  eor CARG2w, CARG1w, CARG1w, asr #31
   |   movz CARG3, #0x41e0, lsl #48	// 2^31.
   |   movz CARG3, #0x41e0, lsl #48	// 2^31.
   |  subs CARG1w, CARG2w, CARG1w, asr #31
   |  subs CARG1w, CARG2w, CARG1w, asr #31
-  |   add CARG1, CARG1, TISNUM
+  |   add_TISNUM CARG1, CARG1
   |  csel CARG1, CARG1, CARG3, pl
   |  csel CARG1, CARG1, CARG3, pl
   |  // Fallthrough.
   |  // Fallthrough.
   |
   |
@@ -1457,7 +1486,7 @@ static void build_subroutines(BuildCtx *ctx)
   |    ldr PC, [BASE, FRAME_PC]
   |    ldr PC, [BASE, FRAME_PC]
   |  str d0, [BASE, #-16]
   |  str d0, [BASE, #-16]
   |    mov RC, #(2+1)*8
   |    mov RC, #(2+1)*8
-  |   add CARG2, CARG2, TISNUM
+  |   add_TISNUM CARG2, CARG2
   |   str CARG2, [BASE, #-8]
   |   str CARG2, [BASE, #-8]
   |  b ->fff_res
   |  b ->fff_res
   |
   |
@@ -1523,7 +1552,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  bne ->fff_fallback
   |  bne ->fff_fallback
   |  ldrb TMP0w, STR:CARG1[1]		// Access is always ok (NUL at end).
   |  ldrb TMP0w, STR:CARG1[1]		// Access is always ok (NUL at end).
   |   ldr CARG3w, STR:CARG1->len
   |   ldr CARG3w, STR:CARG1->len
-  |  add TMP0, TMP0, TISNUM
+  |  add_TISNUM TMP0, TMP0
   |  str TMP0, [BASE, #-16]
   |  str TMP0, [BASE, #-16]
   |  mov RC, #(0+1)*8
   |  mov RC, #(0+1)*8
   |   cbz CARG3, ->fff_res
   |   cbz CARG3, ->fff_res
@@ -1669,17 +1698,17 @@ static void build_subroutines(BuildCtx *ctx)
   |.ffunc_bit tobit
   |.ffunc_bit tobit
   |  mov TMP0w, CARG1w
   |  mov TMP0w, CARG1w
   |9:  // Label reused by .ffunc_bit_op users.
   |9:  // Label reused by .ffunc_bit_op users.
-  |  add CARG1, TMP0, TISNUM
+  |  add_TISNUM CARG1, TMP0
   |  b ->fff_restv
   |  b ->fff_restv
   |
   |
   |.ffunc_bit bswap
   |.ffunc_bit bswap
   |  rev TMP0w, CARG1w
   |  rev TMP0w, CARG1w
-  |  add CARG1, TMP0, TISNUM
+  |  add_TISNUM CARG1, TMP0
   |  b ->fff_restv
   |  b ->fff_restv
   |
   |
   |.ffunc_bit bnot
   |.ffunc_bit bnot
   |  mvn TMP0w, CARG1w
   |  mvn TMP0w, CARG1w
-  |  add CARG1, TMP0, TISNUM
+  |  add_TISNUM CARG1, TMP0
   |  b ->fff_restv
   |  b ->fff_restv
   |
   |
   |.macro .ffunc_bit_sh, name, ins, shmod
   |.macro .ffunc_bit_sh, name, ins, shmod
@@ -1700,7 +1729,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checkint CARG1, ->vm_tobit_fb
   |  checkint CARG1, ->vm_tobit_fb
   |2:
   |2:
   |  ins TMP0w, CARG1w, TMP1w
   |  ins TMP0w, CARG1w, TMP1w
-  |  add CARG1, TMP0, TISNUM
+  |  add_TISNUM CARG1, TMP0
   |  b ->fff_restv
   |  b ->fff_restv
   |.endmacro
   |.endmacro
   |
   |
@@ -1889,8 +1918,7 @@ static void build_subroutines(BuildCtx *ctx)
   |    and CARG3, CARG3, #LJ_GCVMASK
   |    and CARG3, CARG3, #LJ_GCVMASK
   |   beq >2
   |   beq >2
   |1:  // Move results down.
   |1:  // Move results down.
-  |  ldr CARG1, [RA]
-  |    add RA, RA, #8
+  |  ldr CARG1, [RA], #8
   |   subs RB, RB, #8
   |   subs RB, RB, #8
   |  str CARG1, [BASE, RC, lsl #3]
   |  str CARG1, [BASE, RC, lsl #3]
   |    add RC, RC, #1
   |    add RC, RC, #1
@@ -2005,13 +2033,11 @@ static void build_subroutines(BuildCtx *ctx)
   |.if JIT
   |.if JIT
   |  ldr L, SAVE_L
   |  ldr L, SAVE_L
   |1:
   |1:
+  |   init_constants
   |  cmn CARG1w, #LUA_ERRERR
   |  cmn CARG1w, #LUA_ERRERR
   |  bhs >9				// Check for error from exit.
   |  bhs >9				// Check for error from exit.
-  |   lsl RC, CARG1, #3
   |  ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
   |  ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
-  |    movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
-  |    movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
-  |    movn TISNIL, #0
+  |   lsl RC, CARG1, #3
   |  and LFUNC:CARG2, CARG2, #LJ_GCVMASK
   |  and LFUNC:CARG2, CARG2, #LJ_GCVMASK
   |   str RCw, SAVE_MULTRES
   |   str RCw, SAVE_MULTRES
   |   str BASE, L->base
   |   str BASE, L->base
@@ -2162,7 +2188,7 @@ static void build_subroutines(BuildCtx *ctx)
   |//-----------------------------------------------------------------------
   |//-----------------------------------------------------------------------
   |
   |
   |// Handler for callback functions.
   |// Handler for callback functions.
-  |// Saveregs already performed. Callback slot number in [sp], g in r12.
+  |// Saveregs already performed. Callback slot number in w9, g in x10.
   |->vm_ffi_callback:
   |->vm_ffi_callback:
   |.if FFI
   |.if FFI
   |.type CTSTATE, CTState, PC
   |.type CTSTATE, CTState, PC
@@ -2186,9 +2212,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  bl extern lj_ccallback_enter	// (CTState *cts, void *cf)
   |  bl extern lj_ccallback_enter	// (CTState *cts, void *cf)
   |  // Returns lua_State *.
   |  // Returns lua_State *.
   |  ldp BASE, RC, L:CRET1->base
   |  ldp BASE, RC, L:CRET1->base
-  |   movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
-  |   movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
-  |   movn TISNIL, #0
+  |   init_constants
   |   mov L, CRET1
   |   mov L, CRET1
   |  ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
   |  ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
   |  sub RC, RC, BASE
   |  sub RC, RC, BASE
@@ -2215,7 +2239,7 @@ static void build_subroutines(BuildCtx *ctx)
   |.if FFI
   |.if FFI
   |  .type CCSTATE, CCallState, x19
   |  .type CCSTATE, CCallState, x19
   |  sp_auth
   |  sp_auth
-  |  stp x20, CCSTATE, [sp, #-32]!
+  |  stp_unwind CCSTATE, x20, [sp, #-32]!
   |  stp fp, lr, [sp, #16]
   |  stp fp, lr, [sp, #16]
   |  add fp, sp, #16
   |  add fp, sp, #16
   |  mov CCSTATE, x0
   |  mov CCSTATE, x0
@@ -2247,7 +2271,7 @@ static void build_subroutines(BuildCtx *ctx)
   |   stp d0, d1, CCSTATE->fpr[0]
   |   stp d0, d1, CCSTATE->fpr[0]
   |   stp d2, d3, CCSTATE->fpr[2]
   |   stp d2, d3, CCSTATE->fpr[2]
   |  ldp fp, lr, [sp, #16]
   |  ldp fp, lr, [sp, #16]
-  |  ldp x20, CCSTATE, [sp], #32
+  |  ldp_unwind CCSTATE, x20, [sp], #32
   |  ret_auth
   |  ret_auth
   |.endif
   |.endif
   |// Note: vm_ffi_call must be the last function in this object file!
   |// Note: vm_ffi_call must be the last function in this object file!
@@ -2567,7 +2591,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  bne >5
     |  bne >5
     |  negs TMP0w, TMP0w
     |  negs TMP0w, TMP0w
     |   movz CARG3, #0x41e0, lsl #48	// 2^31.
     |   movz CARG3, #0x41e0, lsl #48	// 2^31.
-    |   add TMP0, TMP0, TISNUM
+    |   add_TISNUM TMP0, TMP0
     |  csel TMP0, TMP0, CARG3, vc
     |  csel TMP0, TMP0, CARG3, vc
     |5:
     |5:
     |  str TMP0, [BASE, RA, lsl #3]
     |  str TMP0, [BASE, RA, lsl #3]
@@ -2582,7 +2606,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  bne >2
     |  bne >2
     |  ldr CARG1w, STR:CARG1->len
     |  ldr CARG1w, STR:CARG1->len
     |1:
     |1:
-    |  add CARG1, CARG1, TISNUM
+    |  add_TISNUM CARG1, CARG1
     |  str CARG1, [BASE, RA, lsl #3]
     |  str CARG1, [BASE, RA, lsl #3]
     |  ins_next
     |  ins_next
     |
     |
@@ -2690,7 +2714,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  intins CARG1w, CARG1w, CARG2w
     |  intins CARG1w, CARG1w, CARG2w
     |  ins_arithfallback bvs
     |  ins_arithfallback bvs
     |.endif
     |.endif
-    |  add CARG1, CARG1, TISNUM
+    |  add_TISNUM CARG1, CARG1
     |  str CARG1, [BASE, RA, lsl #3]
     |  str CARG1, [BASE, RA, lsl #3]
     |4:
     |4:
     |  ins_next
     |  ins_next
@@ -2783,7 +2807,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
   case BC_KSHORT:
   case BC_KSHORT:
     |  // RA = dst, RC = int16_literal
     |  // RA = dst, RC = int16_literal
     |  sxth RCw, RCw
     |  sxth RCw, RCw
-    |  add TMP0, RC, TISNUM
+    |  add_TISNUM TMP0, RC
     |  str TMP0, [BASE, RA, lsl #3]
     |  str TMP0, [BASE, RA, lsl #3]
     |  ins_next
     |  ins_next
     break;
     break;
@@ -3006,7 +3030,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   cmp TMP1w, CARG1w		// In array part?
     |   cmp TMP1w, CARG1w		// In array part?
     |   bhs ->vmeta_tgetv
     |   bhs ->vmeta_tgetv
     |  ldr TMP0, [CARG3]
     |  ldr TMP0, [CARG3]
-    |  cmp TMP0, TISNIL
+    |  cmp_nil TMP0
     |  beq >5
     |  beq >5
     |1:
     |1:
     |  str TMP0, [BASE, RA, lsl #3]
     |  str TMP0, [BASE, RA, lsl #3]
@@ -3049,7 +3073,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   ldr NODE:CARG3, NODE:CARG3->next
     |   ldr NODE:CARG3, NODE:CARG3->next
     |  cmp CARG1, CARG4
     |  cmp CARG1, CARG4
     |  bne >4
     |  bne >4
-    |  cmp TMP0, TISNIL
+    |  cmp_nil TMP0
     |  beq >5
     |  beq >5
     |3:
     |3:
     |  str TMP0, [BASE, RA, lsl #3]
     |  str TMP0, [BASE, RA, lsl #3]
@@ -3058,7 +3082,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |4:  // Follow hash chain.
     |4:  // Follow hash chain.
     |  cbnz NODE:CARG3, <1
     |  cbnz NODE:CARG3, <1
     |  // End of hash chain: key not found, nil result.
     |  // End of hash chain: key not found, nil result.
-    |   mov TMP0, TISNIL
+    |   mov_nil TMP0
     |
     |
     |5:  // Check for __index if table value is nil.
     |5:  // Check for __index if table value is nil.
     |  ldr TAB:CARG1, TAB:CARG2->metatable
     |  ldr TAB:CARG1, TAB:CARG2->metatable
@@ -3079,7 +3103,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   cmp RCw, CARG1w			// In array part?
     |   cmp RCw, CARG1w			// In array part?
     |   bhs ->vmeta_tgetb
     |   bhs ->vmeta_tgetb
     |  ldr TMP0, [CARG3]
     |  ldr TMP0, [CARG3]
-    |  cmp TMP0, TISNIL
+    |  cmp_nil TMP0
     |  beq >5
     |  beq >5
     |1:
     |1:
     |  str TMP0, [BASE, RA, lsl #3]
     |  str TMP0, [BASE, RA, lsl #3]
@@ -3126,7 +3150,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  ldr TMP1, [CARG3]
     |  ldr TMP1, [CARG3]
     |   ldr TMP0, [BASE, RA, lsl #3]
     |   ldr TMP0, [BASE, RA, lsl #3]
     |    ldrb TMP2w, TAB:CARG2->marked
     |    ldrb TMP2w, TAB:CARG2->marked
-    |  cmp TMP1, TISNIL			// Previous value is nil?
+    |  cmp_nil TMP1			// Previous value is nil?
     |  beq >5
     |  beq >5
     |1:
     |1:
     |   str TMP0, [CARG3]
     |   str TMP0, [CARG3]
@@ -3178,7 +3202,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  cmp CARG1, CARG4
     |  cmp CARG1, CARG4
     |  bne >5
     |  bne >5
     |   ldr TMP0, [BASE, RA, lsl #3]
     |   ldr TMP0, [BASE, RA, lsl #3]
-    |  cmp TMP1, TISNIL			// Previous value is nil?
+    |  cmp_nil TMP1			// Previous value is nil?
     |  beq >4
     |  beq >4
     |2:
     |2:
     |   str TMP0, NODE:CARG3->val
     |   str TMP0, NODE:CARG3->val
@@ -3237,7 +3261,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  ldr TMP1, [CARG3]
     |  ldr TMP1, [CARG3]
     |   ldr TMP0, [BASE, RA, lsl #3]
     |   ldr TMP0, [BASE, RA, lsl #3]
     |    ldrb TMP2w, TAB:CARG2->marked
     |    ldrb TMP2w, TAB:CARG2->marked
-    |  cmp TMP1, TISNIL			// Previous value is nil?
+    |  cmp_nil TMP1			// Previous value is nil?
     |  beq >5
     |  beq >5
     |1:
     |1:
     |   str TMP0, [CARG3]
     |   str TMP0, [CARG3]
@@ -3336,9 +3360,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |->BC_CALL_Z:
     |->BC_CALL_Z:
     |  mov RB, BASE			// Save old BASE for vmeta_call.
     |  mov RB, BASE			// Save old BASE for vmeta_call.
     |  add BASE, BASE, RA, lsl #3
     |  add BASE, BASE, RA, lsl #3
-    |  ldr CARG3, [BASE]
+    |  ldr CARG3, [BASE], #16
     |   sub NARGS8:RC, NARGS8:RC, #8
     |   sub NARGS8:RC, NARGS8:RC, #8
-    |   add BASE, BASE, #16
     |  checkfunc CARG3, ->vmeta_call
     |  checkfunc CARG3, ->vmeta_call
     |  ins_call
     |  ins_call
     break;
     break;
@@ -3354,9 +3377,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  // RA = base, (RB = 0,) RC = (nargs+1)*8
     |  // RA = base, (RB = 0,) RC = (nargs+1)*8
     |->BC_CALLT1_Z:
     |->BC_CALLT1_Z:
     |  add RA, BASE, RA, lsl #3
     |  add RA, BASE, RA, lsl #3
-    |  ldr TMP1, [RA]
+    |  ldr TMP1, [RA], #16
     |   sub NARGS8:RC, NARGS8:RC, #8
     |   sub NARGS8:RC, NARGS8:RC, #8
-    |   add RA, RA, #16
     |  checktp CARG3, TMP1, LJ_TFUNC, ->vmeta_callt
     |  checktp CARG3, TMP1, LJ_TFUNC, ->vmeta_callt
     |  ldr PC, [BASE, FRAME_PC]
     |  ldr PC, [BASE, FRAME_PC]
     |->BC_CALLT2_Z:
     |->BC_CALLT2_Z:
@@ -3436,10 +3458,10 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   add CARG3, CARG2, CARG1, lsl #3
     |   add CARG3, CARG2, CARG1, lsl #3
     |  bhs >5				// Index points after array part?
     |  bhs >5				// Index points after array part?
     |   ldr TMP0, [CARG3]
     |   ldr TMP0, [CARG3]
-    |   cmp TMP0, TISNIL
+    |   cmp_nil TMP0
     |   cinc CARG1, CARG1, eq		// Skip holes in array part.
     |   cinc CARG1, CARG1, eq		// Skip holes in array part.
     |   beq <1
     |   beq <1
-    |   add CARG1, CARG1, TISNUM
+    |   add_TISNUM CARG1, CARG1
     |   stp CARG1, TMP0, [RA]
     |   stp CARG1, TMP0, [RA]
     |    add CARG1, CARG1, #1
     |    add CARG1, CARG1, #1
     |3:
     |3:
@@ -3457,7 +3479,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   add NODE:CARG3, NODE:RB, CARG1, lsl #3  // node = tab->node + idx*3*8
     |   add NODE:CARG3, NODE:RB, CARG1, lsl #3  // node = tab->node + idx*3*8
     |  bhi <4
     |  bhi <4
     |  ldp TMP0, CARG1, NODE:CARG3->val
     |  ldp TMP0, CARG1, NODE:CARG3->val
-    |  cmp TMP0, TISNIL
+    |  cmp_nil TMP0
     |   add RC, RC, #1
     |   add RC, RC, #1
     |  beq <6				// Skip holes in hash part.
     |  beq <6				// Skip holes in hash part.
     |  stp CARG1, TMP0, [RA]
     |  stp CARG1, TMP0, [RA]
@@ -3475,8 +3497,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  checkfunc CFUNC:CARG1, >5
     |  checkfunc CFUNC:CARG1, >5
     |   asr TMP0, TAB:CARG3, #47
     |   asr TMP0, TAB:CARG3, #47
     |  ldrb TMP1w, CFUNC:CARG1->ffid
     |  ldrb TMP1w, CFUNC:CARG1->ffid
-    |   cmn TMP0, #-LJ_TTAB
-    |   ccmp CARG4, TISNIL, #0, eq
+    |   cmp_nil CARG4
+    |   ccmn TMP0, #-LJ_TTAB, #0, eq
     |  ccmp TMP1w, #FF_next_N, #0, eq
     |  ccmp TMP1w, #FF_next_N, #0, eq
     |  bne >5
     |  bne >5
     |  mov TMP0w, #0xfffe7fff		// LJ_KEYINDEX
     |  mov TMP0w, #0xfffe7fff		// LJ_KEYINDEX
@@ -3516,51 +3538,51 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   and RC, RC, #255
     |   and RC, RC, #255
     |  // RA = base, RB = (nresults+1), RC = numparams
     |  // RA = base, RB = (nresults+1), RC = numparams
     |  ldr TMP1, [BASE, FRAME_PC]
     |  ldr TMP1, [BASE, FRAME_PC]
-    |  add RC, BASE, RC, lsl #3
-    |   add RA, BASE, RA, lsl #3
-    |  add RC, RC, #FRAME_VARG
-    |   add TMP2, RA, RB, lsl #3
-    |  sub RC, RC, TMP1			// RC = vbase
-    |  // Note: RC may now be even _above_ BASE if nargs was < numparams.
+    |  add TMP0, BASE, RC, lsl #3
+    |   add RC, BASE, RA, lsl #3	// RC = destination
+    |  add TMP0, TMP0, #FRAME_VARG
+    |   add TMP2, RC, RB, lsl #3
+    |  sub RA, TMP0, TMP1		// RA = vbase
+    |  // Note: RA may now be even _above_ BASE if nargs was < numparams.
     |   sub TMP3, BASE, #16		// TMP3 = vtop
     |   sub TMP3, BASE, #16		// TMP3 = vtop
     |  cbz RB, >5
     |  cbz RB, >5
     |   sub TMP2, TMP2, #16
     |   sub TMP2, TMP2, #16
     |1:  // Copy vararg slots to destination slots.
     |1:  // Copy vararg slots to destination slots.
-    |  cmp RC, TMP3
-    |  ldr TMP0, [RC], #8
-    |  csel TMP0, TMP0, TISNIL, lo
-    |   cmp RA, TMP2
-    |  str TMP0, [RA], #8
+    |  cmp RA, TMP3
+    |  ldr TMP0, [RA], #8
+    |  csinv TMP0, TMP0, xzr, lo	// TISNIL = ~xzr
+    |   cmp RC, TMP2
+    |  str TMP0, [RC], #8
     |   blo <1
     |   blo <1
     |2:
     |2:
     |  ins_next
     |  ins_next
     |
     |
     |5:  // Copy all varargs.
     |5:  // Copy all varargs.
     |  ldr TMP0, L->maxstack
     |  ldr TMP0, L->maxstack
-    |   subs TMP2, TMP3, RC
+    |   subs TMP2, TMP3, RA
     |   csel RB, xzr, TMP2, le		// MULTRES = (max(vtop-vbase,0)+1)*8
     |   csel RB, xzr, TMP2, le		// MULTRES = (max(vtop-vbase,0)+1)*8
     |   add RB, RB, #8
     |   add RB, RB, #8
-    |  add TMP1, RA, TMP2
+    |  add TMP1, RC, TMP2
     |   str RBw, SAVE_MULTRES
     |   str RBw, SAVE_MULTRES
     |   ble <2				// Nothing to copy.
     |   ble <2				// Nothing to copy.
     |  cmp TMP1, TMP0
     |  cmp TMP1, TMP0
     |  bhi >7
     |  bhi >7
     |6:
     |6:
-    |  ldr TMP0, [RC], #8
-    |  str TMP0, [RA], #8
-    |  cmp RC, TMP3
+    |  ldr TMP0, [RA], #8
+    |  str TMP0, [RC], #8
+    |  cmp RA, TMP3
     |  blo <6
     |  blo <6
     |  b <2
     |  b <2
     |
     |
     |7:  // Grow stack for varargs.
     |7:  // Grow stack for varargs.
     |  lsr CARG2, TMP2, #3
     |  lsr CARG2, TMP2, #3
-    |   stp BASE, RA, L->base
+    |   stp BASE, RC, L->base
     |  mov CARG1, L
     |  mov CARG1, L
-    |  sub RC, RC, BASE			// Need delta, because BASE may change.
+    |  sub RA, RA, BASE			// Need delta, because BASE may change.
     |   str PC, SAVE_PC
     |   str PC, SAVE_PC
     |  bl extern lj_state_growstack	// (lua_State *L, int n)
     |  bl extern lj_state_growstack	// (lua_State *L, int n)
-    |  ldp BASE, RA, L->base
-    |  add RC, BASE, RC
+    |  ldp BASE, RC, L->base
+    |  add RA, BASE, RA
     |  sub TMP3, BASE, #16
     |  sub TMP3, BASE, #16
     |  b <6
     |  b <6
     break;
     break;
@@ -3704,7 +3726,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     } else {
     } else {
       |  adds CARG1w, CARG1w, CARG3w
       |  adds CARG1w, CARG1w, CARG3w
       |  bvs >2
       |  bvs >2
-      |   add TMP0, CARG1, TISNUM
+      |   add_TISNUM TMP0, CARG1
       |  tbnz CARG3w, #31, >4
       |  tbnz CARG3w, #31, >4
       |  cmp CARG1w, CARG2w
       |  cmp CARG1w, CARG2w
     }
     }
@@ -3783,7 +3805,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  // RA = base, RC = target
     |  // RA = base, RC = target
     |  ldr CARG1, [BASE, RA, lsl #3]
     |  ldr CARG1, [BASE, RA, lsl #3]
     |   add TMP1, BASE, RA, lsl #3
     |   add TMP1, BASE, RA, lsl #3
-    |  cmp CARG1, TISNIL
+    |  cmp_nil CARG1
     |  beq >1				// Stop if iterator returned nil.
     |  beq >1				// Stop if iterator returned nil.
     if (op == BC_JITERL) {
     if (op == BC_JITERL) {
       |  str CARG1, [TMP1, #-8]
       |  str CARG1, [TMP1, #-8]
@@ -3892,6 +3914,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   add TMP2, BASE, RC
     |   add TMP2, BASE, RC
     |   add LFUNC:CARG3, CARG3, TMP0, lsl #47
     |   add LFUNC:CARG3, CARG3, TMP0, lsl #47
     |  add RA, RA, RC
     |  add RA, RA, RC
+    |  sub CARG1, CARG1, #8
     |   add TMP0, RC, #16+FRAME_VARG
     |   add TMP0, RC, #16+FRAME_VARG
     |   str LFUNC:CARG3, [TMP2], #8	// Store (tagged) copy of LFUNC.
     |   str LFUNC:CARG3, [TMP2], #8	// Store (tagged) copy of LFUNC.
     |    ldr KBASE, [PC, #-4+PC2PROTO(k)]
     |    ldr KBASE, [PC, #-4+PC2PROTO(k)]

+ 1 - 0
libs/LuaJIT/src/vm_mips64.dasc

@@ -5396,6 +5396,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   settp LFUNC:RB, TMP0
     |   settp LFUNC:RB, TMP0
     |  daddu TMP0, RA, RC
     |  daddu TMP0, RA, RC
     |   sd LFUNC:RB, 0(TMP1)		// Store (tagged) copy of LFUNC.
     |   sd LFUNC:RB, 0(TMP1)		// Store (tagged) copy of LFUNC.
+    |  daddiu TMP2, TMP2, -8
     |   daddiu TMP3, RC, 16+FRAME_VARG
     |   daddiu TMP3, RC, 16+FRAME_VARG
     |  sltu AT, TMP0, TMP2
     |  sltu AT, TMP0, TMP2
     |    ld KBASE, -4+PC2PROTO(k)(PC)
     |    ld KBASE, -4+PC2PROTO(k)(PC)

+ 30 - 12
libs/SDL2/CMakeLists.txt

@@ -2,6 +2,9 @@ if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
   message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the SDL source code and run \"cmake -S ${CMAKE_SOURCE_DIR} -B .\" from there")
   message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the SDL source code and run \"cmake -S ${CMAKE_SOURCE_DIR} -B .\" from there")
 endif()
 endif()
 
 
+# MSVC runtime library flags are selected by an abstraction.
+set(CMAKE_POLICY_DEFAULT_CMP0091 NEW)
+
 cmake_minimum_required(VERSION 3.0.0...3.5)
 cmake_minimum_required(VERSION 3.0.0...3.5)
 project(SDL2 C CXX)
 project(SDL2 C CXX)
 
 
@@ -84,7 +87,7 @@ endif()
 # See docs/release_checklist.md
 # See docs/release_checklist.md
 set(SDL_MAJOR_VERSION 2)
 set(SDL_MAJOR_VERSION 2)
 set(SDL_MINOR_VERSION 28)
 set(SDL_MINOR_VERSION 28)
-set(SDL_MICRO_VERSION 1)
+set(SDL_MICRO_VERSION 4)
 set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
 set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
 
 
 # Set defaults preventing destination file conflicts
 # Set defaults preventing destination file conflicts
@@ -224,11 +227,13 @@ elseif(MSVC_VERSION GREATER 1400) # VisualStudio 8.0+
 elseif(CMAKE_C_COMPILER_ID MATCHES "^Intel$")
 elseif(CMAKE_C_COMPILER_ID MATCHES "^Intel$")
   set(OPT_DEF_ASM TRUE)
   set(OPT_DEF_ASM TRUE)
   set(USE_INTELCC TRUE)
   set(USE_INTELCC TRUE)
+elseif(CMAKE_C_COMPILER_ID MATCHES "QCC")
+  set(USE_QCC TRUE)
 else()
 else()
   set(OPT_DEF_ASM FALSE)
   set(OPT_DEF_ASM FALSE)
 endif()
 endif()
 
 
-if(USE_GCC OR USE_CLANG OR USE_INTELCC)
+if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC)
   set(OPT_DEF_GCC_ATOMICS ON)
   set(OPT_DEF_GCC_ATOMICS ON)
 endif()
 endif()
 
 
@@ -253,6 +258,9 @@ endif()
 if(MSVC)
 if(MSVC)
   option(SDL_FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF)
   option(SDL_FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF)
   if(SDL_FORCE_STATIC_VCRT)
   if(SDL_FORCE_STATIC_VCRT)
+    if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
+      set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+    endif()
     foreach(flag_var
     foreach(flag_var
         CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
         CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
         CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
         CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
@@ -565,7 +573,7 @@ if(NOT SDL_FOREGROUNDING_SIGNAL STREQUAL "OFF")
 endif()
 endif()
 
 
 # Compiler option evaluation
 # Compiler option evaluation
-if(USE_GCC OR USE_CLANG OR USE_INTELCC)
+if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC)
   # Check for -Wall first, so later things can override pieces of it.
   # Check for -Wall first, so later things can override pieces of it.
   # Note: clang-cl treats -Wall as -Weverything (which is very loud),
   # Note: clang-cl treats -Wall as -Weverything (which is very loud),
   #       /W3 as -Wall, and /W4 as -Wall -Wextra.  So: /W3 is enough.
   #       /W3 as -Wall, and /W4 as -Wall -Wextra.  So: /W3 is enough.
@@ -622,11 +630,6 @@ if(USE_GCC OR USE_CLANG OR USE_INTELCC)
     endif()
     endif()
   endif()
   endif()
 
 
-  set(CMAKE_REQUIRED_FLAGS "-mpreferred-stack-boundary=2")
-  check_c_source_compiles("int x = 0; int main(int argc, char **argv) { return 0; }"
-    HAVE_GCC_PREFERRED_STACK_BOUNDARY)
-  set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
-
   set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden -Werror")
   set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden -Werror")
   check_c_source_compiles("
   check_c_source_compiles("
       #if !defined(__GNUC__) || __GNUC__ < 4
       #if !defined(__GNUC__) || __GNUC__ < 4
@@ -1429,6 +1432,12 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
         file(GLOB AIX_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/paudio/*.c)
         file(GLOB AIX_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/paudio/*.c)
         list(APPEND SOURCE_FILES ${AIX_AUDIO_SOURCES})
         list(APPEND SOURCE_FILES ${AIX_AUDIO_SOURCES})
         set(HAVE_SDL_AUDIO TRUE)
         set(HAVE_SDL_AUDIO TRUE)
+    elseif(QNX)
+        set(SDL_AUDIO_DRIVER_QSA 1)
+        file(GLOB QSA_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/qsa/*.c)
+        list(APPEND SOURCE_FILES ${QSA_AUDIO_SOURCES})
+        list(APPEND EXTRA_LIBS asound)
+        set(HAVE_SDL_AUDIO TRUE)
     endif()
     endif()
     CheckOSS()
     CheckOSS()
     CheckALSA()
     CheckALSA()
@@ -1460,6 +1469,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
       set(SDL_VIDEO_VULKAN 1)
       set(SDL_VIDEO_VULKAN 1)
       set(HAVE_VULKAN TRUE)
       set(HAVE_VULKAN TRUE)
     endif()
     endif()
+    CheckQNXScreen()
   endif()
   endif()
 
 
   if(UNIX)
   if(UNIX)
@@ -1710,6 +1720,13 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
     set(HAVE_RPATH TRUE)
     set(HAVE_RPATH TRUE)
   endif()
   endif()
 
 
+  if(QNX)
+    # QNX's *printf() family generates a SIGSEGV if NULL is passed for a string
+    # specifier (on purpose), but SDL expects "(null)". Use the built-in
+    # implementation.
+    set(HAVE_VSNPRINTF 0)
+    set(USE_POSIX_SPAWN 1)
+  endif()
 elseif(WINDOWS)
 elseif(WINDOWS)
   find_program(WINDRES windres)
   find_program(WINDRES windres)
 
 
@@ -1770,7 +1787,7 @@ elseif(WINDOWS)
     check_include_file(ddraw.h HAVE_DDRAW_H)
     check_include_file(ddraw.h HAVE_DDRAW_H)
     check_include_file(dsound.h HAVE_DSOUND_H)
     check_include_file(dsound.h HAVE_DSOUND_H)
     check_include_file(dinput.h HAVE_DINPUT_H)
     check_include_file(dinput.h HAVE_DINPUT_H)
-    if(WINDOWS_STORE OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM")
+    if(WINDOWS_STORE OR SDL_CPU_ARM32)
       set(HAVE_DINPUT_H 0)
       set(HAVE_DINPUT_H 0)
     endif()
     endif()
     check_include_file(dxgi.h HAVE_DXGI_H)
     check_include_file(dxgi.h HAVE_DXGI_H)
@@ -1932,7 +1949,7 @@ elseif(WINDOWS)
 
 
   # Libraries for Win32 native and MinGW
   # Libraries for Win32 native and MinGW
   if(NOT WINDOWS_STORE)
   if(NOT WINDOWS_STORE)
-    list(APPEND EXTRA_LIBS user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32)
+    list(APPEND EXTRA_LIBS kernel32 user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32)
   endif()
   endif()
 
 
   if(WINDOWS_STORE)
   if(WINDOWS_STORE)
@@ -3193,7 +3210,7 @@ if (SDL_ASAN)
 endif()
 endif()
 
 
 if(SDL_CCACHE AND NOT CMAKE_VERSION VERSION_LESS 3.4)
 if(SDL_CCACHE AND NOT CMAKE_VERSION VERSION_LESS 3.4)
-  cmake_minimum_required(VERSION 3.4)
+  cmake_minimum_required(VERSION 3.4...3.5)
   find_program(CCACHE_BINARY ccache)
   find_program(CCACHE_BINARY ccache)
   if(CCACHE_BINARY)
   if(CCACHE_BINARY)
     set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_BINARY})
     set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_BINARY})
@@ -3340,6 +3357,7 @@ if(SDL_SHARED)
   # alias target for in-tree builds
   # alias target for in-tree builds
   add_library(SDL2::SDL2 ALIAS SDL2)
   add_library(SDL2::SDL2 ALIAS SDL2)
   set_target_properties(SDL2 PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
   set_target_properties(SDL2 PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
+  set_target_properties(SDL2 PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS FALSE)
   if(NOT SDL_LIBC)
   if(NOT SDL_LIBC)
     if(SDL_CPU_X86)
     if(SDL_CPU_X86)
       # FIXME: should be added for all architectures (missing symbols for ARM)
       # FIXME: should be added for all architectures (missing symbols for ARM)
@@ -3374,7 +3392,7 @@ if(SDL_SHARED)
       OUTPUT_NAME "SDL2")
       OUTPUT_NAME "SDL2")
   endif()
   endif()
   # Note: The clang toolset for Visual Studio does not support /NODEFAULTLIB.
   # Note: The clang toolset for Visual Studio does not support /NODEFAULTLIB.
-  if(MSVC AND NOT SDL_LIBC AND NOT MSVC_CLANG AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM")
+  if(MSVC AND NOT SDL_LIBC AND NOT MSVC_CLANG AND NOT SDL_CPU_ARM32)
     # Don't try to link with the default set of libraries.
     # Don't try to link with the default set of libraries.
     if(NOT WINDOWS_STORE)
     if(NOT WINDOWS_STORE)
       set_property(TARGET SDL2 APPEND_STRING PROPERTY LINK_FLAGS " /NODEFAULTLIB")
       set_property(TARGET SDL2 APPEND_STRING PROPERTY LINK_FLAGS " /NODEFAULTLIB")

+ 1 - 1
libs/SDL2/Makefile.os2

@@ -15,7 +15,7 @@
 LIBNAME = SDL2
 LIBNAME = SDL2
 MAJOR_VERSION = 2
 MAJOR_VERSION = 2
 MINOR_VERSION = 28
 MINOR_VERSION = 28
-MICRO_VERSION = 1
+MICRO_VERSION = 4
 VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
 VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
 DESCRIPTION = Simple DirectMedia Layer 2
 DESCRIPTION = Simple DirectMedia Layer 2
 
 

+ 1 - 1
libs/SDL2/Makefile.w32

@@ -6,7 +6,7 @@
 LIBNAME = SDL2
 LIBNAME = SDL2
 MAJOR_VERSION = 2
 MAJOR_VERSION = 2
 MINOR_VERSION = 28
 MINOR_VERSION = 28
-MICRO_VERSION = 1
+MICRO_VERSION = 4
 VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
 VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
 
 
 LIBHOME = .
 LIBHOME = .

+ 1 - 1
libs/SDL2/SDL2.spec

@@ -1,6 +1,6 @@
 Summary: Simple DirectMedia Layer
 Summary: Simple DirectMedia Layer
 Name: SDL2
 Name: SDL2
-Version: 2.28.1
+Version: 2.28.4
 Release: 2
 Release: 2
 Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
 Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
 URL: http://www.libsdl.org/
 URL: http://www.libsdl.org/

+ 1 - 1
libs/SDL2/VERSION.txt

@@ -1 +1 @@
-release-2.28.1-0-g4761467b2
+release-2.28.4-0-gcc016b004

+ 1 - 1
libs/SDL2/VisualC/pkg-support/cmake/sdl2-config.cmake

@@ -1,7 +1,7 @@
 # SDL2 CMake configuration file:
 # SDL2 CMake configuration file:
 # This file is meant to be placed in a cmake subfolder of SDL2-devel-2.x.y-VC
 # This file is meant to be placed in a cmake subfolder of SDL2-devel-2.x.y-VC
 
 
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.0...3.5)
 
 
 include(FeatureSummary)
 include(FeatureSummary)
 set_package_properties(SDL2 PROPERTIES
 set_package_properties(SDL2 PROPERTIES

+ 7 - 0
libs/SDL2/WhatsNew.txt

@@ -1,6 +1,13 @@
 
 
 This is a list of major changes in SDL's version history.
 This is a list of major changes in SDL's version history.
 
 
+---------------------------------------------------------------------------
+2.28.2:
+---------------------------------------------------------------------------
+General:
+* Added the hint SDL_HINT_JOYSTICK_WGI to control whether to use Windows.Gaming.Input for controllers
+
+
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 2.28.0:
 2.28.0:
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 2 - 2
libs/SDL2/Xcode/SDL/Info-Framework.plist

@@ -19,10 +19,10 @@
 	<key>CFBundlePackageType</key>
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
 	<key>CFBundleShortVersionString</key>
-	<string>2.28.1</string>
+	<string>2.28.4</string>
 	<key>CFBundleSignature</key>
 	<key>CFBundleSignature</key>
 	<string>SDLX</string>
 	<string>SDLX</string>
 	<key>CFBundleVersion</key>
 	<key>CFBundleVersion</key>
-	<string>2.28.1</string>
+	<string>2.28.4</string>
 </dict>
 </dict>
 </plist>
 </plist>

+ 6 - 6
libs/SDL2/Xcode/SDL/SDL.xcodeproj/project.pbxproj

@@ -9529,7 +9529,7 @@
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEPLOYMENT_POSTPROCESSING = YES;
 				DEPLOYMENT_POSTPROCESSING = YES;
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
-				DYLIB_CURRENT_VERSION = 2801.1.0;
+				DYLIB_CURRENT_VERSION = 2801.4.0;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_ALTIVEC_EXTENSIONS = YES;
 				GCC_ALTIVEC_EXTENSIONS = YES;
@@ -9570,7 +9570,7 @@
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				CLANG_LINK_OBJC_RUNTIME = NO;
-				MARKETING_VERSION = 2.28.1;
+				MARKETING_VERSION = 2.28.4;
 				OTHER_LDFLAGS = "-liconv";
 				OTHER_LDFLAGS = "-liconv";
 			};
 			};
 			name = Release;
 			name = Release;
@@ -9614,7 +9614,7 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
-				DYLIB_CURRENT_VERSION = 2801.1.0;
+				DYLIB_CURRENT_VERSION = 2801.4.0;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				ENABLE_TESTABILITY = YES;
@@ -9656,7 +9656,7 @@
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				CLANG_LINK_OBJC_RUNTIME = NO;
-				MARKETING_VERSION = 2.28.1;
+				MARKETING_VERSION = 2.28.4;
 				OTHER_LDFLAGS = "-liconv";
 				OTHER_LDFLAGS = "-liconv";
 			};
 			};
 			name = Debug;
 			name = Debug;
@@ -9863,7 +9863,7 @@
 				DEFINES_MODULE = YES;
 				DEFINES_MODULE = YES;
 				DEVELOPMENT_TEAM = "";
 				DEVELOPMENT_TEAM = "";
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
-				DYLIB_CURRENT_VERSION = 2801.1.0;
+				DYLIB_CURRENT_VERSION = 2801.4.0;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				GCC_C_LANGUAGE_STANDARD = gnu11;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_DYNAMIC_NO_PIC = NO;
@@ -9915,7 +9915,7 @@
 				DEFINES_MODULE = YES;
 				DEFINES_MODULE = YES;
 				DEVELOPMENT_TEAM = "";
 				DEVELOPMENT_TEAM = "";
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 2801.0.0;
-				DYLIB_CURRENT_VERSION = 2801.1.0;
+				DYLIB_CURRENT_VERSION = 2801.4.0;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				ENABLE_NS_ASSERTIONS = NO;
 				ENABLE_NS_ASSERTIONS = NO;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
 				GCC_C_LANGUAGE_STANDARD = gnu11;

+ 1 - 1
libs/SDL2/Xcode/SDL/pkg-support/SDL.info

@@ -1,4 +1,4 @@
-Title SDL 2.28.1
+Title SDL 2.28.4
 Version 1
 Version 1
 Description SDL Library for Mac OS X (http://www.libsdl.org)
 Description SDL Library for Mac OS X (http://www.libsdl.org)
 DefaultLocation /Library/Frameworks
 DefaultLocation /Library/Frameworks

+ 10 - 10
libs/SDL2/android-project/app/build.gradle

@@ -8,22 +8,22 @@ else {
 }
 }
 
 
 android {
 android {
-    compileSdkVersion 31
+    if (buildAsApplication) {
+        namespace "org.libsdl.app"
+    }
+    compileSdkVersion 34
     defaultConfig {
     defaultConfig {
-        if (buildAsApplication) {
-            applicationId "org.libsdl.app"
-        }
-        minSdkVersion 16
-        targetSdkVersion 31
+        minSdkVersion 19
+        targetSdkVersion 34
         versionCode 1
         versionCode 1
         versionName "1.0"
         versionName "1.0"
         externalNativeBuild {
         externalNativeBuild {
             ndkBuild {
             ndkBuild {
-                arguments "APP_PLATFORM=android-16"
+                arguments "APP_PLATFORM=android-19"
                 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
             }
             }
             // cmake {
             // cmake {
-            //     arguments "-DANDROID_APP_PLATFORM=android-16", "-DANDROID_STL=c++_static"
+            //     arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static"
             //     // abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
             //     // abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
             //     abiFilters 'arm64-v8a'
             //     abiFilters 'arm64-v8a'
             // }
             // }
@@ -53,10 +53,10 @@ android {
         }
         }
        
        
     }
     }
-    lintOptions {
+    lint {
         abortOnError false
         abortOnError false
     }
     }
-    
+
     if (buildAsLibrary) {
     if (buildAsLibrary) {
         libraryVariants.all { variant ->
         libraryVariants.all { variant ->
             variant.outputs.each { output ->
             variant.outputs.each { output ->

+ 0 - 1
libs/SDL2/android-project/app/src/main/AndroidManifest.xml

@@ -3,7 +3,6 @@
      com.gamemaker.game
      com.gamemaker.game
 -->
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="org.libsdl.app"
     android:versionCode="1"
     android:versionCode="1"
     android:versionName="1.0"
     android:versionName="1.0"
     android:installLocation="auto">
     android:installLocation="auto">

+ 16 - 18
libs/SDL2/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java

@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
     private static final String TAG = "SDL";
     private static final String TAG = "SDL";
     private static final int SDL_MAJOR_VERSION = 2;
     private static final int SDL_MAJOR_VERSION = 2;
     private static final int SDL_MINOR_VERSION = 28;
     private static final int SDL_MINOR_VERSION = 28;
-    private static final int SDL_MICRO_VERSION = 1;
+    private static final int SDL_MICRO_VERSION = 4;
 /*
 /*
     // Display InputType.SOURCE/CLASS of events and devices
     // Display InputType.SOURCE/CLASS of events and devices
     //
     //
@@ -1345,23 +1345,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
             }
             }
         }
         }
 
 
-        if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
-            if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                if (isTextInputEvent(event)) {
-                    if (ic != null) {
-                        ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
-                    } else {
-                        SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
-                    }
-                }
-                onNativeKeyDown(keyCode);
-                return true;
-            } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                onNativeKeyUp(keyCode);
-                return true;
-            }
-        }
-
         if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
         if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
             // on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
             // on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
             // they are ignored here because sending them as mouse input to SDL is messy
             // they are ignored here because sending them as mouse input to SDL is messy
@@ -1376,6 +1359,21 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
             }
             }
         }
         }
 
 
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            if (isTextInputEvent(event)) {
+                if (ic != null) {
+                    ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
+                } else {
+                    SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
+                }
+            }
+            onNativeKeyDown(keyCode);
+            return true;
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            onNativeKeyUp(keyCode);
+            return true;
+        }
+
         return false;
         return false;
     }
     }
 
 

+ 1 - 1
libs/SDL2/android-project/build.gradle

@@ -6,7 +6,7 @@ buildscript {
         google()
         google()
     }
     }
     dependencies {
     dependencies {
-        classpath 'com.android.tools.build:gradle:7.0.3'
+        classpath 'com.android.tools.build:gradle:8.1.1'
 
 
         // NOTE: Do not place your application dependencies here; they belong
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
         // in the individual module build.gradle files

+ 1 - 1
libs/SDL2/android-project/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
 #Thu Nov 11 18:20:34 PST 2021
 #Thu Nov 11 18:20:34 PST 2021
 distributionBase=GRADLE_USER_HOME
 distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
 distributionPath=wrapper/dists
 distributionPath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStoreBase=GRADLE_USER_HOME

+ 52 - 13
libs/SDL2/build-scripts/config.guess

@@ -1,10 +1,10 @@
 #! /bin/sh
 #! /bin/sh
 # Attempt to guess a canonical system name.
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2022 Free Software Foundation, Inc.
+#   Copyright 1992-2023 Free Software Foundation, Inc.
 
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
 
-timestamp='2022-05-25'
+timestamp='2023-08-22'
 
 
 # This file is free software; you can redistribute it and/or modify it
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
 # under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'`
 usage="\
 usage="\
 Usage: $0 [OPTION]
 Usage: $0 [OPTION]
 
 
-Output the configuration name of the system \`$me' is run on.
+Output the configuration name of the system '$me' is run on.
 
 
 Options:
 Options:
   -h, --help         print this help, then exit
   -h, --help         print this help, then exit
@@ -60,13 +60,13 @@ version="\
 GNU config.guess ($timestamp)
 GNU config.guess ($timestamp)
 
 
 Originally written by Per Bothner.
 Originally written by Per Bothner.
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
 
 
 This is free software; see the source for copying conditions.  There is NO
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 
 
 help="
 help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
 
 
 # Parse command line
 # Parse command line
 while test $# -gt 0 ; do
 while test $# -gt 0 ; do
@@ -102,8 +102,8 @@ GUESS=
 # temporary files to be created and, as you can see below, it is a
 # temporary files to be created and, as you can see below, it is a
 # headache to deal with in a portable fashion.
 # headache to deal with in a portable fashion.
 
 
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
 
 
 # Portable tmp directory creation inspired by the Autoconf team.
 # Portable tmp directory creation inspired by the Autoconf team.
 
 
@@ -155,6 +155,9 @@ Linux|GNU|GNU/*)
 
 
 	set_cc_for_build
 	set_cc_for_build
 	cat <<-EOF > "$dummy.c"
 	cat <<-EOF > "$dummy.c"
+	#if defined(__ANDROID__)
+	LIBC=android
+	#else
 	#include <features.h>
 	#include <features.h>
 	#if defined(__UCLIBC__)
 	#if defined(__UCLIBC__)
 	LIBC=uclibc
 	LIBC=uclibc
@@ -169,6 +172,7 @@ Linux|GNU|GNU/*)
 	LIBC=musl
 	LIBC=musl
 	#endif
 	#endif
 	#endif
 	#endif
+	#endif
 	EOF
 	EOF
 	cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
 	cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
 	eval "$cc_set_libc"
 	eval "$cc_set_libc"
@@ -459,7 +463,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
 		UNAME_RELEASE=`uname -v`
 		UNAME_RELEASE=`uname -v`
 		;;
 		;;
 	esac
 	esac
-	# Japanese Language versions have a version number like `4.1.3-JL'.
+	# Japanese Language versions have a version number like '4.1.3-JL'.
 	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
 	SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
 	GUESS=sparc-sun-sunos$SUN_REL
 	GUESS=sparc-sun-sunos$SUN_REL
 	;;
 	;;
@@ -904,7 +908,7 @@ EOF
 	fi
 	fi
 	;;
 	;;
     *:FreeBSD:*:*)
     *:FreeBSD:*:*)
-	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	UNAME_PROCESSOR=`uname -p`
 	case $UNAME_PROCESSOR in
 	case $UNAME_PROCESSOR in
 	    amd64)
 	    amd64)
 		UNAME_PROCESSOR=x86_64 ;;
 		UNAME_PROCESSOR=x86_64 ;;
@@ -966,11 +970,37 @@ EOF
 	GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
 	GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
 	GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
 	GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
 	;;
 	;;
+    x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+	GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+	;;
+    *:[Mm]anagarm:*:*)
+	GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+	;;
     *:Minix:*:*)
     *:Minix:*:*)
 	GUESS=$UNAME_MACHINE-unknown-minix
 	GUESS=$UNAME_MACHINE-unknown-minix
 	;;
 	;;
     aarch64:Linux:*:*)
     aarch64:Linux:*:*)
-	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	set_cc_for_build
+	CPU=$UNAME_MACHINE
+	LIBCABI=$LIBC
+	if test "$CC_FOR_BUILD" != no_compiler_found; then
+	    ABI=64
+	    sed 's/^	    //' << EOF > "$dummy.c"
+	    #ifdef __ARM_EABI__
+	    #ifdef __ARM_PCS_VFP
+	    ABI=eabihf
+	    #else
+	    ABI=eabi
+	    #endif
+	    #endif
+EOF
+	    cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+	    eval "$cc_set_abi"
+	    case $ABI in
+		eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
+	    esac
+	fi
+	GUESS=$CPU-unknown-linux-$LIBCABI
 	;;
 	;;
     aarch64_be:Linux:*:*)
     aarch64_be:Linux:*:*)
 	UNAME_MACHINE=aarch64_be
 	UNAME_MACHINE=aarch64_be
@@ -1036,7 +1066,16 @@ EOF
     k1om:Linux:*:*)
     k1om:Linux:*:*)
 	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
 	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
 	;;
 	;;
-    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+    kvx:Linux:*:*)
+	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+	;;
+    kvx:cos:*:*)
+	GUESS=$UNAME_MACHINE-unknown-cos
+	;;
+    kvx:mbr:*:*)
+	GUESS=$UNAME_MACHINE-unknown-mbr
+	;;
+    loongarch32:Linux:*:* | loongarch64:Linux:*:*)
 	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
 	GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
 	;;
 	;;
     m32r*:Linux:*:*)
     m32r*:Linux:*:*)
@@ -1191,7 +1230,7 @@ EOF
 	GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
 	GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
 	;;
 	;;
     i*86:OS/2:*:*)
     i*86:OS/2:*:*)
-	# If we were able to find `uname', then EMX Unix compatibility
+	# If we were able to find 'uname', then EMX Unix compatibility
 	# is probably installed.
 	# is probably installed.
 	GUESS=$UNAME_MACHINE-pc-os2-emx
 	GUESS=$UNAME_MACHINE-pc-os2-emx
 	;;
 	;;
@@ -1332,7 +1371,7 @@ EOF
 		GUESS=ns32k-sni-sysv
 		GUESS=ns32k-sni-sysv
 	fi
 	fi
 	;;
 	;;
-    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+    PENTIUM:*:4.0*:*)	# Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
 			# says <[email protected]>
 			# says <[email protected]>
 	GUESS=i586-unisys-sysv4
 	GUESS=i586-unisys-sysv4
 	;;
 	;;

+ 146 - 76
libs/SDL2/build-scripts/config.sub

@@ -1,10 +1,10 @@
 #! /bin/sh
 #! /bin/sh
 # Configuration validation subroutine script.
 # Configuration validation subroutine script.
-#   Copyright 1992-2022 Free Software Foundation, Inc.
+#   Copyright 1992-2023 Free Software Foundation, Inc.
 
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
 
-timestamp='2022-01-03'
+timestamp='2023-09-19'
 
 
 # This file is free software; you can redistribute it and/or modify it
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
 # under the terms of the GNU General Public License as published by
@@ -76,13 +76,13 @@ Report bugs and patches to <[email protected]>."
 version="\
 version="\
 GNU config.sub ($timestamp)
 GNU config.sub ($timestamp)
 
 
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
 
 
 This is free software; see the source for copying conditions.  There is NO
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 
 
 help="
 help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
 
 
 # Parse command line
 # Parse command line
 while test $# -gt 0 ; do
 while test $# -gt 0 ; do
@@ -130,7 +130,7 @@ IFS=$saved_IFS
 # Separate into logical components for further validation
 # Separate into logical components for further validation
 case $1 in
 case $1 in
 	*-*-*-*-*)
 	*-*-*-*-*)
-		echo Invalid configuration \`"$1"\': more than four components >&2
+		echo "Invalid configuration '$1': more than four components" >&2
 		exit 1
 		exit 1
 		;;
 		;;
 	*-*-*-*)
 	*-*-*-*)
@@ -145,7 +145,8 @@ case $1 in
 			nto-qnx* | linux-* | uclinux-uclibc* \
 			nto-qnx* | linux-* | uclinux-uclibc* \
 			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
 			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
 			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
 			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
-			| storm-chaos* | os2-emx* | rtmk-nova*)
+			| storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \
+			| windows-* )
 				basic_machine=$field1
 				basic_machine=$field1
 				basic_os=$maybe_os
 				basic_os=$maybe_os
 				;;
 				;;
@@ -943,7 +944,7 @@ $basic_machine
 EOF
 EOF
 		IFS=$saved_IFS
 		IFS=$saved_IFS
 		;;
 		;;
-	# We use `pc' rather than `unknown'
+	# We use 'pc' rather than 'unknown'
 	# because (1) that's what they normally are, and
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
 	# (2) the word "unknown" tends to confuse beginning users.
 	i*86 | x86_64)
 	i*86 | x86_64)
@@ -1180,7 +1181,7 @@ case $cpu-$vendor in
 		case $cpu in
 		case $cpu in
 			1750a | 580 \
 			1750a | 580 \
 			| a29k \
 			| a29k \
-			| aarch64 | aarch64_be \
+			| aarch64 | aarch64_be | aarch64c | arm64ec \
 			| abacus \
 			| abacus \
 			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
 			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
 			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
 			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
@@ -1199,45 +1200,23 @@ case $cpu-$vendor in
 			| d10v | d30v | dlx | dsp16xx \
 			| d10v | d30v | dlx | dsp16xx \
 			| e2k | elxsi | epiphany \
 			| e2k | elxsi | epiphany \
 			| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
 			| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+			| javascript \
 			| h8300 | h8500 \
 			| h8300 | h8500 \
 			| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 			| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 			| hexagon \
 			| hexagon \
 			| i370 | i*86 | i860 | i960 | ia16 | ia64 \
 			| i370 | i*86 | i860 | i960 | ia16 | ia64 \
 			| ip2k | iq2000 \
 			| ip2k | iq2000 \
 			| k1om \
 			| k1om \
+			| kvx \
 			| le32 | le64 \
 			| le32 | le64 \
 			| lm32 \
 			| lm32 \
-			| loongarch32 | loongarch64 | loongarchx32 \
+			| loongarch32 | loongarch64 \
 			| m32c | m32r | m32rle \
 			| m32c | m32r | m32rle \
 			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
 			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
 			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
 			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
 			| m88110 | m88k | maxq | mb | mcore | mep | metag \
 			| m88110 | m88k | maxq | mb | mcore | mep | metag \
 			| microblaze | microblazeel \
 			| microblaze | microblazeel \
-			| mips | mipsbe | mipseb | mipsel | mipsle \
-			| mips16 \
-			| mips64 | mips64eb | mips64el \
-			| mips64octeon | mips64octeonel \
-			| mips64orion | mips64orionel \
-			| mips64r5900 | mips64r5900el \
-			| mips64vr | mips64vrel \
-			| mips64vr4100 | mips64vr4100el \
-			| mips64vr4300 | mips64vr4300el \
-			| mips64vr5000 | mips64vr5000el \
-			| mips64vr5900 | mips64vr5900el \
-			| mipsisa32 | mipsisa32el \
-			| mipsisa32r2 | mipsisa32r2el \
-			| mipsisa32r3 | mipsisa32r3el \
-			| mipsisa32r5 | mipsisa32r5el \
-			| mipsisa32r6 | mipsisa32r6el \
-			| mipsisa64 | mipsisa64el \
-			| mipsisa64r2 | mipsisa64r2el \
-			| mipsisa64r3 | mipsisa64r3el \
-			| mipsisa64r5 | mipsisa64r5el \
-			| mipsisa64r6 | mipsisa64r6el \
-			| mipsisa64sb1 | mipsisa64sb1el \
-			| mipsisa64sr71k | mipsisa64sr71kel \
-			| mipsr5900 | mipsr5900el \
-			| mipstx39 | mipstx39el \
+			| mips* \
 			| mmix \
 			| mmix \
 			| mn10200 | mn10300 \
 			| mn10200 | mn10300 \
 			| moxie \
 			| moxie \
@@ -1285,7 +1264,7 @@ case $cpu-$vendor in
 				;;
 				;;
 
 
 			*)
 			*)
-				echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+				echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
 				exit 1
 				exit 1
 				;;
 				;;
 		esac
 		esac
@@ -1306,11 +1285,12 @@ esac
 
 
 # Decode manufacturer-specific aliases for certain operating systems.
 # Decode manufacturer-specific aliases for certain operating systems.
 
 
-if test x$basic_os != x
+if test x"$basic_os" != x
 then
 then
 
 
 # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
 # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
 # set os.
 # set os.
+obj=
 case $basic_os in
 case $basic_os in
 	gnu/linux*)
 	gnu/linux*)
 		kernel=linux
 		kernel=linux
@@ -1341,6 +1321,10 @@ EOF
 		kernel=linux
 		kernel=linux
 		os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
 		os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
 		;;
 		;;
+	managarm*)
+		kernel=managarm
+		os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
+		;;
 	*)
 	*)
 		kernel=
 		kernel=
 		os=$basic_os
 		os=$basic_os
@@ -1506,10 +1490,16 @@ case $os in
 			os=eabi
 			os=eabi
 			;;
 			;;
 		    *)
 		    *)
-			os=elf
+			os=
+			obj=elf
 			;;
 			;;
 		esac
 		esac
 		;;
 		;;
+	aout* | coff* | elf* | pe*)
+		# These are machine code file formats, not OSes
+		obj=$os
+		os=
+		;;
 	*)
 	*)
 		# No normalization, but not necessarily accepted, that comes below.
 		# No normalization, but not necessarily accepted, that comes below.
 		;;
 		;;
@@ -1528,12 +1518,15 @@ else
 # system, and we'll never get to this point.
 # system, and we'll never get to this point.
 
 
 kernel=
 kernel=
+obj=
 case $cpu-$vendor in
 case $cpu-$vendor in
 	score-*)
 	score-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	spu-*)
 	spu-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	*-acorn)
 	*-acorn)
 		os=riscix1.2
 		os=riscix1.2
@@ -1543,28 +1536,35 @@ case $cpu-$vendor in
 		os=gnu
 		os=gnu
 		;;
 		;;
 	arm*-semi)
 	arm*-semi)
-		os=aout
+		os=
+		obj=aout
 		;;
 		;;
 	c4x-* | tic4x-*)
 	c4x-* | tic4x-*)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	c8051-*)
 	c8051-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	clipper-intergraph)
 	clipper-intergraph)
 		os=clix
 		os=clix
 		;;
 		;;
 	hexagon-*)
 	hexagon-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	tic54x-*)
 	tic54x-*)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	tic55x-*)
 	tic55x-*)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	tic6x-*)
 	tic6x-*)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	# This must come before the *-dec entry.
 	# This must come before the *-dec entry.
 	pdp10-*)
 	pdp10-*)
@@ -1586,19 +1586,24 @@ case $cpu-$vendor in
 		os=sunos3
 		os=sunos3
 		;;
 		;;
 	m68*-cisco)
 	m68*-cisco)
-		os=aout
+		os=
+		obj=aout
 		;;
 		;;
 	mep-*)
 	mep-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	mips*-cisco)
 	mips*-cisco)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	mips*-*)
 	mips*-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	or32-*)
 	or32-*)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	*-tti)	# must be before sparc entry or we get the wrong os.
 	*-tti)	# must be before sparc entry or we get the wrong os.
 		os=sysv3
 		os=sysv3
@@ -1607,7 +1612,8 @@ case $cpu-$vendor in
 		os=sunos4.1.1
 		os=sunos4.1.1
 		;;
 		;;
 	pru-*)
 	pru-*)
-		os=elf
+		os=
+		obj=elf
 		;;
 		;;
 	*-be)
 	*-be)
 		os=beos
 		os=beos
@@ -1688,10 +1694,12 @@ case $cpu-$vendor in
 		os=uxpv
 		os=uxpv
 		;;
 		;;
 	*-rom68k)
 	*-rom68k)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	*-*bug)
 	*-*bug)
-		os=coff
+		os=
+		obj=coff
 		;;
 		;;
 	*-apple)
 	*-apple)
 		os=macos
 		os=macos
@@ -1709,7 +1717,8 @@ esac
 
 
 fi
 fi
 
 
-# Now, validate our (potentially fixed-up) OS.
+# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ).
+
 case $os in
 case $os in
 	# Sometimes we do "kernel-libc", so those need to count as OSes.
 	# Sometimes we do "kernel-libc", so those need to count as OSes.
 	musl* | newlib* | relibc* | uclibc*)
 	musl* | newlib* | relibc* | uclibc*)
@@ -1720,6 +1729,9 @@ case $os in
 	# VxWorks passes extra cpu info in the 4th filed.
 	# VxWorks passes extra cpu info in the 4th filed.
 	simlinux | simwindows | spe)
 	simlinux | simwindows | spe)
 		;;
 		;;
+	# See `case $cpu-$os` validation below
+	ghcjs)
+		;;
 	# Now accept the basic system types.
 	# Now accept the basic system types.
 	# The portable systems comes first.
 	# The portable systems comes first.
 	# Each alternative MUST end in a * to match a version number.
 	# Each alternative MUST end in a * to match a version number.
@@ -1728,7 +1740,7 @@ case $os in
 	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
 	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
 	     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
 	     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
 	     | hiux* | abug | nacl* | netware* | windows* \
 	     | hiux* | abug | nacl* | netware* | windows* \
-	     | os9* | macos* | osx* | ios* \
+	     | os9* | macos* | osx* | ios* | tvos* | watchos* \
 	     | mpw* | magic* | mmixware* | mon960* | lnews* \
 	     | mpw* | magic* | mmixware* | mon960* | lnews* \
 	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
 	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
 	     | aos* | aros* | cloudabi* | sortix* | twizzler* \
 	     | aos* | aros* | cloudabi* | sortix* | twizzler* \
@@ -1737,11 +1749,11 @@ case $os in
 	     | mirbsd* | netbsd* | dicos* | openedition* | ose* \
 	     | mirbsd* | netbsd* | dicos* | openedition* | ose* \
 	     | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
 	     | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
 	     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
 	     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
-	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
-	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+	     | bosx* | nextstep* | cxux* | oabi* \
+	     | ptx* | ecoff* | winnt* | domain* | vsta* \
 	     | udi* | lites* | ieee* | go32* | aux* | hcos* \
 	     | udi* | lites* | ieee* | go32* | aux* | hcos* \
 	     | chorusrdb* | cegcc* | glidix* | serenity* \
 	     | chorusrdb* | cegcc* | glidix* | serenity* \
-	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+	     | cygwin* | msys* | moss* | proelf* | rtems* \
 	     | midipix* | mingw32* | mingw64* | mint* \
 	     | midipix* | mingw32* | mingw64* | mint* \
 	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
 	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
 	     | interix* | uwin* | mks* | rhapsody* | darwin* \
 	     | interix* | uwin* | mks* | rhapsody* | darwin* \
@@ -1754,7 +1766,7 @@ case $os in
 	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
 	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
 	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
 	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
 	     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
 	     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
-	     | fiwix* )
+	     | fiwix* | mlibc* | cos* | mbr* )
 		;;
 		;;
 	# This one is extra strict with allowed versions
 	# This one is extra strict with allowed versions
 	sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
 	sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@@ -1762,41 +1774,99 @@ case $os in
 		;;
 		;;
 	none)
 	none)
 		;;
 		;;
+	kernel* | msvc* )
+		# Restricted further below
+		;;
+	'')
+		if test x"$obj" = x
+		then
+			echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2
+		fi
+		;;
+	*)
+		echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
+		exit 1
+		;;
+esac
+
+case $obj in
+	aout* | coff* | elf* | pe*)
+		;;
+	'')
+		# empty is fine
+		;;
 	*)
 	*)
-		echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+		echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
+		exit 1
+		;;
+esac
+
+# Here we handle the constraint that a (synthetic) cpu and os are
+# valid only in combination with each other and nowhere else.
+case $cpu-$os in
+	# The "javascript-unknown-ghcjs" triple is used by GHC; we
+	# accept it here in order to tolerate that, but reject any
+	# variations.
+	javascript-ghcjs)
+		;;
+	javascript-* | *-ghcjs)
+		echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
 		exit 1
 		exit 1
 		;;
 		;;
 esac
 esac
 
 
 # As a final step for OS-related things, validate the OS-kernel combination
 # As a final step for OS-related things, validate the OS-kernel combination
 # (given a valid OS), if there is a kernel.
 # (given a valid OS), if there is a kernel.
-case $kernel-$os in
-	linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
-		   | linux-musl* | linux-relibc* | linux-uclibc* )
+case $kernel-$os-$obj in
+	linux-gnu*- | linux-dietlibc*- | linux-android*- | linux-newlib*- \
+		   | linux-musl*- | linux-relibc*- | linux-uclibc*- | linux-mlibc*- )
+		;;
+	uclinux-uclibc*- )
 		;;
 		;;
-	uclinux-uclibc* )
+	managarm-mlibc*- | managarm-kernel*- )
 		;;
 		;;
-	-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+	windows*-msvc*-)
+		;;
+	-dietlibc*- | -newlib*- | -musl*- | -relibc*- | -uclibc*- | -mlibc*- )
 		# These are just libc implementations, not actual OSes, and thus
 		# These are just libc implementations, not actual OSes, and thus
 		# require a kernel.
 		# require a kernel.
-		echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+		echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
 		exit 1
 		exit 1
 		;;
 		;;
-	kfreebsd*-gnu* | kopensolaris*-gnu*)
+	-kernel*- )
+		echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
+		exit 1
 		;;
 		;;
-	vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+	*-kernel*- )
+		echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
+		exit 1
 		;;
 		;;
-	nto-qnx*)
+	*-msvc*- )
+		echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
+		exit 1
 		;;
 		;;
-	os2-emx)
+	kfreebsd*-gnu*- | kopensolaris*-gnu*-)
 		;;
 		;;
-	*-eabi* | *-gnueabi*)
+	vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
 		;;
 		;;
-	-*)
+	nto-qnx*-)
+		;;
+	os2-emx-)
+		;;
+	*-eabi*- | *-gnueabi*-)
+		;;
+	none--*)
+		# None (no kernel, i.e. freestanding / bare metal),
+		# can be paired with an machine code file format
+		;;
+	-*-)
 		# Blank kernel with real OS is always fine.
 		# Blank kernel with real OS is always fine.
 		;;
 		;;
-	*-*)
-		echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+	--*)
+		# Blank kernel and OS with real machine code file format is always fine.
+		;;
+	*-*-*)
+		echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
 		exit 1
 		exit 1
 		;;
 		;;
 esac
 esac
@@ -1879,7 +1949,7 @@ case $vendor in
 		;;
 		;;
 esac
 esac
 
 
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
 exit
 exit
 
 
 # Local variables:
 # Local variables:

+ 18 - 0
libs/SDL2/cmake/sdlchecks.cmake

@@ -905,6 +905,22 @@ macro(CheckOpenGLES)
   endif()
   endif()
 endmacro()
 endmacro()
 
 
+# Requires:
+# - EGL
+macro(CheckQNXScreen)
+  if(QNX AND HAVE_OPENGL_EGL)
+    check_c_source_compiles("
+        #include <screen/screen.h>
+        int main (int argc, char** argv) { return 0; }" HAVE_QNX_SCREEN)
+    if(HAVE_QNX_SCREEN)
+      set(SDL_VIDEO_DRIVER_QNX 1)
+      file(GLOB QNX_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/qnx/*.c)
+      list(APPEND SOURCE_FILES ${QNX_VIDEO_SOURCES})
+      list(APPEND EXTRA_LIBS screen EGL)
+    endif()
+  endif()
+endmacro()
+
 # Requires:
 # Requires:
 # - nada
 # - nada
 # Optional:
 # Optional:
@@ -955,6 +971,8 @@ macro(CheckPTHREAD)
     elseif(EMSCRIPTEN)
     elseif(EMSCRIPTEN)
       set(PTHREAD_CFLAGS "-D_REENTRANT -pthread")
       set(PTHREAD_CFLAGS "-D_REENTRANT -pthread")
       set(PTHREAD_LDFLAGS "-pthread")
       set(PTHREAD_LDFLAGS "-pthread")
+    elseif(QNX)
+      # pthread support is baked in
     else()
     else()
       set(PTHREAD_CFLAGS "-D_REENTRANT")
       set(PTHREAD_CFLAGS "-D_REENTRANT")
       set(PTHREAD_LDFLAGS "-lpthread")
       set(PTHREAD_LDFLAGS "-lpthread")

+ 4 - 0
libs/SDL2/cmake/sdlplatform.cmake

@@ -28,6 +28,8 @@ macro(SDL_DetectCMakePlatform)
       set(SDL_CMAKE_PLATFORM AIX)
       set(SDL_CMAKE_PLATFORM AIX)
     elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
     elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
       set(SDL_CMAKE_PLATFORM MINIX)
       set(SDL_CMAKE_PLATFORM MINIX)
+    elseif(CMAKE_SYSTEM_NAME MATCHES "QNX")
+      set(SDL_CMAKE_PLATFORM QNX)
     endif()
     endif()
   elseif(APPLE)
   elseif(APPLE)
     if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*")
     if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*")
@@ -48,6 +50,8 @@ macro(SDL_DetectCMakePlatform)
     set(SDL_CMAKE_PLATFORM HAIKU)
     set(SDL_CMAKE_PLATFORM HAIKU)
   elseif(NINTENDO_3DS)
   elseif(NINTENDO_3DS)
     set(SDL_CMAKE_PLATFORM N3DS)
     set(SDL_CMAKE_PLATFORM N3DS)
+  elseif(OS2)
+    set(SDL_CMAKE_PLATFORM OS2)
   endif()
   endif()
   if(SDL_CMAKE_PLATFORM)
   if(SDL_CMAKE_PLATFORM)
     set(${SDL_CMAKE_PLATFORM} TRUE)
     set(${SDL_CMAKE_PLATFORM} TRUE)

+ 4 - 42
libs/SDL2/configure

@@ -3507,7 +3507,7 @@ orig_CFLAGS="$CFLAGS"
 # See docs/release_checklist.md
 # See docs/release_checklist.md
 SDL_MAJOR_VERSION=2
 SDL_MAJOR_VERSION=2
 SDL_MINOR_VERSION=28
 SDL_MINOR_VERSION=28
-SDL_MICRO_VERSION=1
+SDL_MICRO_VERSION=4
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 
 SDL_BINARY_AGE=`expr $SDL_MINOR_VERSION \* 100 + $SDL_MICRO_VERSION`
 SDL_BINARY_AGE=`expr $SDL_MINOR_VERSION \* 100 + $SDL_MICRO_VERSION`
@@ -23026,41 +23026,6 @@ printf "%s\n" "$have_gcc_no_strict_aliasing" >&6; }
     fi
     fi
 }
 }
 
 
-CheckStackBoundary()
-{
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GCC -mpreferred-stack-boundary option" >&5
-printf %s "checking for GCC -mpreferred-stack-boundary option... " >&6; }
-    have_gcc_preferred_stack_boundary=no
-
-    save_CFLAGS="$CFLAGS"
-    CFLAGS="$save_CFLAGS -mpreferred-stack-boundary=2"
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-    int x = 0;
-
-int
-main (void)
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-  have_gcc_preferred_stack_boundary=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_gcc_preferred_stack_boundary" >&5
-printf "%s\n" "$have_gcc_preferred_stack_boundary" >&6; }
-    CFLAGS="$save_CFLAGS"
-
-    if test x$have_gcc_preferred_stack_boundary = xyes; then
-        EXTRA_CFLAGS="$EXTRA_CFLAGS -mpreferred-stack-boundary=2"
-    fi
-}
-
 CheckWerror()
 CheckWerror()
 {
 {
     # Check whether --enable-werror was given.
     # Check whether --enable-werror was given.
@@ -27474,9 +27439,6 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_wince" >&5
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_wince" >&5
 printf "%s\n" "$have_wince" >&6; }
 printf "%s\n" "$have_wince" >&6; }
 
 
-    # This fixes Windows stack alignment with newer GCC
-    CheckStackBoundary
-
     # headers needed elsewhere
     # headers needed elsewhere
     ac_fn_c_check_header_compile "$LINENO" "tpcshrd.h" "ac_cv_header_tpcshrd_h" "$ac_includes_default"
     ac_fn_c_check_header_compile "$LINENO" "tpcshrd.h" "ac_cv_header_tpcshrd_h" "$ac_includes_default"
 if test "x$ac_cv_header_tpcshrd_h" = xyes
 if test "x$ac_cv_header_tpcshrd_h" = xyes
@@ -28285,7 +28247,7 @@ fi
                 enable_hidapi_libusb=yes
                 enable_hidapi_libusb=yes
                 require_hidapi_libusb=yes
                 require_hidapi_libusb=yes
                 ;;
                 ;;
-           *-*-os2* )
+            *-*-os2* )
                 enable_hidapi_libusb=yes
                 enable_hidapi_libusb=yes
                 ;;
                 ;;
         esac
         esac
@@ -29678,7 +29640,7 @@ printf "%s\n" "#define SDL_VIDEO_DRIVER_OS2 1" >>confdefs.h
 
 
             SOURCES="$SOURCES $srcdir/src/video/os2/*.c"
             SOURCES="$SOURCES $srcdir/src/video/os2/*.c"
             have_video=yes
             have_video=yes
-            SUMMARY_video="${SUMMARY_video} os/2"
+            SUMMARY_video="${SUMMARY_video} OS/2"
         fi
         fi
         # Set up files for the audio library
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
         if test x$enable_audio = xyes; then
@@ -29687,7 +29649,7 @@ printf "%s\n" "#define SDL_AUDIO_DRIVER_OS2 1" >>confdefs.h
 
 
             SOURCES="$SOURCES $srcdir/src/audio/os2/*.c"
             SOURCES="$SOURCES $srcdir/src/audio/os2/*.c"
             have_audio=yes
             have_audio=yes
-            SUMMARY_audio="${SUMMARY_audio} os/2"
+            SUMMARY_audio="${SUMMARY_audio} OS/2"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmmpm2"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmmpm2"
         fi
         fi
         # Set up files for the thread library
         # Set up files for the thread library

+ 4 - 27
libs/SDL2/configure.ac

@@ -13,7 +13,7 @@ dnl Set various version strings - taken gratefully from the GTk sources
 # See docs/release_checklist.md
 # See docs/release_checklist.md
 SDL_MAJOR_VERSION=2
 SDL_MAJOR_VERSION=2
 SDL_MINOR_VERSION=28
 SDL_MINOR_VERSION=28
-SDL_MICRO_VERSION=1
+SDL_MICRO_VERSION=4
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 
 SDL_BINARY_AGE=`expr $SDL_MINOR_VERSION \* 100 + $SDL_MICRO_VERSION`
 SDL_BINARY_AGE=`expr $SDL_MINOR_VERSION \* 100 + $SDL_MICRO_VERSION`
@@ -1558,26 +1558,6 @@ CheckNoStrictAliasing()
     fi
     fi
 }
 }
 
 
-dnl See if GCC's -mpreferred-stack-boundary is supported.
-dnl  Reference: http://bugzilla.libsdl.org/show_bug.cgi?id=1296
-CheckStackBoundary()
-{
-    AC_MSG_CHECKING(for GCC -mpreferred-stack-boundary option)
-    have_gcc_preferred_stack_boundary=no
-
-    save_CFLAGS="$CFLAGS"
-    CFLAGS="$save_CFLAGS -mpreferred-stack-boundary=2"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-    int x = 0;
-    ]],[])], [have_gcc_preferred_stack_boundary=yes],[])
-    AC_MSG_RESULT($have_gcc_preferred_stack_boundary)
-    CFLAGS="$save_CFLAGS"
-
-    if test x$have_gcc_preferred_stack_boundary = xyes; then
-        EXTRA_CFLAGS="$EXTRA_CFLAGS -mpreferred-stack-boundary=2"
-    fi
-}
-
 dnl See if GCC's -Werror is supported.
 dnl See if GCC's -Werror is supported.
 CheckWerror()
 CheckWerror()
 {
 {
@@ -3306,9 +3286,6 @@ CheckWINDOWS()
     ],[])
     ],[])
     AC_MSG_RESULT($have_wince)
     AC_MSG_RESULT($have_wince)
 
 
-    # This fixes Windows stack alignment with newer GCC
-    CheckStackBoundary
-
     # headers needed elsewhere
     # headers needed elsewhere
     AC_CHECK_HEADER(tpcshrd.h,have_tpcshrd_h=yes)
     AC_CHECK_HEADER(tpcshrd.h,have_tpcshrd_h=yes)
     if test x$have_tpcshrd_h = xyes; then
     if test x$have_tpcshrd_h = xyes; then
@@ -3637,7 +3614,7 @@ CheckHIDAPI()
                 enable_hidapi_libusb=yes
                 enable_hidapi_libusb=yes
                 require_hidapi_libusb=yes
                 require_hidapi_libusb=yes
                 ;;
                 ;;
-           *-*-os2* )
+            *-*-os2* )
                 enable_hidapi_libusb=yes
                 enable_hidapi_libusb=yes
                 ;;
                 ;;
         esac
         esac
@@ -4648,14 +4625,14 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works.  --ryan.
             AC_DEFINE(SDL_VIDEO_DRIVER_OS2, 1, [ ])
             AC_DEFINE(SDL_VIDEO_DRIVER_OS2, 1, [ ])
             SOURCES="$SOURCES $srcdir/src/video/os2/*.c"
             SOURCES="$SOURCES $srcdir/src/video/os2/*.c"
             have_video=yes
             have_video=yes
-            SUMMARY_video="${SUMMARY_video} os/2"
+            SUMMARY_video="${SUMMARY_video} OS/2"
         fi
         fi
         # Set up files for the audio library
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
         if test x$enable_audio = xyes; then
             AC_DEFINE(SDL_AUDIO_DRIVER_OS2, 1, [ ])
             AC_DEFINE(SDL_AUDIO_DRIVER_OS2, 1, [ ])
             SOURCES="$SOURCES $srcdir/src/audio/os2/*.c"
             SOURCES="$SOURCES $srcdir/src/audio/os2/*.c"
             have_audio=yes
             have_audio=yes
-            SUMMARY_audio="${SUMMARY_audio} os/2"
+            SUMMARY_audio="${SUMMARY_audio} OS/2"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmmpm2"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmmpm2"
         fi
         fi
         # Set up files for the thread library
         # Set up files for the thread library

+ 7 - 7
libs/SDL2/docs/README-android.md

@@ -13,13 +13,13 @@ supported, but you can use the "android-project-ant" directory as a template.
 Requirements
 Requirements
 ================================================================================
 ================================================================================
 
 
-Android SDK (version 31 or later)
+Android SDK (version 34 or later)
 https://developer.android.com/sdk/index.html
 https://developer.android.com/sdk/index.html
 
 
 Android NDK r15c or later
 Android NDK r15c or later
 https://developer.android.com/tools/sdk/ndk/index.html
 https://developer.android.com/tools/sdk/ndk/index.html
 
 
-Minimum API level supported by SDL: 16 (Android 4.1)
+Minimum API level supported by SDL: 19 (Android 4.4)
 
 
 
 
 How the port works
 How the port works
@@ -431,13 +431,13 @@ The Tegra Graphics Debugger is available from NVidia here:
 https://developer.nvidia.com/tegra-graphics-debugger
 https://developer.nvidia.com/tegra-graphics-debugger
 
 
 
 
-Why is API level 16 the minimum required?
+Why is API level 19 the minimum required?
 ================================================================================
 ================================================================================
 
 
-The latest NDK toolchain doesn't support targeting earlier than API level 16.
-As of this writing, according to https://developer.android.com/about/dashboards/index.html
-about 99% of the Android devices accessing Google Play support API level 16 or
-higher (January 2018).
+The latest NDK toolchain doesn't support targeting earlier than API level 19.
+As of this writing, according to https://www.composables.com/tools/distribution-chart
+about 99.7% of the Android devices accessing Google Play support API level 19 or
+higher (August 2023).
 
 
 
 
 A note regarding the use of the "dirty rectangles" rendering technique
 A note regarding the use of the "dirty rectangles" rendering technique

+ 1 - 1
libs/SDL2/docs/README-cmake.md

@@ -48,7 +48,7 @@ SDL can be included in your project in 2 major ways:
 The following CMake script supports both, depending on the value of `MYGAME_VENDORED`.
 The following CMake script supports both, depending on the value of `MYGAME_VENDORED`.
 
 
 ```cmake
 ```cmake
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.5)
 project(mygame)
 project(mygame)
 
 
 # Create an option to switch between a system sdl library and a vendored sdl library
 # Create an option to switch between a system sdl library and a vendored sdl library

+ 1 - 1
libs/SDL2/docs/README-emscripten.md

@@ -38,7 +38,7 @@ for some Javascript code to steal for this approach.
 
 
 ## Building SDL/emscripten
 ## Building SDL/emscripten
 
 
-SDL currently requires at least Emscripten 2.0.32 to build. Newer versions
+SDL currently requires at least Emscripten 3.1.35 to build. Newer versions
 are likely to work, as well.
 are likely to work, as well.
 
 
 
 

+ 1 - 1
libs/SDL2/docs/README-os2.md

@@ -3,7 +3,7 @@ Simple DirectMedia Layer 2 for OS/2 & eComStation
 SDL port for OS/2, authored by Andrey Vasilkin <[email protected]>, 2016
 SDL port for OS/2, authored by Andrey Vasilkin <[email protected]>, 2016
 
 
 
 
-OpenGL and audio capture not supported by this port.
+OpenGL not supported by this port.
 
 
 Additional optional environment variables:
 Additional optional environment variables:
 
 

+ 2 - 0
libs/SDL2/include/SDL_assert.h

@@ -55,6 +55,8 @@ assert can have unique static variables associated with it.
     #define SDL_TriggerBreakpoint() __builtin_debugtrap()
     #define SDL_TriggerBreakpoint() __builtin_debugtrap()
 #elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
 #elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
     #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
     #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
+#elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv)
+    #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" )
 #elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) )  /* this might work on other ARM targets, but this is a known quantity... */
 #elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) )  /* this might work on other ARM targets, but this is a known quantity... */
     #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
     #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
 #elif defined(__APPLE__) && defined(__arm__)
 #elif defined(__APPLE__) && defined(__arm__)

+ 1 - 1
libs/SDL2/include/SDL_atomic.h

@@ -240,7 +240,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)();
 /* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
 /* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
     #define SDL_CPUPauseInstruction() __asm__ __volatile__("pause\n")  /* Some assemblers can't do REP NOP, so go with PAUSE. */
     #define SDL_CPUPauseInstruction() __asm__ __volatile__("pause\n")  /* Some assemblers can't do REP NOP, so go with PAUSE. */
-#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
+#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || defined(__aarch64__)
     #define SDL_CPUPauseInstruction() __asm__ __volatile__("yield" ::: "memory")
     #define SDL_CPUPauseInstruction() __asm__ __volatile__("yield" ::: "memory")
 #elif (defined(__powerpc__) || defined(__powerpc64__))
 #elif (defined(__powerpc__) || defined(__powerpc64__))
     #define SDL_CPUPauseInstruction() __asm__ __volatile__("or 27,27,27");
     #define SDL_CPUPauseInstruction() __asm__ __volatile__("or 27,27,27");

+ 2 - 0
libs/SDL2/include/SDL_config.h.cmake

@@ -262,6 +262,8 @@
 #cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@
 #cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@
 #cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@
 #cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@
 
 
+#cmakedefine USE_POSIX_SPAWN @USE_POSIX_SPAWN@
+
 /* SDL internal assertion support */
 /* SDL internal assertion support */
 #if @SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED@
 #if @SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED@
 #cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@
 #cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@

+ 20 - 0
libs/SDL2/include/SDL_hints.h

@@ -1007,6 +1007,15 @@ extern "C" {
   */
   */
 #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
 #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
 
 
+/**
+  *  \brief  A variable controlling whether Windows.Gaming.Input should be used for controller handling.
+  *
+  *  This variable can be set to the following values:
+  *    "0"       - WGI is not used
+  *    "1"       - WGI is used (the default)
+  */
+#define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI"
+
 /**
 /**
  * \brief Determines whether SDL enforces that DRM master is required in order
  * \brief Determines whether SDL enforces that DRM master is required in order
  *        to initialize the KMSDRM video backend.
  *        to initialize the KMSDRM video backend.
@@ -1465,6 +1474,17 @@ extern "C" {
  */
  */
 #define SDL_HINT_RENDER_VSYNC               "SDL_RENDER_VSYNC"
 #define SDL_HINT_RENDER_VSYNC               "SDL_RENDER_VSYNC"
 
 
+/**
+ *  \brief  A variable controlling whether the Metal render driver select low power device over default one
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - Use the prefered OS device
+ *    "1"       - Select a low power one
+ *
+ *  By default the prefered OS device is used.
+ */
+#define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"
+
 /**
 /**
  *  \brief  A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
  *  \brief  A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
  *
  *

+ 1 - 1
libs/SDL2/include/SDL_render.h

@@ -1890,7 +1890,7 @@ extern DECLSPEC void *SDLCALL SDL_RenderGetMetalLayer(SDL_Renderer * renderer);
  * Note that as of SDL 2.0.18, this will return NULL if Metal refuses to give
  * Note that as of SDL 2.0.18, this will return NULL if Metal refuses to give
  * SDL a drawable to render to, which might happen if the window is
  * SDL a drawable to render to, which might happen if the window is
  * hidden/minimized/offscreen. This doesn't apply to command encoders for
  * hidden/minimized/offscreen. This doesn't apply to command encoders for
- * render targets, just the window's backbacker. Check your return values!
+ * render targets, just the window's backbuffer. Check your return values!
  *
  *
  * \param renderer The renderer to query
  * \param renderer The renderer to query
  * \returns an `id<MTLRenderCommandEncoder>` on success, or NULL if the
  * \returns an `id<MTLRenderCommandEncoder>` on success, or NULL if the

+ 2 - 2
libs/SDL2/include/SDL_revision.h

@@ -1,7 +1,7 @@
 /* Generated by updaterev.sh, do not edit */
 /* Generated by updaterev.sh, do not edit */
 #ifdef SDL_VENDOR_INFO
 #ifdef SDL_VENDOR_INFO
-#define SDL_REVISION "SDL-release-2.28.1-0-g4761467b2 (" SDL_VENDOR_INFO ")"
+#define SDL_REVISION "SDL-release-2.28.4-0-gcc016b004 (" SDL_VENDOR_INFO ")"
 #else
 #else
-#define SDL_REVISION "SDL-release-2.28.1-0-g4761467b2"
+#define SDL_REVISION "SDL-release-2.28.4-0-gcc016b004"
 #endif
 #endif
 #define SDL_REVISION_NUMBER 0
 #define SDL_REVISION_NUMBER 0

+ 1 - 1
libs/SDL2/include/SDL_version.h

@@ -59,7 +59,7 @@ typedef struct SDL_version
 */
 */
 #define SDL_MAJOR_VERSION   2
 #define SDL_MAJOR_VERSION   2
 #define SDL_MINOR_VERSION   28
 #define SDL_MINOR_VERSION   28
-#define SDL_PATCHLEVEL      1
+#define SDL_PATCHLEVEL      4
 
 
 /**
 /**
  * Macro to determine SDL version program was compiled against.
  * Macro to determine SDL version program was compiled against.

+ 2 - 2
libs/SDL2/src/SDL.c

@@ -631,9 +631,9 @@ SDL_bool SDL_IsTablet(void)
 #if defined(__WIN32__)
 #if defined(__WIN32__)
 
 
 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
-/* Need to include DllMain() on Watcom C for some reason.. */
+/* FIXME: Still need to include DllMain() on Watcom C ? */
 
 
-BOOL APIENTRY _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 {
 {
     switch (ul_reason_for_call) {
     switch (ul_reason_for_call) {
     case DLL_PROCESS_ATTACH:
     case DLL_PROCESS_ATTACH:

+ 10 - 2
libs/SDL2/src/SDL_assert.c

@@ -42,7 +42,15 @@
 #endif
 #endif
 
 
 #if defined(__EMSCRIPTEN__)
 #if defined(__EMSCRIPTEN__)
-#include <emscripten.h>
+    #include <emscripten.h>
+    /* older Emscriptens don't have this, but we need to for wasm64 compatibility. */
+    #ifndef MAIN_THREAD_EM_ASM_PTR
+        #ifdef __wasm64__
+            #error You need to upgrade your Emscripten compiler to support wasm64
+        #else
+            #define MAIN_THREAD_EM_ASM_PTR MAIN_THREAD_EM_ASM_INT
+        #endif
+    #endif
 #endif
 #endif
 
 
 /* The size of the stack buffer to use for rendering assert messages. */
 /* The size of the stack buffer to use for rendering assert messages. */
@@ -251,7 +259,7 @@ static SDL_assert_state SDLCALL SDL_PromptAssertion(const SDL_assert_data *data,
         for (;;) {
         for (;;) {
             SDL_bool okay = SDL_TRUE;
             SDL_bool okay = SDL_TRUE;
             /* *INDENT-OFF* */ /* clang-format off */
             /* *INDENT-OFF* */ /* clang-format off */
-            char *buf = (char *) EM_ASM_INT({
+            char *buf = (char *) MAIN_THREAD_EM_ASM_PTR({
                 var str =
                 var str =
                     UTF8ToString($0) + '\n\n' +
                     UTF8ToString($0) + '\n\n' +
                     'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
                     'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';

+ 2 - 0
libs/SDL2/src/audio/emscripten/SDL_emscriptenaudio.c

@@ -197,6 +197,8 @@ static void EMSCRIPTENAUDIO_CloseDevice(_THIS)
 #endif
 #endif
 }
 }
 
 
+EM_JS_DEPS(sdlaudio, "$autoResumeAudioContext,$dynCall");
+
 static int EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
 static int EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
 {
 {
     SDL_AudioFormat test_format;
     SDL_AudioFormat test_format;

+ 220 - 69
libs/SDL2/src/audio/os2/SDL_os2audio.c

@@ -30,17 +30,12 @@
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_os2audio.h"
 #include "SDL_os2audio.h"
 
 
-/*
-void lockIncr(volatile int *piVal);
-#pragma aux lockIncr = \
-  "lock add [eax], 1 "\
-  parm [eax];
-
-void lockDecr(volatile int *piVal);
-#pragma aux lockDecr = \
-  "lock sub [eax], 1 "\
-  parm [eax];
-*/
+static PMCI_MIX_BUFFER _getNextBuffer(SDL_PrivateAudioData *pAData, PMCI_MIX_BUFFER pBuffer)
+{
+    PMCI_MIX_BUFFER pFirstBuffer = &pAData->aMixBuffers[0];
+    PMCI_MIX_BUFFER pLastBuffer = &pAData->aMixBuffers[pAData->cMixBuffers -1];
+    return (pBuffer == pLastBuffer ? pFirstBuffer : pBuffer+1);
+}
 
 
 static ULONG _getEnvULong(const char *name, ULONG ulMax, ULONG ulDefault)
 static ULONG _getEnvULong(const char *name, ULONG ulMax, ULONG ulDefault)
 {
 {
@@ -64,7 +59,7 @@ static int _MCIError(const char *func, ULONG ulResult)
 
 
 static void _mixIOError(const char *function, ULONG ulRC)
 static void _mixIOError(const char *function, ULONG ulRC)
 {
 {
-    debug_os2("%s() - failed, rc = 0x%X (%s)",
+    debug_os2("%s() - failed, rc = 0x%lX (%s)",
               function, ulRC,
               function, ulRC,
               (ulRC == MCIERR_INVALID_MODE)   ? "Mixer mode does not match request" :
               (ulRC == MCIERR_INVALID_MODE)   ? "Mixer mode does not match request" :
               (ulRC == MCIERR_INVALID_BUFFER) ? "Caller sent an invalid buffer"     : "unknown");
               (ulRC == MCIERR_INVALID_BUFFER) ? "Caller sent an invalid buffer"     : "unknown");
@@ -73,18 +68,33 @@ static void _mixIOError(const char *function, ULONG ulRC)
 static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
 static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
                                        ULONG ulFlags)
                                        ULONG ulFlags)
 {
 {
-    SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)pBuffer->ulUserParm;
+    SDL_AudioDevice      *_this = (SDL_AudioDevice *)pBuffer->ulUserParm;
+    SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     ULONG   ulRC;
     ULONG   ulRC;
 
 
+    debug_os2("cbAudioWriteEvent: ulStatus = %lu, pBuffer = %p, ulFlags = %#lX",ulStatus,pBuffer,ulFlags);
+
+    if (pAData->ulState == 2)
+    {
+        return 0;
+    }
+
     if (ulFlags != MIX_WRITE_COMPLETE) {
     if (ulFlags != MIX_WRITE_COMPLETE) {
-        debug_os2("flags = 0x%X", ulFlags);
+        debug_os2("flags = 0x%lX", ulFlags);
+        return 0;
+    }
+
+    pAData->pDrainBuffer = pBuffer;
+    ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
+                                           pAData->pDrainBuffer, 1);
+    if (ulRC != MCIERR_SUCCESS) {
+        _mixIOError("pmixWrite", ulRC);
         return 0;
         return 0;
     }
     }
 
 
-    /*lockDecr((int *)&pAData->ulQueuedBuf);*/
     ulRC = DosPostEventSem(pAData->hevBuf);
     ulRC = DosPostEventSem(pAData->hevBuf);
     if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
     if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
-        debug_os2("DosPostEventSem(), rc = %u", ulRC);
+        debug_os2("DosPostEventSem(), rc = %lu", ulRC);
     }
     }
 
 
     return 1; /* return value doesn't seem to matter. */
     return 1; /* return value doesn't seem to matter. */
@@ -93,19 +103,36 @@ static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
 static LONG APIENTRY cbAudioReadEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
 static LONG APIENTRY cbAudioReadEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
                                       ULONG ulFlags)
                                       ULONG ulFlags)
 {
 {
-    SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)pBuffer->ulUserParm;
+    SDL_AudioDevice      *_this = (SDL_AudioDevice *)pBuffer->ulUserParm;
+    SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     ULONG   ulRC;
     ULONG   ulRC;
 
 
+    debug_os2("cbAudioReadEvent: ulStatus = %lu, pBuffer = %p, ulFlags = %#lX",ulStatus,pBuffer,ulFlags);
+
+    if (pAData->ulState == 2)
+    {
+        return 0;
+    }
+
     if (ulFlags != MIX_READ_COMPLETE) {
     if (ulFlags != MIX_READ_COMPLETE) {
-        debug_os2("flags = 0x%X", ulFlags);
+        debug_os2("flags = 0x%lX", ulFlags);
         return 0;
         return 0;
     }
     }
 
 
-    pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle, pBuffer, 1);
+    pAData->pFillBuffer = pBuffer;
+    if (pAData->pFillBuffer == pAData->aMixBuffers)
+    {
+       ulRC = pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle,
+                                             pAData->pFillBuffer, pAData->cMixBuffers);
+       if (ulRC != MCIERR_SUCCESS) {
+           _mixIOError("pmixRead", ulRC);
+           return 0;
+       }
+    }
 
 
     ulRC = DosPostEventSem(pAData->hevBuf);
     ulRC = DosPostEventSem(pAData->hevBuf);
     if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
     if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
-        debug_os2("DosPostEventSem(), rc = %u", ulRC);
+        debug_os2("DosPostEventSem(), rc = %lu", ulRC);
     }
     }
 
 
     return 1;
     return 1;
@@ -120,31 +147,36 @@ static void OS2_DetectDevices(void)
     MCI_SYSINFO_LOGDEVICE   stLogDevice;
     MCI_SYSINFO_LOGDEVICE   stLogDevice;
     MCI_SYSINFO_PARMS       stSysInfoParams;
     MCI_SYSINFO_PARMS       stSysInfoParams;
     ULONG                   ulRC;
     ULONG                   ulRC;
-    ULONG                   ulHandle = 0;
+    ULONG                   ulNumber;
+    MCI_GETDEVCAPS_PARMS    stDevCapsParams;
+    MCI_OPEN_PARMS          stMCIOpen;
+    MCI_GENERIC_PARMS       stMCIGenericParams;
 
 
+    SDL_memset(&stMCISysInfo, 0, sizeof(stMCISysInfo));
     acBuf[0] = '\0';
     acBuf[0] = '\0';
     stMCISysInfo.pszReturn    = acBuf;
     stMCISysInfo.pszReturn    = acBuf;
     stMCISysInfo.ulRetSize    = sizeof(acBuf);
     stMCISysInfo.ulRetSize    = sizeof(acBuf);
     stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
     stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
     ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY,
     ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY,
                           &stMCISysInfo, 0);
                           &stMCISysInfo, 0);
-    if (ulRC != NO_ERROR) {
-        debug_os2("MCI_SYSINFO, MCI_SYSINFO_QUANTITY - failed, rc = 0x%X", ulRC);
+    if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+        debug_os2("MCI_SYSINFO, MCI_SYSINFO_QUANTITY - failed, rc = 0x%hX", LOUSHORT(ulRC));
         return;
         return;
     }
     }
 
 
     ulDevicesNum = SDL_strtoul(stMCISysInfo.pszReturn, NULL, 10);
     ulDevicesNum = SDL_strtoul(stMCISysInfo.pszReturn, NULL, 10);
 
 
-    for (stSysInfoParams.ulNumber = 0; stSysInfoParams.ulNumber < ulDevicesNum;
-         stSysInfoParams.ulNumber++) {
+    for (ulNumber = 1; ulNumber <= ulDevicesNum;
+         ulNumber++) {
         /* Get device install name. */
         /* Get device install name. */
+        stSysInfoParams.ulNumber     = ulNumber;
         stSysInfoParams.pszReturn    = acBuf;
         stSysInfoParams.pszReturn    = acBuf;
         stSysInfoParams.ulRetSize    = sizeof(acBuf);
         stSysInfoParams.ulRetSize    = sizeof(acBuf);
         stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
         stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
         ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
         ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
                               &stSysInfoParams, 0);
                               &stSysInfoParams, 0);
-        if (ulRC != NO_ERROR) {
-            debug_os2("MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME - failed, rc = 0x%X", ulRC);
+        if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+            debug_os2("MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME - failed, rc = 0x%hX", LOUSHORT(ulRC));
             continue;
             continue;
         }
         }
 
 
@@ -154,15 +186,45 @@ static void OS2_DetectDevices(void)
         SDL_strlcpy(stLogDevice.szInstallName, stSysInfoParams.pszReturn, MAX_DEVICE_NAME);
         SDL_strlcpy(stLogDevice.szInstallName, stSysInfoParams.pszReturn, MAX_DEVICE_NAME);
         ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM,
         ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM,
                               &stSysInfoParams, 0);
                               &stSysInfoParams, 0);
-        if (ulRC != NO_ERROR) {
-            debug_os2("MCI_SYSINFO, MCI_SYSINFO_ITEM - failed, rc = 0x%X", ulRC);
+        if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+            debug_os2("MCI_SYSINFO, MCI_SYSINFO_ITEM - failed, rc = 0x%hX", LOUSHORT(ulRC));
             continue;
             continue;
         }
         }
 
 
-        ulHandle++;
-        SDL_AddAudioDevice(0, stLogDevice.szProductInfo, NULL, (void *)(ulHandle));
-        ulHandle++;
-        SDL_AddAudioDevice(1, stLogDevice.szProductInfo, NULL, (void *)(ulHandle));
+        SDL_AddAudioDevice(0, stLogDevice.szProductInfo, NULL, (void *)ulNumber);
+
+        /* Open audio device for querying its capabilities */
+        /* at this point we HAVE TO OPEN the waveaudio device and not the ampmix device */
+        /* because only the waveaudio device (tied to the ampmix device) supports querying for playback/record capability */
+        SDL_memset(&stMCIOpen, 0, sizeof(stMCIOpen));
+        stMCIOpen.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_WAVEFORM_AUDIO,LOUSHORT(ulNumber));
+        ulRC = mciSendCommand(0, MCI_OPEN,MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,&stMCIOpen,  0);
+        if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+            debug_os2("MCI_OPEN (getDevCaps) - failed");
+            continue;
+        }
+
+        /* check for recording capability */
+        SDL_memset(&stDevCapsParams, 0, sizeof(stDevCapsParams));
+        stDevCapsParams.ulItem = MCI_GETDEVCAPS_CAN_RECORD;
+        ulRC = mciSendCommand(stMCIOpen.usDeviceID, MCI_GETDEVCAPS, MCI_WAIT | MCI_GETDEVCAPS_ITEM,
+                              &stDevCapsParams, 0);
+        if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+            debug_os2("MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM - failed, rc = 0x%hX", LOUSHORT(ulRC));
+        }
+        else {
+            if (stDevCapsParams.ulReturn) {
+                SDL_AddAudioDevice(1, stLogDevice.szProductInfo, NULL, (void *)(ulNumber | 0x80000000));
+            }
+        }
+
+        /* close the audio device, we are done querying its capabilities */
+        SDL_memset(&stMCIGenericParams, 0, sizeof(stMCIGenericParams));
+        ulRC = mciSendCommand(stMCIOpen.usDeviceID, MCI_CLOSE, MCI_WAIT,
+                              &stMCIGenericParams, 0);
+        if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+            debug_os2("MCI_CLOSE (getDevCaps) - failed");
+        }
     }
     }
 }
 }
 
 
@@ -171,52 +233,145 @@ static void OS2_WaitDevice(_THIS)
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     ULONG   ulRC;
     ULONG   ulRC;
 
 
+    debug_os2("Enter");
+
     /* Wait for an audio chunk to finish */
     /* Wait for an audio chunk to finish */
     ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
     ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
     if (ulRC != NO_ERROR) {
     if (ulRC != NO_ERROR) {
-        debug_os2("DosWaitEventSem(), rc = %u", ulRC);
+        debug_os2("DosWaitEventSem(), rc = %lu", ulRC);
     }
     }
 }
 }
 
 
 static Uint8 *OS2_GetDeviceBuf(_THIS)
 static Uint8 *OS2_GetDeviceBuf(_THIS)
 {
 {
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
-    return (Uint8 *) pAData->aMixBuffers[pAData->ulNextBuf].pBuffer;
+
+    debug_os2("Enter");
+
+    return (Uint8 *) pAData->pFillBuffer->pBuffer;
 }
 }
 
 
 static void OS2_PlayDevice(_THIS)
 static void OS2_PlayDevice(_THIS)
 {
 {
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     ULONG                 ulRC;
     ULONG                 ulRC;
-    PMCI_MIX_BUFFER       pMixBuffer = &pAData->aMixBuffers[pAData->ulNextBuf];
+    PMCI_MIX_BUFFER       pMixBuffer = NULL;
+
+    debug_os2("Enter");
+
+    pMixBuffer  = pAData->pDrainBuffer;
+    pAData->pFillBuffer = _getNextBuffer(pAData, pAData->pFillBuffer);
+    if (!pAData->ulState && pAData->pFillBuffer != pMixBuffer)
+    {
+        /*
+         * this buffer was filled but we have not yet filled all buffers
+         * so just signal event sem so that OS2_WaitDevice does not need
+         * to block
+         */
+        ulRC = DosPostEventSem(pAData->hevBuf);
+    }
 
 
-    /* Queue it up */
-    /*lockIncr((int *)&pAData->ulQueuedBuf);*/
-    ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
-                                           pMixBuffer, 1);
-    if (ulRC != MCIERR_SUCCESS) {
-        _mixIOError("pmixWrite", ulRC);
-    } else {
-        pAData->ulNextBuf = (pAData->ulNextBuf + 1) % pAData->cMixBuffers;
+    if (!pAData->ulState && (pAData->pFillBuffer == pMixBuffer) )
+    {
+        debug_os2("!hasStarted");
+        pAData->ulState = 1;
+
+        /* Write buffers to kick off the amp mixer */
+        ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
+                                               pMixBuffer, pAData->cMixBuffers);
+
+        if (ulRC != MCIERR_SUCCESS) {
+            _mixIOError("pmixWrite", ulRC);
+        }
     }
     }
 }
 }
 
 
+static int OS2_CaptureFromDevice(_THIS,void *buffer,int buflen)
+{
+    SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
+    ULONG                 ulRC;
+    PMCI_MIX_BUFFER       pMixBuffer = NULL;
+    int                   len = 0;
+
+    if (!pAData->ulState)
+    {
+        pAData->ulState = 1;
+        ulRC = pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle,
+                                              pAData->aMixBuffers, pAData->cMixBuffers);
+        if (ulRC != MCIERR_SUCCESS) {
+            _mixIOError("pmixRead", ulRC);
+            return -1;
+        }
+    }
+
+    /* Wait for an audio chunk to finish */
+    ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
+    if (ulRC != NO_ERROR)
+    {
+        debug_os2("DosWaitEventSem(), rc = %lu", ulRC);
+        return -1;
+    }
+
+    pMixBuffer = pAData->pDrainBuffer;
+    len = SDL_min((int)pMixBuffer->ulBufferLength, buflen);
+    SDL_memcpy(buffer,pMixBuffer->pBuffer, len);
+    pAData->pDrainBuffer = _getNextBuffer(pAData, pMixBuffer);
+
+    debug_os2("buflen = %u, ulBufferLength = %lu",buflen,pMixBuffer->ulBufferLength);
+
+    return len;
+}
+
+static void OS2_FlushCapture(_THIS)
+{
+    SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
+    ULONG                 ulIdx;
+
+    debug_os2("Enter");
+
+    /* Fill all device buffers with data */
+    for (ulIdx = 0; ulIdx < pAData->cMixBuffers; ulIdx++) {
+        pAData->aMixBuffers[ulIdx].ulFlags        = 0;
+        pAData->aMixBuffers[ulIdx].ulBufferLength = _this->spec.size;
+        pAData->aMixBuffers[ulIdx].ulUserParm     = (ULONG)_this;
+
+        SDL_memset(((PMCI_MIX_BUFFER)pAData->aMixBuffers)[ulIdx].pBuffer,
+                   _this->spec.silence, _this->spec.size);
+    }
+    pAData->pFillBuffer  = pAData->aMixBuffers;
+    pAData->pDrainBuffer = pAData->aMixBuffers;
+}
+
+
 static void OS2_CloseDevice(_THIS)
 static void OS2_CloseDevice(_THIS)
 {
 {
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
     MCI_GENERIC_PARMS     sMCIGenericParms;
     MCI_GENERIC_PARMS     sMCIGenericParms;
     ULONG                 ulRC;
     ULONG                 ulRC;
 
 
+    debug_os2("Enter");
+
     if (pAData == NULL)
     if (pAData == NULL)
         return;
         return;
 
 
+    pAData->ulState = 2;
+
     /* Close up audio */
     /* Close up audio */
     if (pAData->usDeviceId != (USHORT)~0) { /* Device is open. */
     if (pAData->usDeviceId != (USHORT)~0) { /* Device is open. */
+            SDL_zero(sMCIGenericParms);
+
+            ulRC = mciSendCommand(pAData->usDeviceId, MCI_STOP,
+                                  MCI_WAIT,
+                                  &sMCIGenericParms, 0);
+            if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+                debug_os2("MCI_STOP - failed" );
+            }
+
         if (pAData->stMCIMixSetup.ulBitsPerSample != 0) { /* Mixer was initialized. */
         if (pAData->stMCIMixSetup.ulBitsPerSample != 0) { /* Mixer was initialized. */
             ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
             ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
                                   MCI_WAIT | MCI_MIXSETUP_DEINIT,
                                   MCI_WAIT | MCI_MIXSETUP_DEINIT,
                                   &pAData->stMCIMixSetup, 0);
                                   &pAData->stMCIMixSetup, 0);
-            if (ulRC != MCIERR_SUCCESS) {
+            if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
                 debug_os2("MCI_MIXSETUP, MCI_MIXSETUP_DEINIT - failed");
                 debug_os2("MCI_MIXSETUP, MCI_MIXSETUP_DEINIT - failed");
             }
             }
         }
         }
@@ -230,14 +385,14 @@ static void OS2_CloseDevice(_THIS)
 
 
             ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
             ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
                                   MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0);
                                   MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0);
-            if (ulRC != MCIERR_SUCCESS) {
+            if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
                 debug_os2("MCI_BUFFER, MCI_DEALLOCATE_MEMORY - failed");
                 debug_os2("MCI_BUFFER, MCI_DEALLOCATE_MEMORY - failed");
             }
             }
         }
         }
 
 
         ulRC = mciSendCommand(pAData->usDeviceId, MCI_CLOSE, MCI_WAIT,
         ulRC = mciSendCommand(pAData->usDeviceId, MCI_CLOSE, MCI_WAIT,
                               &sMCIGenericParms, 0);
                               &sMCIGenericParms, 0);
-        if (ulRC != MCIERR_SUCCESS) {
+        if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
             debug_os2("MCI_CLOSE - failed");
             debug_os2("MCI_CLOSE - failed");
         }
         }
     }
     }
@@ -257,6 +412,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
     ULONG                 ulRC;
     ULONG                 ulRC;
     ULONG                 ulIdx;
     ULONG                 ulIdx;
     BOOL                  new_freq;
     BOOL                  new_freq;
+    ULONG                 ulHandle = (ULONG)_this->handle;
     SDL_bool              iscapture = _this->iscapture;
     SDL_bool              iscapture = _this->iscapture;
 
 
     new_freq = FALSE;
     new_freq = FALSE;
@@ -279,20 +435,21 @@ static int OS2_OpenDevice(_THIS, const char *devname)
 
 
     ulRC = DosCreateEventSem(NULL, &pAData->hevBuf, DCE_AUTORESET, TRUE);
     ulRC = DosCreateEventSem(NULL, &pAData->hevBuf, DCE_AUTORESET, TRUE);
     if (ulRC != NO_ERROR) {
     if (ulRC != NO_ERROR) {
-        debug_os2("DosCreateEventSem() failed, rc = %u", ulRC);
+        debug_os2("DosCreateEventSem() failed, rc = %lu", ulRC);
         return -1;
         return -1;
     }
     }
 
 
     /* Open audio device */
     /* Open audio device */
-    stMCIAmpOpen.usDeviceID = (_this->handle != NULL) ? ((ULONG)_this->handle - 1) : 0;
-    stMCIAmpOpen.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
+    stMCIAmpOpen.usDeviceID = 0;
+    stMCIAmpOpen.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX,LOUSHORT(ulHandle));
     ulRC = mciSendCommand(0, MCI_OPEN,
     ulRC = mciSendCommand(0, MCI_OPEN,
                           (_getEnvULong("SDL_AUDIO_SHARE", 1, 0) != 0)?
                           (_getEnvULong("SDL_AUDIO_SHARE", 1, 0) != 0)?
                            MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE :
                            MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE :
                            MCI_WAIT | MCI_OPEN_TYPE_ID,
                            MCI_WAIT | MCI_OPEN_TYPE_ID,
                           &stMCIAmpOpen,  0);
                           &stMCIAmpOpen,  0);
-    if (ulRC != MCIERR_SUCCESS) {
-        stMCIAmpOpen.usDeviceID = (USHORT)~0;
+    if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
+        DosCloseEventSem(pAData->hevBuf);
+        pAData->usDeviceId = (USHORT)~0;
         return _MCIError("MCI_OPEN", ulRC);
         return _MCIError("MCI_OPEN", ulRC);
     }
     }
     pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
     pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
@@ -355,7 +512,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
 
 
     ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
     ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
                           MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
                           MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
-    if (ulRC != MCIERR_SUCCESS && _this->spec.freq > 44100) {
+    if (LOUSHORT(ulRC) != MCIERR_SUCCESS && _this->spec.freq > 44100) {
         new_freq = TRUE;
         new_freq = TRUE;
         pAData->stMCIMixSetup.ulSamplesPerSec = 44100;
         pAData->stMCIMixSetup.ulSamplesPerSec = 44100;
         _this->spec.freq = 44100;
         _this->spec.freq = 44100;
@@ -363,7 +520,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
                               MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
                               MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
     }
     }
 
 
-    debug_os2("Setup mixer [BPS: %u, Freq.: %u, Channels: %u]: %s",
+    debug_os2("Setup mixer [BPS: %lu, Freq.: %lu, Channels: %lu]: %s",
               pAData->stMCIMixSetup.ulBitsPerSample,
               pAData->stMCIMixSetup.ulBitsPerSample,
               pAData->stMCIMixSetup.ulSamplesPerSec,
               pAData->stMCIMixSetup.ulSamplesPerSec,
               pAData->stMCIMixSetup.ulChannels,
               pAData->stMCIMixSetup.ulChannels,
@@ -394,29 +551,25 @@ static int OS2_OpenDevice(_THIS, const char *devname)
 
 
     ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
     ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
                           MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0);
                           MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0);
-    if (ulRC != MCIERR_SUCCESS) {
+    if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
         return _MCIError("MCI_BUFFER", ulRC);
         return _MCIError("MCI_BUFFER", ulRC);
     }
     }
     pAData->cMixBuffers = stMCIBuffer.ulNumBuffers;
     pAData->cMixBuffers = stMCIBuffer.ulNumBuffers;
     _this->spec.size = stMCIBuffer.ulBufferSize;
     _this->spec.size = stMCIBuffer.ulBufferSize;
 
 
+    debug_os2("%s, number of mix buffers: %lu",iscapture ? "capture": "play",pAData->cMixBuffers);
+
     /* Fill all device buffers with data */
     /* Fill all device buffers with data */
     for (ulIdx = 0; ulIdx < stMCIBuffer.ulNumBuffers; ulIdx++) {
     for (ulIdx = 0; ulIdx < stMCIBuffer.ulNumBuffers; ulIdx++) {
         pAData->aMixBuffers[ulIdx].ulFlags        = 0;
         pAData->aMixBuffers[ulIdx].ulFlags        = 0;
         pAData->aMixBuffers[ulIdx].ulBufferLength = stMCIBuffer.ulBufferSize;
         pAData->aMixBuffers[ulIdx].ulBufferLength = stMCIBuffer.ulBufferSize;
-        pAData->aMixBuffers[ulIdx].ulUserParm     = (ULONG)pAData;
+        pAData->aMixBuffers[ulIdx].ulUserParm     = (ULONG)_this;
 
 
         SDL_memset(((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulIdx].pBuffer,
         SDL_memset(((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulIdx].pBuffer,
                    _this->spec.silence, stMCIBuffer.ulBufferSize);
                    _this->spec.silence, stMCIBuffer.ulBufferSize);
     }
     }
-
-    /* Write buffers to kick off the amp mixer */
-    ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
-                                           pAData->aMixBuffers, 1);
-    if (ulRC != MCIERR_SUCCESS) {
-        _mixIOError("pmixWrite", ulRC);
-        return -1;
-    }
+    pAData->pFillBuffer  = pAData->aMixBuffers;
+    pAData->pDrainBuffer = pAData->aMixBuffers;
 
 
     return 0;
     return 0;
 }
 }
@@ -431,12 +584,10 @@ static SDL_bool OS2_Init(SDL_AudioDriverImpl * impl)
     impl->WaitDevice    = OS2_WaitDevice;
     impl->WaitDevice    = OS2_WaitDevice;
     impl->GetDeviceBuf  = OS2_GetDeviceBuf;
     impl->GetDeviceBuf  = OS2_GetDeviceBuf;
     impl->CloseDevice   = OS2_CloseDevice;
     impl->CloseDevice   = OS2_CloseDevice;
-
-    /* TODO: IMPLEMENT CAPTURE SUPPORT:
-    impl->CaptureFromDevice = ;
-    impl->FlushCapture = ;
+    impl->CaptureFromDevice = OS2_CaptureFromDevice ;
+    impl->FlushCapture = OS2_FlushCapture;
     impl->HasCaptureSupport = SDL_TRUE;
     impl->HasCaptureSupport = SDL_TRUE;
-    */
+
     return SDL_TRUE; /* this audio target is available. */
     return SDL_TRUE; /* this audio target is available. */
 }
 }
 
 

+ 3 - 2
libs/SDL2/src/audio/os2/SDL_os2audio.h

@@ -43,10 +43,11 @@ typedef struct SDL_PrivateAudioData
     BYTE                _pad[2];
     BYTE                _pad[2];
     MCI_MIXSETUP_PARMS  stMCIMixSetup;
     MCI_MIXSETUP_PARMS  stMCIMixSetup;
     HEV                 hevBuf;
     HEV                 hevBuf;
-    ULONG               ulNextBuf;
+    PMCI_MIX_BUFFER     pFillBuffer;
+    PMCI_MIX_BUFFER     pDrainBuffer;
+    ULONG               ulState;
     ULONG               cMixBuffers;
     ULONG               cMixBuffers;
     MCI_MIX_BUFFER      aMixBuffers[NUM_BUFFERS];
     MCI_MIX_BUFFER      aMixBuffers[NUM_BUFFERS];
-/*  ULONG               ulQueuedBuf;*/
 } SDL_PrivateAudioData;
 } SDL_PrivateAudioData;
 
 
 #endif /* SDL_os2mm_h_ */
 #endif /* SDL_os2mm_h_ */

+ 2 - 0
libs/SDL2/src/audio/qsa/SDL_qsa_audio.c

@@ -233,6 +233,7 @@ static Uint8 *QSA_GetDeviceBuf(_THIS)
 static void QSA_CloseDevice(_THIS)
 static void QSA_CloseDevice(_THIS)
 {
 {
     if (this->hidden->audio_handle != NULL) {
     if (this->hidden->audio_handle != NULL) {
+#if _NTO_VERSION < 710
         if (!this->iscapture) {
         if (!this->iscapture) {
             /* Finish playing available samples */
             /* Finish playing available samples */
             snd_pcm_plugin_flush(this->hidden->audio_handle,
             snd_pcm_plugin_flush(this->hidden->audio_handle,
@@ -242,6 +243,7 @@ static void QSA_CloseDevice(_THIS)
             snd_pcm_plugin_flush(this->hidden->audio_handle,
             snd_pcm_plugin_flush(this->hidden->audio_handle,
                                  SND_PCM_CHANNEL_CAPTURE);
                                  SND_PCM_CHANNEL_CAPTURE);
         }
         }
+#endif
         snd_pcm_close(this->hidden->audio_handle);
         snd_pcm_close(this->hidden->audio_handle);
     }
     }
 
 

+ 0 - 1
libs/SDL2/src/core/linux/SDL_fcitx.c

@@ -401,7 +401,6 @@ void SDL_Fcitx_SetFocus(SDL_bool focused)
 void SDL_Fcitx_Reset(void)
 void SDL_Fcitx_Reset(void)
 {
 {
     FcitxClientICCallMethod(&fcitx_client, "Reset");
     FcitxClientICCallMethod(&fcitx_client, "Reset");
-    FcitxClientICCallMethod(&fcitx_client, "CloseIC");
 }
 }
 
 
 SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
 SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)

+ 13 - 0
libs/SDL2/src/core/windows/SDL_windows.h

@@ -76,6 +76,19 @@
 #define WINVER       _WIN32_WINNT
 #define WINVER       _WIN32_WINNT
 #endif
 #endif
 
 
+/* See https://github.com/libsdl-org/SDL/pull/7607  */
+/* force_align_arg_pointer attribute requires gcc >= 4.2.x.  */
+#if defined(__clang__)
+#define HAVE_FORCE_ALIGN_ARG_POINTER
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+#define HAVE_FORCE_ALIGN_ARG_POINTER
+#endif
+#if defined(__GNUC__) && defined(__i386__) && defined(HAVE_FORCE_ALIGN_ARG_POINTER)
+#define MINGW32_FORCEALIGN __attribute__((force_align_arg_pointer))
+#else
+#define MINGW32_FORCEALIGN
+#endif
+
 #include <windows.h>
 #include <windows.h>
 #include <basetyps.h> /* for REFIID with broken mingw.org headers */
 #include <basetyps.h> /* for REFIID with broken mingw.org headers */
 
 

+ 24 - 7
libs/SDL2/src/events/SDL_keyboard.c

@@ -34,7 +34,8 @@
 /* Global keyboard information */
 /* Global keyboard information */
 
 
 #define KEYBOARD_HARDWARE    0x01
 #define KEYBOARD_HARDWARE    0x01
-#define KEYBOARD_AUTORELEASE 0x02
+#define KEYBOARD_VIRTUAL     0x02
+#define KEYBOARD_AUTORELEASE 0x04
 
 
 typedef struct SDL_Keyboard SDL_Keyboard;
 typedef struct SDL_Keyboard SDL_Keyboard;
 
 
@@ -47,6 +48,7 @@ struct SDL_Keyboard
     Uint8 keystate[SDL_NUM_SCANCODES];
     Uint8 keystate[SDL_NUM_SCANCODES];
     SDL_Keycode keymap[SDL_NUM_SCANCODES];
     SDL_Keycode keymap[SDL_NUM_SCANCODES];
     SDL_bool autorelease_pending;
     SDL_bool autorelease_pending;
+    Uint32 hardware_timestamp;
 };
 };
 
 
 static SDL_Keyboard SDL_keyboard;
 static SDL_Keyboard SDL_keyboard;
@@ -865,7 +867,9 @@ static int SDL_SendKeyboardKeyInternal(Uint8 source, Uint8 state, SDL_Scancode s
         keycode = keyboard->keymap[scancode];
         keycode = keyboard->keymap[scancode];
     }
     }
 
 
-    if (source == KEYBOARD_AUTORELEASE) {
+    if (source == KEYBOARD_HARDWARE) {
+        keyboard->hardware_timestamp = SDL_GetTicks();
+    } else if (source == KEYBOARD_AUTORELEASE) {
         keyboard->autorelease_pending = SDL_TRUE;
         keyboard->autorelease_pending = SDL_TRUE;
     }
     }
 
 
@@ -965,20 +969,25 @@ int SDL_SendKeyboardUnicodeKey(Uint32 ch)
 
 
     if (mod & KMOD_SHIFT) {
     if (mod & KMOD_SHIFT) {
         /* If the character uses shift, press shift down */
         /* If the character uses shift, press shift down */
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
+        SDL_SendKeyboardKeyInternal(KEYBOARD_VIRTUAL, SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN);
     }
     }
 
 
     /* Send a keydown and keyup for the character */
     /* Send a keydown and keyup for the character */
-    SDL_SendKeyboardKey(SDL_PRESSED, code);
-    SDL_SendKeyboardKey(SDL_RELEASED, code);
+    SDL_SendKeyboardKeyInternal(KEYBOARD_VIRTUAL, SDL_PRESSED, code, SDLK_UNKNOWN);
+    SDL_SendKeyboardKeyInternal(KEYBOARD_VIRTUAL, SDL_RELEASED, code, SDLK_UNKNOWN);
 
 
     if (mod & KMOD_SHIFT) {
     if (mod & KMOD_SHIFT) {
         /* If the character uses shift, release shift */
         /* If the character uses shift, release shift */
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
+        SDL_SendKeyboardKeyInternal(KEYBOARD_VIRTUAL, SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN);
     }
     }
     return 0;
     return 0;
 }
 }
 
 
+int SDL_SendVirtualKeyboardKey(Uint8 state, SDL_Scancode scancode)
+{
+    return SDL_SendKeyboardKeyInternal(KEYBOARD_VIRTUAL, state, scancode, SDLK_UNKNOWN);
+}
+
 int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
 int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
 {
 {
     return SDL_SendKeyboardKeyInternal(KEYBOARD_HARDWARE, state, scancode, SDLK_UNKNOWN);
     return SDL_SendKeyboardKeyInternal(KEYBOARD_HARDWARE, state, scancode, SDLK_UNKNOWN);
@@ -1007,6 +1016,13 @@ void SDL_ReleaseAutoReleaseKeys(void)
         }
         }
         keyboard->autorelease_pending = SDL_FALSE;
         keyboard->autorelease_pending = SDL_FALSE;
     }
     }
+
+    if (keyboard->hardware_timestamp) {
+        /* Keep hardware keyboard "active" for 250 ms */
+        if (SDL_TICKS_PASSED(SDL_GetTicks(), keyboard->hardware_timestamp + 250)) {
+            keyboard->hardware_timestamp = 0;
+        }
+    }
 }
 }
 
 
 SDL_bool SDL_HardwareKeyboardKeyPressed(void)
 SDL_bool SDL_HardwareKeyboardKeyPressed(void)
@@ -1019,7 +1035,8 @@ SDL_bool SDL_HardwareKeyboardKeyPressed(void)
             return SDL_TRUE;
             return SDL_TRUE;
         }
         }
     }
     }
-    return SDL_FALSE;
+
+    return keyboard->hardware_timestamp ? SDL_TRUE : SDL_FALSE;
 }
 }
 
 
 int SDL_SendKeyboardText(const char *text)
 int SDL_SendKeyboardText(const char *text)

+ 3 - 0
libs/SDL2/src/events/SDL_keyboard_c.h

@@ -52,6 +52,9 @@ extern void SDL_SetKeyboardFocus(SDL_Window *window);
  */
  */
 extern int SDL_SendKeyboardUnicodeKey(Uint32 ch);
 extern int SDL_SendKeyboardUnicodeKey(Uint32 ch);
 
 
+/* Send a key from a virtual key source, like an on-screen keyboard */
+extern int SDL_SendVirtualKeyboardKey(Uint8 state, SDL_Scancode scancode);
+
 /* Send a keyboard key event */
 /* Send a keyboard key event */
 extern int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode);
 extern int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode);
 extern int SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode);
 extern int SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode);

+ 2 - 2
libs/SDL2/src/file/SDL_rwops.c

@@ -648,7 +648,7 @@ SDL_RWops *SDL_RWFromMem(void *mem, int size)
         SDL_InvalidParamError("mem");
         SDL_InvalidParamError("mem");
         return rwops;
         return rwops;
     }
     }
-    if (!size) {
+    if (size <= 0) {
         SDL_InvalidParamError("size");
         SDL_InvalidParamError("size");
         return rwops;
         return rwops;
     }
     }
@@ -675,7 +675,7 @@ SDL_RWops *SDL_RWFromConstMem(const void *mem, int size)
         SDL_InvalidParamError("mem");
         SDL_InvalidParamError("mem");
         return rwops;
         return rwops;
     }
     }
-    if (!size) {
+    if (size <= 0) {
         SDL_InvalidParamError("size");
         SDL_InvalidParamError("size");
         return rwops;
         return rwops;
     }
     }

+ 3 - 3
libs/SDL2/src/hidapi/linux/hid.c

@@ -884,9 +884,9 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
 	unsigned char report = data[0];
 	unsigned char report = data[0];
 
 
 	res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
 	res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
-	if (res < 0)
-		perror("ioctl (GFEATURE)");
-	else if (dev->needs_ble_hack) {
+	if (res < 0) {
+		/* perror("ioctl (GFEATURE)"); */
+	} else if (dev->needs_ble_hack) {
 		/* Versions of BlueZ before 5.56 don't include the report in the data,
 		/* Versions of BlueZ before 5.56 don't include the report in the data,
 		 * and versions of BlueZ >= 5.56 include 2 copies of the report.
 		 * and versions of BlueZ >= 5.56 include 2 copies of the report.
 		 * We'll fix it so that there is a single copy of the report in both cases
 		 * We'll fix it so that there is a single copy of the report in both cases

+ 1 - 0
libs/SDL2/src/joystick/SDL_gamecontroller.c

@@ -586,6 +586,7 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
         switch (guid.data[15]) {
         switch (guid.data[15]) {
         case k_eSwitchDeviceInfoControllerType_HVCLeft:
         case k_eSwitchDeviceInfoControllerType_HVCLeft:
             SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string));
             SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,", sizeof(mapping_string));
+            break;
         case k_eSwitchDeviceInfoControllerType_HVCRight:
         case k_eSwitchDeviceInfoControllerType_HVCRight:
             SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,", sizeof(mapping_string));
             SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,", sizeof(mapping_string));
             break;
             break;

+ 4 - 10
libs/SDL2/src/joystick/SDL_gamecontrollerdb.h

@@ -134,9 +134,7 @@ static const char *s_ControllerMappings[] = {
     "03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,",
     "03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,",
     "03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
     "030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
-    "03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,", /* Bluetooth */
-    "03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,", /* Dongle */
-    "03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", /* Wired */
+    "03000000790000000600000000000000,G-Shark GS-GP702,crc:8e4f,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
     "030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
     "03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
     "03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
     "03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
@@ -416,9 +414,6 @@ static const char *s_ControllerMappings[] = {
     "03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,",
     "03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,",
     "030000000d0f00008400000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "030000000d0f00008400000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "030000000d0f00008500000000010000,Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
-    "03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,", /* Bluetooth */
-    "03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", /* Dongle */
-    "03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", /* Wired */
     "03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
     "03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
     "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
     "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
     "03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
@@ -610,9 +605,6 @@ static const char *s_ControllerMappings[] = {
     "050000004c050000f20d000000010000,DualSense Edge Wireless Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "050000004c050000f20d000000010000,DualSense Edge Wireless Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
     "03000000790000001100000010010000,Elecom Gamepad,crc:e86c,a:b2,b:b3,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b0,y:b1,",
     "03000000790000001100000010010000,Elecom Gamepad,crc:e86c,a:b2,b:b3,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b0,y:b1,",
-    "03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", /* Dongle */
-    "03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", /* Wired */
-    "05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", /* Bluetooth */
     "0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,",
     "0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,",
     "0500000047532067616d657061640000,GS Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
     "0500000047532067616d657061640000,GS Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
     "03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
     "03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
@@ -824,6 +816,7 @@ static const char *s_ControllerMappings[] = {
     "05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
     "05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
     "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
     "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
     "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
     "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
+    "03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,",
     "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,",
     "03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,",
     "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
     "0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
     "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b6,leftstick:b13,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:+a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
     "05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b6,leftstick:b13,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:+a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
@@ -856,6 +849,8 @@ static const char *s_ControllerMappings[] = {
     "0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,",
     "0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,",
     "030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),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,",
     "030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),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,",
     "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
     "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
+    "050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
     "05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,",
     "05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,",
     "03000000c0160000e105000010010000,Xin-Mo Dual Arcade,crc:82d5,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */
     "03000000c0160000e105000010010000,Xin-Mo Dual Arcade,crc:82d5,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */
     "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
@@ -907,7 +902,6 @@ static const char *s_ControllerMappings[] = {
     "05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
     "05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
     "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
     "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b0,b:b1,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
     "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
     "05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
-    "05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
     "05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,",
     "05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,",
     "0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
     "0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
     "05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
     "05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",

+ 15 - 1
libs/SDL2/src/joystick/SDL_joystick.c

@@ -1906,7 +1906,7 @@ void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *prod
         if (crc16) {
         if (crc16) {
             *crc16 = SDL_SwapLE16(guid16[1]);
             *crc16 = SDL_SwapLE16(guid16[1]);
         }
         }
-    } else if (bus < ' ') {
+    } else if (bus < ' ' || bus == SDL_HARDWARE_BUS_VIRTUAL) {
         /* This GUID fits the unknown VID/PID form:
         /* This GUID fits the unknown VID/PID form:
          * 16-bit bus
          * 16-bit bus
          * 16-bit CRC16 of the joystick name (can be zero)
          * 16-bit CRC16 of the joystick name (can be zero)
@@ -2479,8 +2479,11 @@ static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
         MAKE_VIDPID(0x046d, 0xc262), /* Logitech G920 (active mode) */
         MAKE_VIDPID(0x046d, 0xc262), /* Logitech G920 (active mode) */
         MAKE_VIDPID(0x046d, 0xc268), /* Logitech PRO Racing Wheel (PC mode) */
         MAKE_VIDPID(0x046d, 0xc268), /* Logitech PRO Racing Wheel (PC mode) */
         MAKE_VIDPID(0x046d, 0xc269), /* Logitech PRO Racing Wheel (PS4/PS5 mode) */
         MAKE_VIDPID(0x046d, 0xc269), /* Logitech PRO Racing Wheel (PS4/PS5 mode) */
+        MAKE_VIDPID(0x046d, 0xc272), /* Logitech PRO Racing Wheel for Xbox (PC mode) */
         MAKE_VIDPID(0x046d, 0xc26d), /* Logitech G923 (Xbox) */
         MAKE_VIDPID(0x046d, 0xc26d), /* Logitech G923 (Xbox) */
         MAKE_VIDPID(0x046d, 0xc26e), /* Logitech G923 */
         MAKE_VIDPID(0x046d, 0xc26e), /* Logitech G923 */
+        MAKE_VIDPID(0x046d, 0xc266), /* Logitech G923 for Playstation 4 and PC (PC mode) */
+        MAKE_VIDPID(0x046d, 0xc267), /* Logitech G923 for Playstation 4 and PC (PS4 mode)*/
         MAKE_VIDPID(0x046d, 0xca03), /* Logitech Momo Racing */
         MAKE_VIDPID(0x046d, 0xca03), /* Logitech Momo Racing */
         MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */
         MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */
         MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */
         MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */
@@ -2492,6 +2495,17 @@ static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
         MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */
         MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */
         MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */
         MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */
         MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */
         MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */
+        MAKE_VIDPID(0x0483, 0x0522), /* Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U) */
+        MAKE_VIDPID(0x0eb7, 0x0001), /* Fanatec ClubSport Wheel Base V2 */
+        MAKE_VIDPID(0x0eb7, 0x0004), /* Fanatec ClubSport Wheel Base V2.5 */
+        MAKE_VIDPID(0x0eb7, 0x0005), /* Fanatec CSL Elite Wheel Base+ (PS4) */
+        MAKE_VIDPID(0x0eb7, 0x0006), /* Fanatec Podium Wheel Base DD1 */
+        MAKE_VIDPID(0x0eb7, 0x0007), /* Fanatec Podium Wheel Base DD2 */
+        MAKE_VIDPID(0x0eb7, 0x0011), /* Fanatec Forza Motorsport (CSR Wheel / CSR Elite Wheel) */
+        MAKE_VIDPID(0x0eb7, 0x0020), /* Fanatec generic wheel / CSL DD / GT DD Pro */
+        MAKE_VIDPID(0x0eb7, 0x0197), /* Fanatec Porsche Wheel (Turbo / GT3 RS / Turbo S / GT3 V2 / GT2) */
+        MAKE_VIDPID(0x0eb7, 0x038e), /* Fanatec ClubSport Wheel Base V1 */
+        MAKE_VIDPID(0x0eb7, 0x0e03), /* Fanatec CSL Elite Wheel Base */
         MAKE_VIDPID(0x11ff, 0x0511), /* DragonRise Inc. Wired Wheel (initial mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */
         MAKE_VIDPID(0x11ff, 0x0511), /* DragonRise Inc. Wired Wheel (initial mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */
     };
     };
     int i;
     int i;

+ 87 - 76
libs/SDL2/src/joystick/hidapi/SDL_hidapi_ps4.c

@@ -320,81 +320,83 @@ static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
     SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", device->is_bluetooth ? "TRUE" : "FALSE");
     SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", device->is_bluetooth ? "TRUE" : "FALSE");
 #endif
 #endif
 
 
-    size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data));
-    /* Get the device capabilities */
-    if (size == 48 && data[2] == 0x27) {
-        Uint8 capabilities = data[4];
-        Uint8 device_type = data[5];
-        Uint16 gyro_numerator = LOAD16(data[10], data[11]);
-        Uint16 gyro_denominator = LOAD16(data[12], data[13]);
-        Uint16 accel_numerator = LOAD16(data[14], data[15]);
-        Uint16 accel_denominator = LOAD16(data[16], data[17]);
-
-#ifdef DEBUG_PS4_PROTOCOL
-        HIDAPI_DumpPacket("PS4 capabilities: size = %d", data, size);
-#endif
-        if (capabilities & 0x02) {
-            ctx->sensors_supported = SDL_TRUE;
-        }
-        if (capabilities & 0x04) {
-            ctx->lightbar_supported = SDL_TRUE;
-        }
-        if (capabilities & 0x08) {
-            ctx->vibration_supported = SDL_TRUE;
-        }
-        if (capabilities & 0x40) {
-            ctx->touchpad_supported = SDL_TRUE;
-        }
-
-        switch (device_type) {
-        case 0x00:
-            joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
-            break;
-        case 0x01:
-            joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
-            break;
-        case 0x02:
-            joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
-            break;
-        case 0x04:
-            joystick_type = SDL_JOYSTICK_TYPE_DANCE_PAD;
-            break;
-        case 0x06:
-            joystick_type = SDL_JOYSTICK_TYPE_WHEEL;
-            break;
-        case 0x07:
-            joystick_type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
-            break;
-        case 0x08:
-            joystick_type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
-            break;
-        default:
-            joystick_type = SDL_JOYSTICK_TYPE_UNKNOWN;
-            break;
-        }
-
-        if (gyro_numerator && gyro_denominator) {
-            ctx->gyro_numerator = gyro_numerator;
-            ctx->gyro_denominator = gyro_denominator;
-        }
-        if (accel_numerator && accel_denominator) {
-            ctx->accel_numerator = accel_numerator;
-            ctx->accel_denominator = accel_denominator;
-        }
-    } else if (device->vendor_id == USB_VENDOR_SONY) {
+    if (device->vendor_id == USB_VENDOR_SONY) {
         ctx->official_controller = SDL_TRUE;
         ctx->official_controller = SDL_TRUE;
         ctx->sensors_supported = SDL_TRUE;
         ctx->sensors_supported = SDL_TRUE;
         ctx->lightbar_supported = SDL_TRUE;
         ctx->lightbar_supported = SDL_TRUE;
         ctx->vibration_supported = SDL_TRUE;
         ctx->vibration_supported = SDL_TRUE;
         ctx->touchpad_supported = SDL_TRUE;
         ctx->touchpad_supported = SDL_TRUE;
-    } else if (device->vendor_id == USB_VENDOR_RAZER) {
-        /* The Razer Raiju doesn't respond to the detection protocol, but has a touchpad and vibration */
-        ctx->vibration_supported = SDL_TRUE;
-        ctx->touchpad_supported = SDL_TRUE;
+    } else {
+        size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data));
+        /* Get the device capabilities */
+        if (size == 48 && data[2] == 0x27) {
+            Uint8 capabilities = data[4];
+            Uint8 device_type = data[5];
+            Uint16 gyro_numerator = LOAD16(data[10], data[11]);
+            Uint16 gyro_denominator = LOAD16(data[12], data[13]);
+            Uint16 accel_numerator = LOAD16(data[14], data[15]);
+            Uint16 accel_denominator = LOAD16(data[16], data[17]);
 
 
-        if (device->product_id == USB_PRODUCT_RAZER_TOURNAMENT_EDITION_BLUETOOTH ||
-            device->product_id == USB_PRODUCT_RAZER_ULTIMATE_EDITION_BLUETOOTH) {
-            device->is_bluetooth = SDL_TRUE;
+#ifdef DEBUG_PS4_PROTOCOL
+            HIDAPI_DumpPacket("PS4 capabilities: size = %d", data, size);
+#endif
+            if (capabilities & 0x02) {
+                ctx->sensors_supported = SDL_TRUE;
+            }
+            if (capabilities & 0x04) {
+                ctx->lightbar_supported = SDL_TRUE;
+            }
+            if (capabilities & 0x08) {
+                ctx->vibration_supported = SDL_TRUE;
+            }
+            if (capabilities & 0x40) {
+                ctx->touchpad_supported = SDL_TRUE;
+            }
+
+            switch (device_type) {
+            case 0x00:
+                joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
+                break;
+            case 0x01:
+                joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
+                break;
+            case 0x02:
+                joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
+                break;
+            case 0x04:
+                joystick_type = SDL_JOYSTICK_TYPE_DANCE_PAD;
+                break;
+            case 0x06:
+                joystick_type = SDL_JOYSTICK_TYPE_WHEEL;
+                break;
+            case 0x07:
+                joystick_type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
+                break;
+            case 0x08:
+                joystick_type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
+                break;
+            default:
+                joystick_type = SDL_JOYSTICK_TYPE_UNKNOWN;
+                break;
+            }
+
+            if (gyro_numerator && gyro_denominator) {
+                ctx->gyro_numerator = gyro_numerator;
+                ctx->gyro_denominator = gyro_denominator;
+            }
+            if (accel_numerator && accel_denominator) {
+                ctx->accel_numerator = accel_numerator;
+                ctx->accel_denominator = accel_denominator;
+            }
+        } else if (device->vendor_id == USB_VENDOR_RAZER) {
+            /* The Razer Raiju doesn't respond to the detection protocol, but has a touchpad and vibration */
+            ctx->vibration_supported = SDL_TRUE;
+            ctx->touchpad_supported = SDL_TRUE;
+
+            if (device->product_id == USB_PRODUCT_RAZER_TOURNAMENT_EDITION_BLUETOOTH ||
+                device->product_id == USB_PRODUCT_RAZER_ULTIMATE_EDITION_BLUETOOTH) {
+                device->is_bluetooth = SDL_TRUE;
+            }
         }
         }
     }
     }
     ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported);
     ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported);
@@ -660,16 +662,25 @@ static int HIDAPI_DriverPS4_UpdateEffects(SDL_HIDAPI_Device *device)
 
 
 static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
 static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
 {
 {
-    /* This is just a dummy packet that should have no effect, since we don't set the CRC */
-    Uint8 data[78];
+    SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
 
 
-    SDL_zeroa(data);
+    if (ctx->enhanced_mode) {
+        /* This is just a dummy packet that should have no effect, since we don't set the CRC */
+        Uint8 data[78];
 
 
-    data[0] = k_EPS4ReportIdBluetoothEffects;
-    data[1] = 0xC0; /* Magic value HID + CRC */
+        SDL_zeroa(data);
+
+        data[0] = k_EPS4ReportIdBluetoothEffects;
+        data[1] = 0xC0; /* Magic value HID + CRC */
 
 
-    if (SDL_HIDAPI_LockRumble() == 0) {
-        SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
+        if (SDL_HIDAPI_LockRumble() == 0) {
+            SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
+        }
+    } else {
+        /* We can't even send an invalid effects packet, or it will put the controller in enhanced mode */
+        if (device->num_joysticks > 0) {
+            HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
+        }
     }
     }
 }
 }
 
 

+ 122 - 81
libs/SDL2/src/joystick/hidapi/SDL_hidapi_ps5.c

@@ -102,7 +102,7 @@ typedef struct
     Uint8 rgucAccelX[2];          /* 21 */
     Uint8 rgucAccelX[2];          /* 21 */
     Uint8 rgucAccelY[2];          /* 23 */
     Uint8 rgucAccelY[2];          /* 23 */
     Uint8 rgucAccelZ[2];          /* 25 */
     Uint8 rgucAccelZ[2];          /* 25 */
-    Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */
+    Uint8 rgucSensorTimestamp[4]; /* 27 - 16/32 bit little endian */
 
 
 } PS5StatePacketCommon_t;
 } PS5StatePacketCommon_t;
 
 
@@ -154,7 +154,9 @@ typedef struct
     Uint8 rgucAccelX[2];          /* 21 */
     Uint8 rgucAccelX[2];          /* 21 */
     Uint8 rgucAccelY[2];          /* 23 */
     Uint8 rgucAccelY[2];          /* 23 */
     Uint8 rgucAccelZ[2];          /* 25 */
     Uint8 rgucAccelZ[2];          /* 25 */
-    Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */
+    Uint8 rgucSensorTimestamp[2]; /* 27 - 16 bit little endian */
+    Uint8 ucBatteryLevel;         /* 29 */
+    Uint8 ucUnknown;              /* 30 */
     Uint8 ucTouchpadCounter1;     /* 31 - high bit clear + counter */
     Uint8 ucTouchpadCounter1;     /* 31 - high bit clear + counter */
     Uint8 rgucTouchpadData1[3];   /* 32 - X/Y, 12 bits per axis */
     Uint8 rgucTouchpadData1[3];   /* 32 - X/Y, 12 bits per axis */
     Uint8 ucTouchpadCounter2;     /* 35 - high bit clear + counter */
     Uint8 ucTouchpadCounter2;     /* 35 - high bit clear + counter */
@@ -421,7 +423,6 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
         }
         }
     }
     }
 
 
-    size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data));
     /* Get the device capabilities */
     /* Get the device capabilities */
     if (device->vendor_id == USB_VENDOR_SONY) {
     if (device->vendor_id == USB_VENDOR_SONY) {
         ctx->sensors_supported = SDL_TRUE;
         ctx->sensors_supported = SDL_TRUE;
@@ -429,61 +430,66 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
         ctx->vibration_supported = SDL_TRUE;
         ctx->vibration_supported = SDL_TRUE;
         ctx->playerled_supported = SDL_TRUE;
         ctx->playerled_supported = SDL_TRUE;
         ctx->touchpad_supported = SDL_TRUE;
         ctx->touchpad_supported = SDL_TRUE;
-    } else if (size == 48 && data[2] == 0x28) {
-        Uint8 capabilities = data[4];
-        Uint8 capabilities2 = data[20];
-        Uint8 device_type = data[5];
+    } else {
+        /* Third party controller capability request */
+        size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data));
+        if (size == 48 && data[2] == 0x28) {
+            Uint8 capabilities = data[4];
+            Uint8 capabilities2 = data[20];
+            Uint8 device_type = data[5];
 
 
 #ifdef DEBUG_PS5_PROTOCOL
 #ifdef DEBUG_PS5_PROTOCOL
-        HIDAPI_DumpPacket("PS5 capabilities: size = %d", data, size);
+            HIDAPI_DumpPacket("PS5 capabilities: size = %d", data, size);
 #endif
 #endif
-        if (capabilities & 0x02) {
+            if (capabilities & 0x02) {
+                ctx->sensors_supported = SDL_TRUE;
+            }
+            if (capabilities & 0x04) {
+                ctx->lightbar_supported = SDL_TRUE;
+            }
+            if (capabilities & 0x08) {
+                ctx->vibration_supported = SDL_TRUE;
+            }
+            if (capabilities & 0x40) {
+                ctx->touchpad_supported = SDL_TRUE;
+            }
+            if (capabilities2 & 0x80) {
+                ctx->playerled_supported = SDL_TRUE;
+            }
+
+            switch (device_type) {
+            case 0x00:
+                joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
+                break;
+            case 0x01:
+                joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
+                break;
+            case 0x02:
+                joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
+                break;
+            case 0x06:
+                joystick_type = SDL_JOYSTICK_TYPE_WHEEL;
+                break;
+            case 0x07:
+                joystick_type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
+                break;
+            case 0x08:
+                joystick_type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
+                break;
+            default:
+                joystick_type = SDL_JOYSTICK_TYPE_UNKNOWN;
+                break;
+            }
+
+            ctx->use_alternate_report = SDL_TRUE;
+        } else if (device->vendor_id == USB_VENDOR_RAZER &&
+                   (device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRED ||
+                    device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRELESS)) {
+            /* The Razer Wolverine V2 Pro doesn't respond to the detection protocol, but has a touchpad and sensors, but no vibration */
             ctx->sensors_supported = SDL_TRUE;
             ctx->sensors_supported = SDL_TRUE;
-        }
-        if (capabilities & 0x04) {
-            ctx->lightbar_supported = SDL_TRUE;
-        }
-        if (capabilities & 0x08) {
-            ctx->vibration_supported = SDL_TRUE;
-        }
-        if (capabilities & 0x40) {
             ctx->touchpad_supported = SDL_TRUE;
             ctx->touchpad_supported = SDL_TRUE;
+            ctx->use_alternate_report = SDL_TRUE;
         }
         }
-        if (capabilities2 & 0x80) {
-            ctx->playerled_supported = SDL_TRUE;
-        }
-
-        switch (device_type) {
-        case 0x00:
-            joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
-            break;
-        case 0x01:
-            joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
-            break;
-        case 0x02:
-            joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
-            break;
-        case 0x06:
-            joystick_type = SDL_JOYSTICK_TYPE_WHEEL;
-            break;
-        case 0x07:
-            joystick_type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
-            break;
-        case 0x08:
-            joystick_type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
-            break;
-        default:
-            joystick_type = SDL_JOYSTICK_TYPE_UNKNOWN;
-            break;
-        }
-
-        ctx->use_alternate_report = SDL_TRUE;
-    } else if (device->vendor_id == USB_VENDOR_RAZER &&
-               (device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRED ||
-                device->product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRELESS)) {
-        /* The Razer Wolverine V2 Pro doesn't respond to the detection protocol, but has a touchpad and sensors, but no vibration */
-        ctx->sensors_supported = SDL_TRUE;
-        ctx->touchpad_supported = SDL_TRUE;
     }
     }
     ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported || ctx->playerled_supported);
     ctx->effects_supported = (ctx->lightbar_supported || ctx->vibration_supported || ctx->playerled_supported);
 
 
@@ -717,7 +723,7 @@ static void HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device)
     SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
     SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
     SDL_bool led_reset_complete = SDL_FALSE;
     SDL_bool led_reset_complete = SDL_FALSE;
 
 
-    if (ctx->sensors_supported) {
+    if (ctx->enhanced_mode && ctx->sensors_supported && !ctx->use_alternate_report) {
         const PS5StatePacketCommon_t *packet = &ctx->last_state.state;
         const PS5StatePacketCommon_t *packet = &ctx->last_state.state;
 
 
         /* Check the timer to make sure the Bluetooth connection LED animation is complete */
         /* Check the timer to make sure the Bluetooth connection LED animation is complete */
@@ -726,7 +732,7 @@ static void HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device)
                                   packet->rgucSensorTimestamp[1],
                                   packet->rgucSensorTimestamp[1],
                                   packet->rgucSensorTimestamp[2],
                                   packet->rgucSensorTimestamp[2],
                                   packet->rgucSensorTimestamp[3]);
                                   packet->rgucSensorTimestamp[3]);
-        if (SDL_TICKS_PASSED(timestamp, connection_complete)) {
+        if (timestamp >= connection_complete) {
             led_reset_complete = SDL_TRUE;
             led_reset_complete = SDL_TRUE;
         }
         }
     } else {
     } else {
@@ -745,16 +751,25 @@ static void HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device)
 
 
 static void HIDAPI_DriverPS5_TickleBluetooth(SDL_HIDAPI_Device *device)
 static void HIDAPI_DriverPS5_TickleBluetooth(SDL_HIDAPI_Device *device)
 {
 {
-    /* This is just a dummy packet that should have no effect, since we don't set the CRC */
-    Uint8 data[78];
+    SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
 
 
-    SDL_zeroa(data);
+    if (ctx->enhanced_mode) {
+        /* This is just a dummy packet that should have no effect, since we don't set the CRC */
+        Uint8 data[78];
 
 
-    data[0] = k_EPS5ReportIdBluetoothEffects;
-    data[1] = 0x02; /* Magic value */
+        SDL_zeroa(data);
 
 
-    if (SDL_HIDAPI_LockRumble() == 0) {
-        SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
+        data[0] = k_EPS5ReportIdBluetoothEffects;
+        data[1] = 0x02; /* Magic value */
+
+        if (SDL_HIDAPI_LockRumble() == 0) {
+            SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
+        }
+    } else {
+        /* We can't even send an invalid effects packet, or it will put the controller in enhanced mode */
+        if (device->num_joysticks > 0) {
+            HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
+        }
     }
     }
 }
 }
 
 
@@ -1216,30 +1231,56 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
 
 
     if (ctx->report_sensors) {
     if (ctx->report_sensors) {
-        Uint32 timestamp;
-        Uint64 timestamp_us;
         float data[3];
         float data[3];
+        Uint64 timestamp_us;
 
 
-        timestamp = LOAD32(packet->rgucSensorTimestamp[0],
-                           packet->rgucSensorTimestamp[1],
-                           packet->rgucSensorTimestamp[2],
-                           packet->rgucSensorTimestamp[3]);
-        if (ctx->timestamp) {
-            Uint32 delta;
+        if (ctx->use_alternate_report) {
+            /* 16-bit timestamp */
+            Uint16 timestamp;
 
 
-            if (ctx->last_timestamp > timestamp) {
-                delta = (SDL_MAX_UINT32 - ctx->last_timestamp + timestamp + 1);
+            timestamp = LOAD16(packet->rgucSensorTimestamp[0],
+                               packet->rgucSensorTimestamp[1]);
+            if (ctx->timestamp) {
+                Uint16 delta;
+
+                if (ctx->last_timestamp > timestamp) {
+                    delta = (SDL_MAX_UINT16 - ctx->last_timestamp + timestamp + 1);
+                } else {
+                    delta = (timestamp - ctx->last_timestamp);
+                }
+                ctx->timestamp += delta;
             } else {
             } else {
-                delta = (timestamp - ctx->last_timestamp);
+                ctx->timestamp = timestamp;
             }
             }
-            ctx->timestamp += delta;
+            ctx->last_timestamp = timestamp;
+
+            /* Sensor timestamp is in 1us units */
+            timestamp_us = ctx->timestamp;
         } else {
         } else {
-            ctx->timestamp = timestamp;
-        }
-        ctx->last_timestamp = timestamp;
+            /* 32-bit timestamp */
+            Uint32 timestamp;
+
+            timestamp = LOAD32(packet->rgucSensorTimestamp[0],
+                               packet->rgucSensorTimestamp[1],
+                               packet->rgucSensorTimestamp[2],
+                               packet->rgucSensorTimestamp[3]);
+            if (ctx->timestamp) {
+                Uint32 delta;
+
+                if (ctx->last_timestamp > timestamp) {
+                    delta = (SDL_MAX_UINT32 - ctx->last_timestamp + timestamp + 1);
+                } else {
+                    delta = (timestamp - ctx->last_timestamp);
+                }
+                ctx->timestamp += delta;
+            } else {
+                ctx->timestamp = timestamp;
+            }
+            ctx->last_timestamp = timestamp;
 
 
-        /* Sensor timestamp is in 0.33us units */
-        timestamp_us = ctx->timestamp / 3;
+            /* Sensor timestamp is in 0.33us units */
+            timestamp_us = ctx->timestamp / 3;
+        }
 
 
         data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
         data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
         data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
         data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
@@ -1395,15 +1436,15 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
                 /* This is the extended report, we can enable effects now */
                 /* This is the extended report, we can enable effects now */
                 HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
                 HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
             }
             }
-            if (ctx->led_reset_state == k_EDS5LEDResetStatePending) {
-                HIDAPI_DriverPS5_CheckPendingLEDReset(device);
-            }
             HIDAPI_DriverPS5_HandleStatePacketCommon(joystick, device->dev, ctx, (PS5StatePacketCommon_t *)&data[2]);
             HIDAPI_DriverPS5_HandleStatePacketCommon(joystick, device->dev, ctx, (PS5StatePacketCommon_t *)&data[2]);
             if (ctx->use_alternate_report) {
             if (ctx->use_alternate_report) {
                 HIDAPI_DriverPS5_HandleStatePacketAlt(joystick, device->dev, ctx, (PS5StatePacketAlt_t *)&data[2]);
                 HIDAPI_DriverPS5_HandleStatePacketAlt(joystick, device->dev, ctx, (PS5StatePacketAlt_t *)&data[2]);
             } else {
             } else {
                 HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[2]);
                 HIDAPI_DriverPS5_HandleStatePacket(joystick, device->dev, ctx, (PS5StatePacket_t *)&data[2]);
             }
             }
+            if (ctx->led_reset_state == k_EDS5LEDResetStatePending) {
+                HIDAPI_DriverPS5_CheckPendingLEDReset(device);
+            }
             break;
             break;
         default:
         default:
 #ifdef DEBUG_JOYSTICK
 #ifdef DEBUG_JOYSTICK

+ 3 - 3
libs/SDL2/src/joystick/linux/SDL_sysjoystick.c

@@ -1041,7 +1041,7 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd)
         }
         }
         for (i = 0; i < ABS_MAX; ++i) {
         for (i = 0; i < ABS_MAX; ++i) {
             /* Skip digital hats */
             /* Skip digital hats */
-            if (joystick->hwdata->has_hat[(i - ABS_HAT0X) / 2]) {
+            if (i >= ABS_HAT0X && i <= ABS_HAT3Y && joystick->hwdata->has_hat[(i - ABS_HAT0X) / 2]) {
                 continue;
                 continue;
             }
             }
             if (test_bit(i, absbit)) {
             if (test_bit(i, absbit)) {
@@ -1752,11 +1752,11 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap
     /* We temporarily open the device to check how it's configured. Make
     /* We temporarily open the device to check how it's configured. Make
        a fake SDL_Joystick object to do so. */
        a fake SDL_Joystick object to do so. */
     joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1);
     joystick = (SDL_Joystick *)SDL_calloc(sizeof(*joystick), 1);
-    joystick->magic = &SDL_joystick_magic;
     if (joystick == NULL) {
     if (joystick == NULL) {
         SDL_OutOfMemory();
         SDL_OutOfMemory();
         return SDL_FALSE;
         return SDL_FALSE;
     }
     }
+    joystick->magic = &SDL_joystick_magic;
     SDL_memcpy(&joystick->guid, &item->guid, sizeof(item->guid));
     SDL_memcpy(&joystick->guid, &item->guid, sizeof(item->guid));
 
 
     joystick->hwdata = (struct joystick_hwdata *)
     joystick->hwdata = (struct joystick_hwdata *)
@@ -2026,7 +2026,7 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap
 #endif
 #endif
     }
     }
 
 
-    if (!(mapped & MAPPED_TRIGGER_LEFT) && joystick->hwdata->has_key[BTN_TR2]) {
+    if (!(mapped & MAPPED_TRIGGER_RIGHT) && joystick->hwdata->has_key[BTN_TR2]) {
         out->righttrigger.kind = EMappingKind_Button;
         out->righttrigger.kind = EMappingKind_Button;
         out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
         out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
         mapped |= MAPPED_TRIGGER_RIGHT;
         mapped |= MAPPED_TRIGGER_RIGHT;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 477 - 450
libs/SDL2/src/joystick/os2/SDL_os2joystick.c


+ 1 - 0
libs/SDL2/src/joystick/sort_controllers.py

@@ -22,6 +22,7 @@ standard_guid_pattern = re.compile(r'^([0-9a-fA-F]{4})([0-9a-fA-F]{2})([0-9a-fA-
 invalid_controllers = (
 invalid_controllers = (
     ('0079', '0006', '0000'), # DragonRise Inc. Generic USB Joystick
     ('0079', '0006', '0000'), # DragonRise Inc. Generic USB Joystick
     ('0079', '0006', '6120'), # DragonRise Inc. Generic USB Joystick
     ('0079', '0006', '6120'), # DragonRise Inc. Generic USB Joystick
+    ('04b4', '2412', 'c529'), # Flydigi Vader 2, Vader 2 Pro, Apex 2, Apex 3
     ('16c0', '05e1', '0000'), # Xinmotek Controller
     ('16c0', '05e1', '0000'), # Xinmotek Controller
 )
 )
 
 

+ 175 - 34
libs/SDL2/src/joystick/windows/SDL_rawinputjoystick.c

@@ -33,6 +33,7 @@
 
 
 #if SDL_JOYSTICK_RAWINPUT
 #if SDL_JOYSTICK_RAWINPUT
 
 
+#include "SDL_atomic.h"
 #include "SDL_endian.h"
 #include "SDL_endian.h"
 #include "SDL_events.h"
 #include "SDL_events.h"
 #include "SDL_hints.h"
 #include "SDL_hints.h"
@@ -47,7 +48,7 @@
    raw input will turn off the Xbox Series X controller when it is connected via the
    raw input will turn off the Xbox Series X controller when it is connected via the
    Xbox One Wireless Adapter.
    Xbox One Wireless Adapter.
  */
  */
-#if 0 /*def HAVE_XINPUT_H*/
+#ifdef HAVE_XINPUT_H
 #define SDL_JOYSTICK_RAWINPUT_XINPUT
 #define SDL_JOYSTICK_RAWINPUT_XINPUT
 #endif
 #endif
 #ifdef HAVE_WINDOWS_GAMING_INPUT_H
 #ifdef HAVE_WINDOWS_GAMING_INPUT_H
@@ -78,7 +79,9 @@ typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
 #endif
 #endif
 #endif
 #endif
 
 
-/*#define DEBUG_RAWINPUT*/
+#if 0
+#define DEBUG_RAWINPUT
+#endif
 
 
 #ifndef RIDEV_EXINPUTSINK
 #ifndef RIDEV_EXINPUTSINK
 #define RIDEV_EXINPUTSINK 0x00001000
 #define RIDEV_EXINPUTSINK 0x00001000
@@ -401,6 +404,21 @@ static SDL_bool RAWINPUT_GuessXInputSlot(const WindowsMatchState *state, Uint8 *
     int user_index;
     int user_index;
     int match_count;
     int match_count;
 
 
+    /* If there is only one available slot, let's use that
+     * That will be right most of the time, and uncorrelation will fix any bad guesses
+     */
+    match_count = 0;
+    for (user_index = 0; user_index < XUSER_MAX_COUNT; ++user_index) {
+        if (xinput_state[user_index].connected && !xinput_state[user_index].used) {
+            *slot_idx = user_index;
+            ++match_count;
+        }
+    }
+    if (match_count == 1) {
+        *correlation_id = ++xinput_state[*slot_idx].correlation_id;
+        return SDL_TRUE;
+    }
+
     *slot_idx = 0;
     *slot_idx = 0;
 
 
     match_count = 0;
     match_count = 0;
@@ -445,8 +463,86 @@ static struct
     SDL_bool need_device_list_update;
     SDL_bool need_device_list_update;
     int ref_count;
     int ref_count;
     __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics *gamepad_statics;
     __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics *gamepad_statics;
+    EventRegistrationToken gamepad_added_token;
+    EventRegistrationToken gamepad_removed_token;
 } wgi_state;
 } wgi_state;
 
 
+typedef struct GamepadDelegate
+{
+    __FIEventHandler_1_Windows__CGaming__CInput__CGamepad iface;
+    SDL_atomic_t refcount;
+} GamepadDelegate;
+
+static const IID IID_IEventHandler_Gamepad = { 0x8a7639ee, 0x624a, 0x501a, { 0xbb, 0x53, 0x56, 0x2d, 0x1e, 0xc1, 0x1b, 0x52 } };
+
+static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_QueryInterface(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This, REFIID riid, void **ppvObject)
+{
+    if (ppvObject == NULL) {
+        return E_INVALIDARG;
+    }
+
+    *ppvObject = NULL;
+    if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID_IEventHandler_Gamepad)) {
+        *ppvObject = This;
+        __FIEventHandler_1_Windows__CGaming__CInput__CGamepad_AddRef(This);
+        return S_OK;
+    } else if (WIN_IsEqualIID(riid, &IID_IMarshal)) {
+        /* This seems complicated. Let's hope it doesn't happen. */
+        return E_OUTOFMEMORY;
+    } else {
+        return E_NOINTERFACE;
+    }
+}
+
+static ULONG STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_AddRef(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This)
+{
+    GamepadDelegate *self = (GamepadDelegate *)This;
+    return SDL_AtomicAdd(&self->refcount, 1) + 1UL;
+}
+
+static ULONG STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_Release(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This)
+{
+    GamepadDelegate *self = (GamepadDelegate *)This;
+    int rc = SDL_AtomicAdd(&self->refcount, -1) - 1;
+    /* Should never free the static delegate objects */
+    SDL_assert(rc > 0);
+    return rc;
+}
+
+static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIGamepad *e)
+{
+    wgi_state.need_device_list_update = SDL_TRUE;
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE IEventHandler_CGamepadVtbl_InvokeRemoved(__FIEventHandler_1_Windows__CGaming__CInput__CGamepad *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIGamepad *e)
+{
+    wgi_state.need_device_list_update = SDL_TRUE;
+    return S_OK;
+}
+
+static __FIEventHandler_1_Windows__CGaming__CInput__CGamepadVtbl gamepad_added_vtbl = {
+    IEventHandler_CGamepadVtbl_QueryInterface,
+    IEventHandler_CGamepadVtbl_AddRef,
+    IEventHandler_CGamepadVtbl_Release,
+    IEventHandler_CGamepadVtbl_InvokeAdded
+};
+static GamepadDelegate gamepad_added = {
+    { &gamepad_added_vtbl },
+    { 1 }
+};
+
+static __FIEventHandler_1_Windows__CGaming__CInput__CGamepadVtbl gamepad_removed_vtbl = {
+    IEventHandler_CGamepadVtbl_QueryInterface,
+    IEventHandler_CGamepadVtbl_AddRef,
+    IEventHandler_CGamepadVtbl_Release,
+    IEventHandler_CGamepadVtbl_InvokeRemoved
+};
+static GamepadDelegate gamepad_removed = {
+    { &gamepad_removed_vtbl },
+    { 1 }
+};
+
 static void RAWINPUT_MarkWindowsGamingInputSlotUsed(WindowsGamingInputGamepadState *wgi_slot, RAWINPUT_DeviceContext *ctx)
 static void RAWINPUT_MarkWindowsGamingInputSlotUsed(WindowsGamingInputGamepadState *wgi_slot, RAWINPUT_DeviceContext *ctx)
 {
 {
     wgi_slot->used = SDL_TRUE;
     wgi_slot->used = SDL_TRUE;
@@ -564,7 +660,10 @@ static void RAWINPUT_UpdateWindowsGamingInput()
 }
 }
 static void RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
 static void RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
 {
 {
-    wgi_state.need_device_list_update = SDL_TRUE;
+    if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_WGI, SDL_TRUE)) {
+        return;
+    }
+
     wgi_state.ref_count++;
     wgi_state.ref_count++;
     if (!wgi_state.initialized) {
     if (!wgi_state.initialized) {
         static const IID SDL_IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
         static const IID SDL_IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
@@ -596,6 +695,20 @@ static void RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
                 if (SUCCEEDED(hr)) {
                 if (SUCCEEDED(hr)) {
                     RoGetActivationFactoryFunc(hNamespaceString, &SDL_IID_IGamepadStatics, (void **)&wgi_state.gamepad_statics);
                     RoGetActivationFactoryFunc(hNamespaceString, &SDL_IID_IGamepadStatics, (void **)&wgi_state.gamepad_statics);
                 }
                 }
+
+                if (wgi_state.gamepad_statics) {
+                    wgi_state.need_device_list_update = SDL_TRUE;
+
+                    hr = __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_add_GamepadAdded(wgi_state.gamepad_statics, &gamepad_added.iface, &wgi_state.gamepad_added_token);
+                    if (!SUCCEEDED(hr)) {
+                        SDL_SetError("add_GamepadAdded() failed: 0x%lx\n", hr);
+                    }
+
+                    hr = __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_add_GamepadRemoved(wgi_state.gamepad_statics, &gamepad_removed.iface, &wgi_state.gamepad_removed_token);
+                    if (!SUCCEEDED(hr)) {
+                        SDL_SetError("add_GamepadRemoved() failed: 0x%lx\n", hr);
+                    }
+                }
             }
             }
         }
         }
     }
     }
@@ -621,10 +734,27 @@ static SDL_bool RAWINPUT_WindowsGamingInputSlotMatches(const WindowsMatchState *
 static SDL_bool RAWINPUT_GuessWindowsGamingInputSlot(const WindowsMatchState *state, Uint8 *correlation_id, WindowsGamingInputGamepadState **slot, SDL_bool xinput_correlated)
 static SDL_bool RAWINPUT_GuessWindowsGamingInputSlot(const WindowsMatchState *state, Uint8 *correlation_id, WindowsGamingInputGamepadState **slot, SDL_bool xinput_correlated)
 {
 {
     int match_count, user_index;
     int match_count, user_index;
+    WindowsGamingInputGamepadState *gamepad_state = NULL;
+
+    /* If there is only one available slot, let's use that
+     * That will be right most of the time, and uncorrelation will fix any bad guesses
+     */
+    match_count = 0;
+    for (user_index = 0; user_index < wgi_state.per_gamepad_count; ++user_index) {
+        gamepad_state = wgi_state.per_gamepad[user_index];
+        if (gamepad_state->connected && !gamepad_state->used) {
+            *slot = gamepad_state;
+            ++match_count;
+        }
+    }
+    if (match_count == 1) {
+        *correlation_id = ++gamepad_state->correlation_id;
+        return SDL_TRUE;
+    }
 
 
     match_count = 0;
     match_count = 0;
     for (user_index = 0; user_index < wgi_state.per_gamepad_count; ++user_index) {
     for (user_index = 0; user_index < wgi_state.per_gamepad_count; ++user_index) {
-        WindowsGamingInputGamepadState *gamepad_state = wgi_state.per_gamepad[user_index];
+        gamepad_state = wgi_state.per_gamepad[user_index];
         if (RAWINPUT_WindowsGamingInputSlotMatches(state, gamepad_state, xinput_correlated)) {
         if (RAWINPUT_WindowsGamingInputSlotMatches(state, gamepad_state, xinput_correlated)) {
             ++match_count;
             ++match_count;
             *slot = gamepad_state;
             *slot = gamepad_state;
@@ -643,7 +773,6 @@ static SDL_bool RAWINPUT_GuessWindowsGamingInputSlot(const WindowsMatchState *st
 
 
 static void RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
 static void RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
 {
 {
-    wgi_state.need_device_list_update = SDL_TRUE;
     --wgi_state.ref_count;
     --wgi_state.ref_count;
     if (!wgi_state.ref_count && wgi_state.initialized) {
     if (!wgi_state.ref_count && wgi_state.initialized) {
         int ii;
         int ii;
@@ -656,6 +785,8 @@ static void RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
         }
         }
         wgi_state.per_gamepad_count = 0;
         wgi_state.per_gamepad_count = 0;
         if (wgi_state.gamepad_statics) {
         if (wgi_state.gamepad_statics) {
+            __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_remove_GamepadAdded(wgi_state.gamepad_statics, wgi_state.gamepad_added_token);
+            __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_remove_GamepadRemoved(wgi_state.gamepad_statics, wgi_state.gamepad_removed_token);
             __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi_state.gamepad_statics);
             __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi_state.gamepad_statics);
             wgi_state.gamepad_statics = NULL;
             wgi_state.gamepad_statics = NULL;
         }
         }
@@ -879,12 +1010,12 @@ static int RAWINPUT_JoystickInit(void)
 {
 {
     SDL_assert(!SDL_RAWINPUT_inited);
     SDL_assert(!SDL_RAWINPUT_inited);
 
 
-    if (!WIN_IsWindowsVistaOrGreater()) {
-        /* According to bug 6400, this doesn't work on Windows XP */
-        return -1;
+    if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, SDL_TRUE)) {
+        return 0;
     }
     }
 
 
-    if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_RAWINPUT, SDL_TRUE)) {
+    if (!WIN_IsWindowsVistaOrGreater()) {
+        /* According to bug 6400, this doesn't work on Windows XP */
         return -1;
         return -1;
     }
     }
 
 
@@ -917,9 +1048,6 @@ SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 ve
 #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
 #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
     xinput_device_change = SDL_TRUE;
     xinput_device_change = SDL_TRUE;
 #endif
 #endif
-#ifdef SDL_JOYSTICK_RAWINPUT_WGI
-    wgi_state.need_device_list_update = SDL_TRUE;
-#endif
 
 
     device = SDL_RAWINPUT_devices;
     device = SDL_RAWINPUT_devices;
     while (device) {
     while (device) {
@@ -1008,8 +1136,13 @@ static void RAWINPUT_PostUpdate(void)
 
 
 static void RAWINPUT_JoystickDetect(void)
 static void RAWINPUT_JoystickDetect(void)
 {
 {
-    SDL_bool remote_desktop = GetSystemMetrics(SM_REMOTESESSION) ? SDL_TRUE : SDL_FALSE;
+    SDL_bool remote_desktop;
+
+    if (!SDL_RAWINPUT_inited) {
+        return;
+    }
 
 
+    remote_desktop = GetSystemMetrics(SM_REMOTESESSION) ? SDL_TRUE : SDL_FALSE;
     if (remote_desktop != SDL_RAWINPUT_remote_desktop) {
     if (remote_desktop != SDL_RAWINPUT_remote_desktop) {
         SDL_RAWINPUT_remote_desktop = remote_desktop;
         SDL_RAWINPUT_remote_desktop = remote_desktop;
 
 
@@ -1281,20 +1414,8 @@ static int RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_
 #endif
 #endif
     SDL_bool rumbled = SDL_FALSE;
     SDL_bool rumbled = SDL_FALSE;
 
 
-#ifdef SDL_JOYSTICK_RAWINPUT_WGI
-    if (!rumbled && ctx->wgi_correlated) {
-        WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
-        HRESULT hr;
-        gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
-        gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
-        hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
-        if (SUCCEEDED(hr)) {
-            rumbled = SDL_TRUE;
-        }
-    }
-#endif
-
 #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
 #ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
+    /* Prefer XInput over WGI because it allows rumble in the background */
     if (!rumbled && ctx->xinput_correlated) {
     if (!rumbled && ctx->xinput_correlated) {
         XINPUT_VIBRATION XVibration;
         XINPUT_VIBRATION XVibration;
 
 
@@ -1312,6 +1433,19 @@ static int RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_
     }
     }
 #endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
 #endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
 
 
+#ifdef SDL_JOYSTICK_RAWINPUT_WGI
+    if (!rumbled && ctx->wgi_correlated) {
+        WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
+        HRESULT hr;
+        gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
+        gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
+        hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
+        if (SUCCEEDED(hr)) {
+            rumbled = SDL_TRUE;
+        }
+    }
+#endif
+
     if (!rumbled) {
     if (!rumbled) {
 #if defined(SDL_JOYSTICK_RAWINPUT_WGI) || defined(SDL_JOYSTICK_RAWINPUT_XINPUT)
 #if defined(SDL_JOYSTICK_RAWINPUT_WGI) || defined(SDL_JOYSTICK_RAWINPUT_XINPUT)
         return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
         return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
@@ -1911,10 +2045,14 @@ static void RAWINPUT_JoystickClose(SDL_Joystick *joystick)
     }
     }
 }
 }
 
 
-SDL_bool RAWINPUT_RegisterNotifications(HWND hWnd)
+int RAWINPUT_RegisterNotifications(HWND hWnd)
 {
 {
-    RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
     int i;
     int i;
+    RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
+
+    if (!SDL_RAWINPUT_inited) {
+        return 0;
+    }
 
 
     for (i = 0; i < SDL_arraysize(subscribed_devices); i++) {
     for (i = 0; i < SDL_arraysize(subscribed_devices); i++) {
         rid[i].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
         rid[i].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
@@ -1924,17 +2062,20 @@ SDL_bool RAWINPUT_RegisterNotifications(HWND hWnd)
     }
     }
 
 
     if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
     if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
-        SDL_SetError("Couldn't register for raw input events");
-        return SDL_FALSE;
+        return SDL_SetError("Couldn't register for raw input events");
     }
     }
-    return SDL_TRUE;
+    return 0;
 }
 }
 
 
-void RAWINPUT_UnregisterNotifications()
+int RAWINPUT_UnregisterNotifications()
 {
 {
     int i;
     int i;
     RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
     RAWINPUTDEVICE rid[SDL_arraysize(subscribed_devices)];
 
 
+    if (!SDL_RAWINPUT_inited) {
+        return 0;
+    }
+
     for (i = 0; i < SDL_arraysize(subscribed_devices); i++) {
     for (i = 0; i < SDL_arraysize(subscribed_devices); i++) {
         rid[i].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
         rid[i].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP;
         rid[i].usUsage = subscribed_devices[i];
         rid[i].usUsage = subscribed_devices[i];
@@ -1943,9 +2084,9 @@ void RAWINPUT_UnregisterNotifications()
     }
     }
 
 
     if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
     if (!RegisterRawInputDevices(rid, SDL_arraysize(rid), sizeof(RAWINPUTDEVICE))) {
-        SDL_SetError("Couldn't unregister for raw input events");
-        return;
+        return SDL_SetError("Couldn't unregister for raw input events");
     }
     }
+    return 0;
 }
 }
 
 
 LRESULT CALLBACK
 LRESULT CALLBACK

+ 2 - 2
libs/SDL2/src/joystick/windows/SDL_rawinputjoystick_c.h

@@ -28,8 +28,8 @@ extern SDL_bool RAWINPUT_IsEnabled();
 extern SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
 extern SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
 
 
 /* Registers for input events */
 /* Registers for input events */
-extern SDL_bool RAWINPUT_RegisterNotifications(HWND hWnd);
-extern void RAWINPUT_UnregisterNotifications();
+extern int RAWINPUT_RegisterNotifications(HWND hWnd);
+extern int RAWINPUT_UnregisterNotifications();
 
 
 /* Returns 0 if message was handled */
 /* Returns 0 if message was handled */
 extern LRESULT CALLBACK RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
 extern LRESULT CALLBACK RAWINPUT_WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

+ 162 - 108
libs/SDL2/src/joystick/windows/SDL_windows_gaming_input.c

@@ -101,6 +101,9 @@ static const IID IID_IRacingWheelStatics = { 0x3AC12CD5, 0x581B, 0x4936, { 0x9F,
 static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } };
 static const IID IID_IRacingWheelStatics2 = { 0xE666BCAA, 0xEDFD, 0x4323, { 0xA9, 0xF6, 0x3C, 0x38, 0x40, 0x48, 0xD1, 0xED } };
 /*static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };*/
 /*static const IID IID_IRacingWheel = { 0xF546656F, 0xE106, 0x4C82, { 0xA9, 0x0F, 0x55, 0x40, 0x12, 0x90, 0x4B, 0x85 } };*/
 
 
+typedef HRESULT(WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string);
+typedef HRESULT(WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory);
+
 
 
 extern SDL_bool SDL_XINPUT_Enabled(void);
 extern SDL_bool SDL_XINPUT_Enabled(void);
 extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
 extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
@@ -211,6 +214,136 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
     return SDL_FALSE;
     return SDL_FALSE;
 }
 }
 
 
+static void WGI_LoadRawGameControllerStatics()
+{
+    WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
+    RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
+    HRESULT hr;
+
+#ifdef __WINRT__
+    WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
+    RoGetActivationFactoryFunc = RoGetActivationFactory;
+#else
+    {
+        WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
+        RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
+    }
+#endif /* __WINRT__ */
+    if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
+        PCWSTR pNamespace;
+        HSTRING_HEADER hNamespaceStringHeader;
+        HSTRING hNamespaceString;
+
+        pNamespace = L"Windows.Gaming.Input.RawGameController";
+        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
+        if (SUCCEEDED(hr)) {
+            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, (void **)&wgi.statics);
+            if (!SUCCEEDED(hr)) {
+                SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%lx", hr);
+            }
+        }
+    }
+}
+
+static void WGI_LoadOtherControllerStatics()
+{
+    WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
+    RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
+    HRESULT hr;
+
+#ifdef __WINRT__
+    WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
+    RoGetActivationFactoryFunc = RoGetActivationFactory;
+#else
+    {
+        WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
+        RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
+    }
+#endif /* __WINRT__ */
+    if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
+        PCWSTR pNamespace;
+        HSTRING_HEADER hNamespaceStringHeader;
+        HSTRING hNamespaceString;
+
+        pNamespace = L"Windows.Gaming.Input.ArcadeStick";
+        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
+        if (SUCCEEDED(hr)) {
+            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, (void **)&wgi.arcade_stick_statics);
+            if (SUCCEEDED(hr)) {
+                __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, (void **)&wgi.arcade_stick_statics2);
+            } else {
+                SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%lx", hr);
+            }
+        }
+
+        pNamespace = L"Windows.Gaming.Input.FlightStick";
+        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
+        if (SUCCEEDED(hr)) {
+            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, (void **)&wgi.flight_stick_statics);
+            if (!SUCCEEDED(hr)) {
+                SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%lx", hr);
+            }
+        }
+
+        pNamespace = L"Windows.Gaming.Input.Gamepad";
+        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
+        if (SUCCEEDED(hr)) {
+            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, (void **)&wgi.gamepad_statics);
+            if (SUCCEEDED(hr)) {
+                __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, (void **)&wgi.gamepad_statics2);
+            } else {
+                SDL_SetError("Couldn't find IGamepadStatics: 0x%lx", hr);
+            }
+        }
+
+        pNamespace = L"Windows.Gaming.Input.RacingWheel";
+        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
+        if (SUCCEEDED(hr)) {
+            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, (void **)&wgi.racing_wheel_statics);
+            if (SUCCEEDED(hr)) {
+                __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, (void **)&wgi.racing_wheel_statics2);
+            } else {
+                SDL_SetError("Couldn't find IRacingWheelStatics: 0x%lx", hr);
+            }
+        }
+    }
+}
+
+static SDL_JoystickType GetGameControllerType(__x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller)
+{
+    __x_ABI_CWindows_CGaming_CInput_CIArcadeStick *arcade_stick = NULL;
+    __x_ABI_CWindows_CGaming_CInput_CIFlightStick *flight_stick = NULL;
+    __x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad = NULL;
+    __x_ABI_CWindows_CGaming_CInput_CIRacingWheel *racing_wheel = NULL;
+
+    /* Wait to initialize these interfaces until we need them.
+     * Initializing the gamepad interface will switch Bluetooth PS4 controllers into enhanced mode, breaking DirectInput
+     */
+    WGI_LoadOtherControllerStatics();
+
+    if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, gamecontroller, &gamepad)) && gamepad) {
+        __x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(gamepad);
+        return SDL_JOYSTICK_TYPE_GAMECONTROLLER;
+    }
+
+    if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, gamecontroller, &arcade_stick)) && arcade_stick) {
+        __x_ABI_CWindows_CGaming_CInput_CIArcadeStick_Release(arcade_stick);
+        return SDL_JOYSTICK_TYPE_ARCADE_STICK;
+    }
+
+    if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, gamecontroller, &flight_stick)) && flight_stick) {
+        __x_ABI_CWindows_CGaming_CInput_CIFlightStick_Release(flight_stick);
+        return SDL_JOYSTICK_TYPE_FLIGHT_STICK;
+    }
+
+    if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, gamecontroller, &racing_wheel)) && racing_wheel) {
+        __x_ABI_CWindows_CGaming_CInput_CIRacingWheel_Release(racing_wheel);
+        return SDL_JOYSTICK_TYPE_WHEEL;
+    }
+
+    return SDL_JOYSTICK_TYPE_UNKNOWN;
+}
+
 typedef struct RawGameControllerDelegate
 typedef struct RawGameControllerDelegate
 {
 {
     __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController iface;
     __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController iface;
@@ -226,7 +359,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_QueryInter
     *ppvObject = NULL;
     *ppvObject = NULL;
     if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) {
     if (WIN_IsEqualIID(riid, &IID_IUnknown) || WIN_IsEqualIID(riid, &IID_IAgileObject) || WIN_IsEqualIID(riid, &IID_IEventHandler_RawGameController)) {
         *ppvObject = This;
         *ppvObject = This;
-        __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_AddRef(This);
+        __FIEventHandler_1_Windows__CGaming__CInput__CRawGameController_AddRef(This);
         return S_OK;
         return S_OK;
     } else if (WIN_IsEqualIID(riid, &IID_IMarshal)) {
     } else if (WIN_IsEqualIID(riid, &IID_IMarshal)) {
         /* This seems complicated. Let's hope it doesn't happen. */
         /* This seems complicated. Let's hope it doesn't happen. */
@@ -313,38 +446,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             name = SDL_strdup("");
             name = SDL_strdup("");
         }
         }
 
 
-        hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller);
-        if (SUCCEEDED(hr)) {
-            __x_ABI_CWindows_CGaming_CInput_CIArcadeStick *arcade_stick = NULL;
-            __x_ABI_CWindows_CGaming_CInput_CIFlightStick *flight_stick = NULL;
-            __x_ABI_CWindows_CGaming_CInput_CIGamepad *gamepad = NULL;
-            __x_ABI_CWindows_CGaming_CInput_CIRacingWheel *racing_wheel = NULL;
-            boolean wireless;
-
-            if (wgi.gamepad_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2_FromGameController(wgi.gamepad_statics2, gamecontroller, &gamepad)) && gamepad) {
-                type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
-                __x_ABI_CWindows_CGaming_CInput_CIGamepad_Release(gamepad);
-            } else if (wgi.arcade_stick_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics2_FromGameController(wgi.arcade_stick_statics2, gamecontroller, &arcade_stick)) && arcade_stick) {
-                type = SDL_JOYSTICK_TYPE_ARCADE_STICK;
-                __x_ABI_CWindows_CGaming_CInput_CIArcadeStick_Release(arcade_stick);
-            } else if (wgi.flight_stick_statics && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIFlightStickStatics_FromGameController(wgi.flight_stick_statics, gamecontroller, &flight_stick)) && flight_stick) {
-                type = SDL_JOYSTICK_TYPE_FLIGHT_STICK;
-                __x_ABI_CWindows_CGaming_CInput_CIFlightStick_Release(flight_stick);
-            } else if (wgi.racing_wheel_statics2 && SUCCEEDED(__x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics2_FromGameController(wgi.racing_wheel_statics2, gamecontroller, &racing_wheel)) && racing_wheel) {
-                type = SDL_JOYSTICK_TYPE_WHEEL;
-                __x_ABI_CWindows_CGaming_CInput_CIRacingWheel_Release(racing_wheel);
-            }
-
-            hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(gamecontroller, &wireless);
-            if (SUCCEEDED(hr) && wireless) {
-                bus = SDL_HARDWARE_BUS_BLUETOOTH;
-            }
-
-            __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller);
-        }
-
-        guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type);
-
 #ifdef SDL_JOYSTICK_HIDAPI
 #ifdef SDL_JOYSTICK_HIDAPI
         if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) {
         if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) {
             ignore_joystick = SDL_TRUE;
             ignore_joystick = SDL_TRUE;
@@ -365,13 +466,29 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             ignore_joystick = SDL_TRUE;
             ignore_joystick = SDL_TRUE;
         }
         }
 
 
-        if (!ignore_joystick && SDL_ShouldIgnoreJoystick(name, guid)) {
-            ignore_joystick = SDL_TRUE;
+        if (!ignore_joystick) {
+            hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller);
+            if (SUCCEEDED(hr)) {
+                boolean wireless;
+
+                type = GetGameControllerType(gamecontroller);
+
+                hr = __x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(gamecontroller, &wireless);
+                if (SUCCEEDED(hr) && wireless) {
+                    bus = SDL_HARDWARE_BUS_BLUETOOTH;
+                }
+
+                __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller);
+            }
+
+            guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type);
+
+            if (SDL_ShouldIgnoreJoystick(name, guid)) {
+                ignore_joystick = SDL_TRUE;
+            }
         }
         }
 
 
-        if (ignore_joystick) {
-            SDL_free(name);
-        } else {
+        if (!ignore_joystick) {
             /* New device, add it */
             /* New device, add it */
             WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
             WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
             if (controllers) {
             if (controllers) {
@@ -398,6 +515,8 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             } else {
             } else {
                 SDL_free(name);
                 SDL_free(name);
             }
             }
+        } else {
+            SDL_free(name);
         }
         }
 
 
         __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
         __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
@@ -476,13 +595,12 @@ static RawGameControllerDelegate controller_removed = {
 
 
 static int WGI_JoystickInit(void)
 static int WGI_JoystickInit(void)
 {
 {
-    typedef HRESULT(WINAPI * WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER * hstringHeader, HSTRING * string);
-    typedef HRESULT(WINAPI * RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory);
-
-    WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
-    RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
     HRESULT hr;
     HRESULT hr;
 
 
+    if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_WGI, SDL_TRUE)) {
+        return 0;
+    }
+
     if (FAILED(WIN_RoInitialize())) {
     if (FAILED(WIN_RoInitialize())) {
         return SDL_SetError("RoInitialize() failed");
         return SDL_SetError("RoInitialize() failed");
     }
     }
@@ -511,71 +629,7 @@ static int WGI_JoystickInit(void)
     }
     }
 #endif
 #endif
 
 
-#ifdef __WINRT__
-    WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
-    RoGetActivationFactoryFunc = RoGetActivationFactory;
-#else
-    {
-        WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
-        RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
-    }
-#endif /* __WINRT__ */
-    if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
-        PCWSTR pNamespace;
-        HSTRING_HEADER hNamespaceStringHeader;
-        HSTRING hNamespaceString;
-
-        pNamespace = L"Windows.Gaming.Input.RawGameController";
-        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
-        if (SUCCEEDED(hr)) {
-            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRawGameControllerStatics, (void **)&wgi.statics);
-            if (!SUCCEEDED(hr)) {
-                SDL_SetError("Couldn't find IRawGameControllerStatics: 0x%lx", hr);
-            }
-        }
-
-        pNamespace = L"Windows.Gaming.Input.ArcadeStick";
-        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
-        if (SUCCEEDED(hr)) {
-            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IArcadeStickStatics, (void **)&wgi.arcade_stick_statics);
-            if (SUCCEEDED(hr)) {
-                __x_ABI_CWindows_CGaming_CInput_CIArcadeStickStatics_QueryInterface(wgi.arcade_stick_statics, &IID_IArcadeStickStatics2, (void **)&wgi.arcade_stick_statics2);
-            } else {
-                SDL_SetError("Couldn't find IID_IArcadeStickStatics: 0x%lx", hr);
-            }
-        }
-
-        pNamespace = L"Windows.Gaming.Input.FlightStick";
-        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
-        if (SUCCEEDED(hr)) {
-            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IFlightStickStatics, (void **)&wgi.flight_stick_statics);
-            if (!SUCCEEDED(hr)) {
-                SDL_SetError("Couldn't find IID_IFlightStickStatics: 0x%lx", hr);
-            }
-        }
-
-        pNamespace = L"Windows.Gaming.Input.Gamepad";
-        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
-        if (SUCCEEDED(hr)) {
-            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IGamepadStatics, (void **)&wgi.gamepad_statics);
-            if (SUCCEEDED(hr)) {
-                __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_QueryInterface(wgi.gamepad_statics, &IID_IGamepadStatics2, (void **)&wgi.gamepad_statics2);
-            } else {
-                SDL_SetError("Couldn't find IGamepadStatics: 0x%lx", hr);
-            }
-        }
-
-        pNamespace = L"Windows.Gaming.Input.RacingWheel";
-        hr = WindowsCreateStringReferenceFunc(pNamespace, (UINT32)SDL_wcslen(pNamespace), &hNamespaceStringHeader, &hNamespaceString);
-        if (SUCCEEDED(hr)) {
-            hr = RoGetActivationFactoryFunc(hNamespaceString, &IID_IRacingWheelStatics, (void **)&wgi.racing_wheel_statics);
-            if (SUCCEEDED(hr)) {
-                __x_ABI_CWindows_CGaming_CInput_CIRacingWheelStatics_QueryInterface(wgi.racing_wheel_statics, &IID_IRacingWheelStatics2, (void **)&wgi.racing_wheel_statics2);
-            } else {
-                SDL_SetError("Couldn't find IRacingWheelStatics: 0x%lx", hr);
-            }
-        }
-    }
+    WGI_LoadRawGameControllerStatics();
 
 
     if (wgi.statics) {
     if (wgi.statics) {
         __FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers;
         __FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers;

+ 14 - 7
libs/SDL2/src/joystick/windows/SDL_xinputjoystick.c

@@ -235,6 +235,20 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
     JoyStick_DeviceData *pPrevJoystick = NULL;
     JoyStick_DeviceData *pPrevJoystick = NULL;
     JoyStick_DeviceData *pNewJoystick = *pContext;
     JoyStick_DeviceData *pNewJoystick = *pContext;
 
 
+#ifdef SDL_JOYSTICK_RAWINPUT
+    if (RAWINPUT_IsEnabled()) {
+        /* The raw input driver handles more than 4 controllers, so prefer that when available */
+        /* We do this check here rather than at the top of SDL_XINPUT_JoystickDetect() because
+           we need to check XInput state before RAWINPUT gets a hold of the device, otherwise
+           when a controller is connected via the wireless adapter, it will shut down at the
+           first subsequent XInput call. This seems like a driver stack bug?
+
+           Reference: https://github.com/libsdl-org/SDL/issues/3468
+         */
+        return;
+    }
+#endif
+
     if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD) {
     if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD) {
         return;
         return;
     }
     }
@@ -322,13 +336,6 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
         return;
         return;
     }
     }
 
 
-#ifdef SDL_JOYSTICK_RAWINPUT
-    if (RAWINPUT_IsEnabled()) {
-        /* The raw input driver handles more than 4 controllers, so prefer that when available */
-        return;
-    }
-#endif
-
     /* iterate in reverse, so these are in the final list in ascending numeric order. */
     /* iterate in reverse, so these are in the final list in ascending numeric order. */
     for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
     for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
         const Uint8 userid = (Uint8)iuserid;
         const Uint8 userid = (Uint8)iuserid;

+ 1 - 1
libs/SDL2/src/main/windows/SDL_windows_main.c

@@ -103,7 +103,7 @@ int console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
 #endif
 #endif
 
 
 /* This is where execution begins [windowed apps] */
 /* This is where execution begins [windowed apps] */
-int WINAPI
+int WINAPI MINGW32_FORCEALIGN
 WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) /* NOLINT(readability-inconsistent-declaration-parameter-name) */
 WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) /* NOLINT(readability-inconsistent-declaration-parameter-name) */
 {
 {
     return main_getcmdline();
     return main_getcmdline();

+ 4 - 4
libs/SDL2/src/main/windows/version.rc

@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 //
 
 
 VS_VERSION_INFO VERSIONINFO
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,28,1,0
- PRODUCTVERSION 2,28,1,0
+ FILEVERSION 2,28,4,0
+ PRODUCTVERSION 2,28,4,0
  FILEFLAGSMASK 0x3fL
  FILEFLAGSMASK 0x3fL
  FILEFLAGS 0x0L
  FILEFLAGS 0x0L
  FILEOS 0x40004L
  FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
         BEGIN
         BEGIN
             VALUE "CompanyName", "\0"
             VALUE "CompanyName", "\0"
             VALUE "FileDescription", "SDL\0"
             VALUE "FileDescription", "SDL\0"
-            VALUE "FileVersion", "2, 28, 1, 0\0"
+            VALUE "FileVersion", "2, 28, 4, 0\0"
             VALUE "InternalName", "SDL\0"
             VALUE "InternalName", "SDL\0"
             VALUE "LegalCopyright", "Copyright (C) 2023 Sam Lantinga\0"
             VALUE "LegalCopyright", "Copyright (C) 2023 Sam Lantinga\0"
             VALUE "OriginalFilename", "SDL2.dll\0"
             VALUE "OriginalFilename", "SDL2.dll\0"
             VALUE "ProductName", "Simple DirectMedia Layer\0"
             VALUE "ProductName", "Simple DirectMedia Layer\0"
-            VALUE "ProductVersion", "2, 28, 1, 0\0"
+            VALUE "ProductVersion", "2, 28, 4, 0\0"
         END
         END
     END
     END
     BLOCK "VarFileInfo"
     BLOCK "VarFileInfo"

+ 3 - 5
libs/SDL2/src/misc/emscripten/SDL_sysurl.c

@@ -23,13 +23,11 @@
 
 
 #include <emscripten/emscripten.h>
 #include <emscripten/emscripten.h>
 
 
+EM_JS_DEPS(sdlsysurl, "$UTF8ToString");
+
 int SDL_SYS_OpenURL(const char *url)
 int SDL_SYS_OpenURL(const char *url)
 {
 {
-    EM_ASM({
-        window.open(UTF8ToString($0), "_blank");
-    },
-           url);
-
+    EM_ASM(window.open(UTF8ToString($0), "_blank"), url);
     return 0;
     return 0;
 }
 }
 
 

+ 13 - 0
libs/SDL2/src/misc/unix/SDL_sysurl.c

@@ -32,6 +32,18 @@ int SDL_SYS_OpenURL(const char *url)
 {
 {
     const pid_t pid1 = fork();
     const pid_t pid1 = fork();
     if (pid1 == 0) { /* child process */
     if (pid1 == 0) { /* child process */
+#ifdef USE_POSIX_SPAWN
+        pid_t pid2;
+        const char *args[] = { "xdg-open", url, NULL };
+        /* Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam */
+        unsetenv("LD_PRELOAD");
+        if (posix_spawnp(&pid2, args[0], NULL, NULL, (char **)args, environ) == 0) {
+            /* Child process doesn't wait for possibly-blocking grandchild. */
+            _exit(EXIT_SUCCESS);
+        } else {
+            _exit(EXIT_FAILURE);
+        }
+#else
         pid_t pid2;
         pid_t pid2;
         /* Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam */
         /* Clear LD_PRELOAD so Chrome opens correctly when this application is launched by Steam */
         unsetenv("LD_PRELOAD");
         unsetenv("LD_PRELOAD");
@@ -46,6 +58,7 @@ int SDL_SYS_OpenURL(const char *url)
             /* Child process doesn't wait for possibly-blocking grandchild. */
             /* Child process doesn't wait for possibly-blocking grandchild. */
             _exit(EXIT_SUCCESS);
             _exit(EXIT_SUCCESS);
         }
         }
+#endif /* USE_POSIX_SPAWN */
     } else if (pid1 < 0) {
     } else if (pid1 < 0) {
         return SDL_SetError("fork() failed: %s", strerror(errno));
         return SDL_SetError("fork() failed: %s", strerror(errno));
     } else {
     } else {

+ 1 - 1
libs/SDL2/src/render/SDL_render.c

@@ -2481,7 +2481,7 @@ int SDL_RenderSetClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
     int retval;
     int retval;
     CHECK_RENDERER_MAGIC(renderer, -1)
     CHECK_RENDERER_MAGIC(renderer, -1)
 
 
-    if (rect && rect->w > 0 && rect->h > 0) {
+    if (rect && rect->w >= 0 && rect->h >= 0) {
         renderer->clipping_enabled = SDL_TRUE;
         renderer->clipping_enabled = SDL_TRUE;
         renderer->clip_rect.x = (double)rect->x * renderer->scale.x;
         renderer->clip_rect.x = (double)rect->x * renderer->scale.x;
         renderer->clip_rect.y = (double)rect->y * renderer->scale.y;
         renderer->clip_rect.y = (double)rect->y * renderer->scale.y;

+ 1 - 1
libs/SDL2/src/render/direct3d11/SDL_render_d3d11.c

@@ -2143,7 +2143,7 @@ static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
     D3D11_BOX srcBox;
     D3D11_BOX srcBox;
     D3D11_MAPPED_SUBRESOURCE textureMemory;
     D3D11_MAPPED_SUBRESOURCE textureMemory;
 
 
-    ID3D11DeviceContext_OMGetRenderTargets(data->d3dContext, 1, &renderTargetView, NULL);
+    renderTargetView = D3D11_GetCurrentRenderTargetView(renderer);
     if (renderTargetView == NULL) {
     if (renderTargetView == NULL) {
         SDL_SetError("%s, ID3D11DeviceContext::OMGetRenderTargets failed", __FUNCTION__);
         SDL_SetError("%s, ID3D11DeviceContext::OMGetRenderTargets failed", __FUNCTION__);
         goto done;
         goto done;

+ 6 - 1
libs/SDL2/src/render/direct3d12/SDL_render_d3d12.c

@@ -2609,6 +2609,7 @@ static int D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
         case SDL_RENDERCMD_SETCLIPRECT:
         case SDL_RENDERCMD_SETCLIPRECT:
         {
         {
             const SDL_Rect *rect = &cmd->data.cliprect.rect;
             const SDL_Rect *rect = &cmd->data.cliprect.rect;
+            SDL_Rect viewport_cliprect;
             if (rendererData->currentCliprectEnabled != cmd->data.cliprect.enabled) {
             if (rendererData->currentCliprectEnabled != cmd->data.cliprect.enabled) {
                 rendererData->currentCliprectEnabled = cmd->data.cliprect.enabled;
                 rendererData->currentCliprectEnabled = cmd->data.cliprect.enabled;
                 rendererData->cliprectDirty = SDL_TRUE;
                 rendererData->cliprectDirty = SDL_TRUE;
@@ -2616,7 +2617,11 @@ static int D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
             if (!rendererData->currentCliprectEnabled) {
             if (!rendererData->currentCliprectEnabled) {
                 /* If the clip rect is disabled, then the scissor rect should be the whole viewport,
                 /* If the clip rect is disabled, then the scissor rect should be the whole viewport,
                    since direct3d12 doesn't allow disabling the scissor rectangle */
                    since direct3d12 doesn't allow disabling the scissor rectangle */
-                rect = &rendererData->currentViewport;
+                viewport_cliprect.x = 0;
+                viewport_cliprect.y = 0;
+                viewport_cliprect.w = rendererData->currentViewport.w;
+                viewport_cliprect.h = rendererData->currentViewport.h;
+                rect = &viewport_cliprect;
             }
             }
             if (SDL_memcmp(&rendererData->currentCliprect, rect, sizeof(*rect)) != 0) {
             if (SDL_memcmp(&rendererData->currentCliprect, rect, sizeof(*rect)) != 0) {
                 SDL_copyp(&rendererData->currentCliprect, rect);
                 SDL_copyp(&rendererData->currentCliprect, rect);

Vissa filer visades inte eftersom för många filer har ändrats