Explorar el Código

Update to SDL 1.0.11-0b98870c7f72.

woollybah hace 5 años
padre
commit
4701a2a9f2
Se han modificado 100 ficheros con 5725 adiciones y 1642 borrados
  1. 6 1
      sdl.mod/SDL/Android.mk
  2. 334 54
      sdl.mod/SDL/CMakeLists.txt
  3. 1 0
      sdl.mod/SDL/Makefile.in
  4. 4 1
      sdl.mod/SDL/Makefile.os2
  5. 2 1
      sdl.mod/SDL/SDL2.spec.in
  6. 1 4
      sdl.mod/SDL/VisualC/SDL/SDL.vcxproj
  7. 1 2
      sdl.mod/SDL/VisualC/SDL/SDL.vcxproj.filters
  8. 0 2
      sdl.mod/SDL/VisualC/SDLmain/SDLmain.vcxproj
  9. 0 2
      sdl.mod/SDL/VisualC/SDLtest/SDLtest.vcxproj
  10. 28 0
      sdl.mod/SDL/WhatsNew.txt
  11. 134 48
      sdl.mod/SDL/Xcode-iOS/Demos/Demos.xcodeproj/project.pbxproj
  12. 8 12
      sdl.mod/SDL/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
  13. 1 1
      sdl.mod/SDL/Xcode-iOS/Test/Info.plist
  14. 297 181
      sdl.mod/SDL/Xcode-iOS/Test/TestiPhoneOS.xcodeproj/project.pbxproj
  15. 2 2
      sdl.mod/SDL/Xcode/SDL/Info-Framework.plist
  16. 9 11
      sdl.mod/SDL/Xcode/SDL/SDL.xcodeproj/project.pbxproj
  17. 8 0
      sdl.mod/SDL/android-project/app/build.gradle
  18. 20 0
      sdl.mod/SDL/android-project/app/jni/CMakeLists.txt
  19. 13 0
      sdl.mod/SDL/android-project/app/jni/src/CMakeLists.txt
  20. 70 8
      sdl.mod/SDL/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
  21. 1 1
      sdl.mod/SDL/build-scripts/winrtbuild.ps1
  22. 38 0
      sdl.mod/SDL/cmake/sdlchecks.cmake
  23. 271 55
      sdl.mod/SDL/configure
  24. 220 49
      sdl.mod/SDL/configure.ac
  25. 12 0
      sdl.mod/SDL/debian/changelog
  26. 19 0
      sdl.mod/SDL/docs/README-android.md
  27. 53 1
      sdl.mod/SDL/docs/README-cmake.md
  28. 5 2
      sdl.mod/SDL/docs/README-winrt.md
  29. 1 0
      sdl.mod/SDL/include/SDL.h
  30. 18 0
      sdl.mod/SDL/include/SDL_atomic.h
  31. 46 13
      sdl.mod/SDL/include/SDL_audio.h
  32. 14 1
      sdl.mod/SDL/include/SDL_config.h.cmake
  33. 12 5
      sdl.mod/SDL/include/SDL_config.h.in
  34. 4 0
      sdl.mod/SDL/include/SDL_config_iphoneos.h
  35. 28 11
      sdl.mod/SDL/include/SDL_config_macosx.h
  36. 2 3
      sdl.mod/SDL/include/SDL_config_windows.h
  37. 0 1
      sdl.mod/SDL/include/SDL_config_winrt.h
  38. 72 4
      sdl.mod/SDL/include/SDL_cpuinfo.h
  39. 3 0
      sdl.mod/SDL/include/SDL_egl.h
  40. 5 2
      sdl.mod/SDL/include/SDL_endian.h
  41. 5 1
      sdl.mod/SDL/include/SDL_events.h
  42. 93 11
      sdl.mod/SDL/include/SDL_hints.h
  43. 2 2
      sdl.mod/SDL/include/SDL_keycode.h
  44. 2 2
      sdl.mod/SDL/include/SDL_log.h
  45. 5 3
      sdl.mod/SDL/include/SDL_messagebox.h
  46. 91 0
      sdl.mod/SDL/include/SDL_metal.h
  47. 3 0
      sdl.mod/SDL/include/SDL_opengl_glext.h
  48. 10 10
      sdl.mod/SDL/include/SDL_pixels.h
  49. 21 0
      sdl.mod/SDL/include/SDL_render.h
  50. 49 12
      sdl.mod/SDL/include/SDL_rwops.h
  51. 4 1
      sdl.mod/SDL/include/SDL_stdinc.h
  52. 3 0
      sdl.mod/SDL/include/SDL_syswm.h
  53. 1 1
      sdl.mod/SDL/include/SDL_version.h
  54. 0 1
      sdl.mod/SDL/include/SDL_video.h
  55. 3 3
      sdl.mod/SDL/include/SDL_vulkan.h
  56. 3 0
      sdl.mod/SDL/include/begin_code.h
  57. 36 0
      sdl.mod/SDL/src/SDL.c
  58. 12 29
      sdl.mod/SDL/src/SDL_assert.c
  59. 0 10
      sdl.mod/SDL/src/SDL_error.c
  60. 2 2
      sdl.mod/SDL/src/SDL_log.c
  61. 4 0
      sdl.mod/SDL/src/atomic/SDL_atomic.c
  62. 12 14
      sdl.mod/SDL/src/audio/SDL_audio.c
  63. 16 6
      sdl.mod/SDL/src/audio/SDL_audiocvt.c
  64. 21 22
      sdl.mod/SDL/src/audio/SDL_audiotypecvt.c
  65. 0 1
      sdl.mod/SDL/src/audio/SDL_sysaudio.h
  66. 2024 565
      sdl.mod/SDL/src/audio/SDL_wave.c
  67. 103 31
      sdl.mod/SDL/src/audio/SDL_wave.h
  68. 21 13
      sdl.mod/SDL/src/audio/alsa/SDL_alsa_audio.c
  69. 34 4
      sdl.mod/SDL/src/audio/coreaudio/SDL_coreaudio.m
  70. 47 126
      sdl.mod/SDL/src/audio/netbsd/SDL_netbsdaudio.c
  71. 40 14
      sdl.mod/SDL/src/audio/openslES/SDL_openslES.c
  72. 4 4
      sdl.mod/SDL/src/audio/qsa/SDL_qsa_audio.c
  73. 3 19
      sdl.mod/SDL/src/audio/wasapi/SDL_wasapi.c
  74. 1 1
      sdl.mod/SDL/src/audio/winmm/SDL_winmm.c
  75. 78 20
      sdl.mod/SDL/src/core/android/SDL_android.c
  76. 6 0
      sdl.mod/SDL/src/core/android/SDL_android.h
  77. 20 8
      sdl.mod/SDL/src/core/linux/SDL_dbus.c
  78. 57 22
      sdl.mod/SDL/src/core/linux/SDL_evdev.c
  79. 0 1
      sdl.mod/SDL/src/core/linux/SDL_evdev_kbd.c
  80. 13 9
      sdl.mod/SDL/src/core/linux/SDL_threadprio.c
  81. 7 0
      sdl.mod/SDL/src/core/linux/SDL_udev.c
  82. 65 4
      sdl.mod/SDL/src/cpuinfo/SDL_cpuinfo.c
  83. 0 88
      sdl.mod/SDL/src/cpuinfo/SDL_simd.h
  84. 42 13
      sdl.mod/SDL/src/dynapi/SDL_dynapi.c
  85. 14 0
      sdl.mod/SDL/src/dynapi/SDL_dynapi_overrides.h
  86. 15 1
      sdl.mod/SDL/src/dynapi/SDL_dynapi_procs.h
  87. 3 3
      sdl.mod/SDL/src/dynapi/gendynapi.pl
  88. 9 9
      sdl.mod/SDL/src/events/SDL_events.c
  89. 45 36
      sdl.mod/SDL/src/events/SDL_gesture.c
  90. 2 2
      sdl.mod/SDL/src/events/SDL_keyboard.c
  91. 43 24
      sdl.mod/SDL/src/events/SDL_mouse.c
  92. 1 0
      sdl.mod/SDL/src/events/SDL_mouse_c.h
  93. 36 8
      sdl.mod/SDL/src/events/SDL_touch.c
  94. 2 2
      sdl.mod/SDL/src/events/SDL_touch_c.h
  95. 61 3
      sdl.mod/SDL/src/file/SDL_rwops.c
  96. 21 0
      sdl.mod/SDL/src/filesystem/cocoa/SDL_sysfilesystem.m
  97. 1 1
      sdl.mod/SDL/src/filesystem/unix/SDL_sysfilesystem.c
  98. 1 1
      sdl.mod/SDL/src/hidapi/AUTHORS.txt
  99. 1 1
      sdl.mod/SDL/src/hidapi/README.txt
  100. 744 0
      sdl.mod/SDL/src/hidapi/SDL_hidapi.c

+ 6 - 1
sdl.mod/SDL/Android.mk

@@ -64,7 +64,12 @@ LOCAL_CFLAGS += \
 	-Wmissing-variable-declarations \
 	-Wmissing-variable-declarations \
 	-Wfloat-conversion \
 	-Wfloat-conversion \
 	-Wshorten-64-to-32 \
 	-Wshorten-64-to-32 \
-	-Wunreachable-code-return
+	-Wunreachable-code-return \
+	-Wshift-sign-overflow \
+	-Wunused-macros \
+	-Wstrict-prototypes \
+	-Wkeyword-macro \
+
 
 
 # Warnings we haven't fixed (yet)
 # Warnings we haven't fixed (yet)
 LOCAL_CFLAGS += -Wno-unused-parameter -Wno-sign-compare
 LOCAL_CFLAGS += -Wno-unused-parameter -Wno-sign-compare

+ 334 - 54
sdl.mod/SDL/CMakeLists.txt

@@ -42,9 +42,9 @@ include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
 # set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
 # set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
 set(SDL_MAJOR_VERSION 2)
 set(SDL_MAJOR_VERSION 2)
 set(SDL_MINOR_VERSION 0)
 set(SDL_MINOR_VERSION 0)
-set(SDL_MICRO_VERSION 9)
+set(SDL_MICRO_VERSION 11)
 set(SDL_INTERFACE_AGE 0)
 set(SDL_INTERFACE_AGE 0)
-set(SDL_BINARY_AGE 9)
+set(SDL_BINARY_AGE 11)
 set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
 set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
 # the following should match the versions in Xcode project file:
 # the following should match the versions in Xcode project file:
 set(DYLIB_CURRENT_VERSION 10.0.0)
 set(DYLIB_CURRENT_VERSION 10.0.0)
@@ -118,6 +118,8 @@ elseif(APPLE)
     set(DARWIN TRUE)
     set(DARWIN TRUE)
   elseif(CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*")
   elseif(CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*")
     set(MACOSX TRUE)
     set(MACOSX TRUE)
+  elseif(CMAKE_SYSTEM_NAME MATCHES ".*tvOS.*")
+    set(TVOS TRUE)
   endif()
   endif()
   # TODO: iOS?
   # TODO: iOS?
 elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*")
 elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*")
@@ -155,6 +157,27 @@ if(UNIX OR MINGW OR MSYS)
   set(OPT_DEF_LIBC ON)
   set(OPT_DEF_LIBC ON)
 endif()
 endif()
 
 
+# The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers,
+#  so we'll just use libusb when it's available. libusb does not support iOS,
+#  so we default to yes on iOS.
+#  TODO: Windows can support libusb, the hid.c file just depends on Unix APIs
+if(WINDOWS OR IOS OR TVOS OR ANDROID)
+  set(HIDAPI_SKIP_LIBUSB TRUE)
+else()
+  set(HIDAPI_SKIP_LIBUSB FALSE)
+endif()
+if (HIDAPI_SKIP_LIBUSB)
+  set(OPT_DEF_HIDAPI ON)
+endif()
+
+# On the other hand, *BSD specifically uses libusb only, so we make a special
+#  case just for them.
+if(FREEBSD OR NETBSD OR OPENBSD OR BSDI)
+  set(HIDAPI_ONLY_LIBUSB TRUE)
+else()
+  set(HIDAPI_ONLY_LIBUSB FALSE)
+endif()
+
 # Compiler info
 # Compiler info
 if(CMAKE_COMPILER_IS_GNUCC)
 if(CMAKE_COMPILER_IS_GNUCC)
   set(USE_GCC TRUE)
   set(USE_GCC TRUE)
@@ -264,8 +287,23 @@ if(EMSCRIPTEN)
   set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF)
   set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF)
 endif()
 endif()
 
 
+# When defined, respect CMake's BUILD_SHARED_LIBS setting:
+set(SDL_STATIC_ENABLED_BY_DEFAULT ON)
 if (NOT DEFINED SDL_SHARED_ENABLED_BY_DEFAULT)
 if (NOT DEFINED SDL_SHARED_ENABLED_BY_DEFAULT)
+  # ...unless decided already (as for EMSCRIPTEN)
+
+  set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
+
+  if (NOT DEFINED BUILD_SHARED_LIBS)
+    # No preference? Build both, just like the AC/AM configure
+    set(SDL_SHARED_ENABLED_BY_DEFAULT ON)
+
+  elseif (BUILD_SHARED_LIBS)
+    # In this case, we assume the user wants a shared lib and don't build
+    # the static one
     set(SDL_SHARED_ENABLED_BY_DEFAULT ON)
     set(SDL_SHARED_ENABLED_BY_DEFAULT ON)
+    set(SDL_STATIC_ENABLED_BY_DEFAULT OFF)
+  endif()
 endif()
 endif()
 
 
 set(SDL_SUBSYSTEMS
 set(SDL_SUBSYSTEMS
@@ -291,6 +329,8 @@ set_option(SSE                 "Use SSE assembly routines" ${OPT_DEF_ASM})
 set_option(SSE2                "Use SSE2 assembly routines" ${OPT_DEF_SSEMATH})
 set_option(SSE2                "Use SSE2 assembly routines" ${OPT_DEF_SSEMATH})
 set_option(SSE3                "Use SSE3 assembly routines" ${OPT_DEF_SSEMATH})
 set_option(SSE3                "Use SSE3 assembly routines" ${OPT_DEF_SSEMATH})
 set_option(ALTIVEC             "Use Altivec assembly routines" ${OPT_DEF_ASM})
 set_option(ALTIVEC             "Use Altivec assembly routines" ${OPT_DEF_ASM})
+set_option(ARMSIMD             "use SIMD assembly blitters on ARM" ON)
+set_option(ARMNEON             "use NEON assembly blitters on ARM" ON)
 set_option(DISKAUDIO           "Support the disk writer audio driver" ON)
 set_option(DISKAUDIO           "Support the disk writer audio driver" ON)
 set_option(DUMMYAUDIO          "Support the dummy audio driver" ON)
 set_option(DUMMYAUDIO          "Support the dummy audio driver" ON)
 set_option(VIDEO_DIRECTFB      "Use DirectFB video driver" OFF)
 set_option(VIDEO_DIRECTFB      "Use DirectFB video driver" OFF)
@@ -337,17 +377,19 @@ set_option(VIDEO_COCOA         "Use Cocoa video driver" ${APPLE})
 set_option(DIRECTX             "Use DirectX for Windows audio/video" ${WINDOWS})
 set_option(DIRECTX             "Use DirectX for Windows audio/video" ${WINDOWS})
 set_option(WASAPI              "Use the Windows WASAPI audio driver" ${WINDOWS})
 set_option(WASAPI              "Use the Windows WASAPI audio driver" ${WINDOWS})
 set_option(RENDER_D3D          "Enable the Direct3D render driver" ${WINDOWS})
 set_option(RENDER_D3D          "Enable the Direct3D render driver" ${WINDOWS})
+set_option(RENDER_METAL        "Enable the Metal render driver" ${APPLE})
 set_option(VIDEO_VIVANTE       "Use Vivante EGL video driver" ${UNIX_SYS})
 set_option(VIDEO_VIVANTE       "Use Vivante EGL video driver" ${UNIX_SYS})
 dep_option(VIDEO_VULKAN        "Enable Vulkan support" ON "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF)
 dep_option(VIDEO_VULKAN        "Enable Vulkan support" ON "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF)
+set_option(VIDEO_METAL         "Enable Metal support" ${APPLE})
 set_option(VIDEO_KMSDRM        "Use KMS DRM video driver" ${UNIX_SYS})
 set_option(VIDEO_KMSDRM        "Use KMS DRM video driver" ${UNIX_SYS})
 dep_option(KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF)
 dep_option(KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF)
+set_option(VIDEO_OFFSCREEN     "Use offscreen video driver" OFF)
 option_string(BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" "OFF")
 option_string(BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" "OFF")
 option_string(FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" "OFF")
 option_string(FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" "OFF")
+set_option(HIDAPI              "Use HIDAPI for low level joystick drivers" ${OPT_DEF_HIDAPI})
 
 
-# TODO: We should (should we?) respect cmake's ${BUILD_SHARED_LIBS} flag here
-# The options below are for compatibility to configure's default behaviour.
 set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
 set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
-set(SDL_STATIC ON CACHE BOOL "Build a static version of the library")
+set(SDL_STATIC ${SDL_STATIC_ENABLED_BY_DEFAULT} CACHE BOOL "Build a static version of the library")
 
 
 dep_option(SDL_STATIC_PIC      "Static version of the library should be built with Position Independent Code" OFF "SDL_STATIC" OFF)
 dep_option(SDL_STATIC_PIC      "Static version of the library should be built with Position Independent Code" OFF "SDL_STATIC" OFF)
 set_option(SDL_TEST            "Build the test directory" OFF)
 set_option(SDL_TEST            "Build the test directory" OFF)
@@ -405,6 +447,11 @@ if(USE_GCC OR USE_CLANG)
     endif()
     endif()
   endif()
   endif()
 
 
+  check_c_compiler_flag(-fno-strict-aliasing HAVE_GCC_NO_STRICT_ALIASING)
+  if(HAVE_GCC_NO_STRICT_ALIASING)
+    list(APPEND EXTRA_CFLAGS "-fno-strict-aliasing")
+  endif()
+
   check_c_compiler_flag(-Wdeclaration-after-statement HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
   check_c_compiler_flag(-Wdeclaration-after-statement HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
   if(HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
   if(HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
     check_c_compiler_flag(-Werror=declaration-after-statement HAVE_GCC_WERROR_DECLARATION_AFTER_STATEMENT)
     check_c_compiler_flag(-Werror=declaration-after-statement HAVE_GCC_WERROR_DECLARATION_AFTER_STATEMENT)
@@ -626,6 +673,61 @@ if(ASSEMBLY)
         endif()
         endif()
       endif()
       endif()
     endif()
     endif()
+
+    if(ARMSIMD)
+      set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+      set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -x assembler-with-cpp")
+      check_c_source_compiles("
+        .text
+        .arch armv6
+        .object_arch armv4
+        .arm
+        .altmacro
+        #ifndef __ARM_EABI__
+        #error EABI is required (to be sure that calling conventions are compatible)
+        #endif
+        pld [r0]
+        uqadd8 r0, r0, r0
+      " ARMSIMD_FOUND)
+      set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
+
+      if(ARMSIMD_FOUND)
+        set(HAVE_ARMSIMD TRUE)
+        set(SDL_ARM_SIMD_BLITTERS 1)
+        file(GLOB ARMSIMD_SOURCES ${SDL2_SOURCE_DIR}/src/video/arm/pixman-arm-simd*.S)
+        set(SOURCE_FILES ${SOURCE_FILES} ${ARMSIMD_SOURCES})
+        set(WARN_ABOUT_ARM_SIMD_ASM_MIT TRUE)
+      endif()
+    endif()
+
+    if(ARMNEON)
+      set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+      set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -x assembler-with-cpp")
+      check_c_source_compiles("
+        .text
+        .fpu neon
+        .arch armv7a
+        .object_arch armv4
+        .eabi_attribute 10, 0
+        .arm
+        .altmacro
+        #ifndef __ARM_EABI__
+        #error EABI is required (to be sure that calling conventions are compatible)
+        #endif
+        pld [r0]
+        vmovn.u16 d0, q0
+      " ARMNEON_FOUND)
+      set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
+
+      if(ARMNEON_FOUND)
+        set(HAVE_ARMNEON TRUE)
+        set(SDL_ARM_NEON_BLITTERS 1)
+        file(GLOB ARMNEON_SOURCES ${SDL2_SOURCE_DIR}/src/video/arm/pixman-arm-neon*.S)
+        set(SOURCE_FILES ${SOURCE_FILES} ${ARMNEON_SOURCES})
+        set(WARN_ABOUT_ARM_NEON_ASM_MIT TRUE)
+      endif()
+    endif()
+
   elseif(MSVC_VERSION GREATER 1500)
   elseif(MSVC_VERSION GREATER 1500)
     # TODO: SDL_cpuinfo.h needs to support the user's configuration wish
     # TODO: SDL_cpuinfo.h needs to support the user's configuration wish
     # for MSVC - right now it is always activated
     # for MSVC - right now it is always activated
@@ -808,8 +910,16 @@ if(SDL_VIDEO)
     set(HAVE_VIDEO_DUMMY TRUE)
     set(HAVE_VIDEO_DUMMY TRUE)
     set(HAVE_SDL_VIDEO TRUE)
     set(HAVE_SDL_VIDEO TRUE)
   endif()
   endif()
+  if(VIDEO_OFFSCREEN)
+    set(SDL_VIDEO_DRIVER_OFFSCREEN 1)
+    file(GLOB VIDEO_OFFSCREEN_SOURCES ${SDL2_SOURCE_DIR}/src/video/offscreen/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${VIDEO_OFFSCREEN_SOURCES})
+    set(HAVE_VIDEO_OFFSCREEN TRUE)
+    set(HAVE_SDL_VIDEO TRUE)
+  endif()
 endif()
 endif()
 
 
+# Platform-specific options and settings
 if(ANDROID)
 if(ANDROID)
   file(GLOB ANDROID_CORE_SOURCES ${SDL2_SOURCE_DIR}/src/core/android/*.c)
   file(GLOB ANDROID_CORE_SOURCES ${SDL2_SOURCE_DIR}/src/core/android/*.c)
   set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_CORE_SOURCES})
   set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_CORE_SOURCES})
@@ -845,6 +955,7 @@ if(ANDROID)
     set(HAVE_SDL_HAPTIC TRUE)
     set(HAVE_SDL_HAPTIC TRUE)
   endif()
   endif()
   if(SDL_JOYSTICK)
   if(SDL_JOYSTICK)
+    CheckHIDAPI()
     set(SDL_JOYSTICK_ANDROID 1)
     set(SDL_JOYSTICK_ANDROID 1)
     file(GLOB ANDROID_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/android/*.c ${SDL2_SOURCE_DIR}/src/joystick/steam/*.c)
     file(GLOB ANDROID_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/android/*.c ${SDL2_SOURCE_DIR}/src/joystick/steam/*.c)
     set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_JOYSTICK_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_JOYSTICK_SOURCES})
@@ -881,16 +992,24 @@ if(ANDROID)
     set(HAVE_SDL_VIDEO TRUE)
     set(HAVE_SDL_VIDEO TRUE)
 
 
     # Core stuff
     # Core stuff
-    find_library(ANDROID_DL_LIBRARY dl)
+    # find_library(ANDROID_DL_LIBRARY dl)
+    # FIXME failing dlopen https://github.com/android-ndk/ndk/issues/929
+    find_library(ANDROID_DL_LIBRARY NAMES libdl.so dl)
     find_library(ANDROID_LOG_LIBRARY log)
     find_library(ANDROID_LOG_LIBRARY log)
     find_library(ANDROID_LIBRARY_LIBRARY android)
     find_library(ANDROID_LIBRARY_LIBRARY android)
     list(APPEND EXTRA_LIBS ${ANDROID_DL_LIBRARY} ${ANDROID_LOG_LIBRARY} ${ANDROID_LIBRARY_LIBRARY})
     list(APPEND EXTRA_LIBS ${ANDROID_DL_LIBRARY} ${ANDROID_LOG_LIBRARY} ${ANDROID_LIBRARY_LIBRARY})
     add_definitions(-DGL_GLEXT_PROTOTYPES)
     add_definitions(-DGL_GLEXT_PROTOTYPES)
 
 
+    if (HAVE_HIDAPI)
+        list(APPEND EXTRA_LIBS hidapi)
+    endif()
+
     #enable gles
     #enable gles
     if(VIDEO_OPENGLES)
     if(VIDEO_OPENGLES)
       set(SDL_VIDEO_OPENGL_EGL 1)
       set(SDL_VIDEO_OPENGL_EGL 1)
       set(HAVE_VIDEO_OPENGLES TRUE)
       set(HAVE_VIDEO_OPENGLES TRUE)
+      set(SDL_VIDEO_OPENGL_ES 1)
+      set(SDL_VIDEO_RENDER_OGL_ES 1)
       set(SDL_VIDEO_OPENGL_ES2 1)
       set(SDL_VIDEO_OPENGL_ES2 1)
       set(SDL_VIDEO_RENDER_OGL_ES2 1)
       set(SDL_VIDEO_RENDER_OGL_ES2 1)
 
 
@@ -914,14 +1033,9 @@ if(ANDROID)
     endif()
     endif()
   endif()
   endif()
 
 
-  file(GLOB ANDROID_HIDAPI_SOURCES ${SDL2_SOURCE_DIR}/src/hidapi/android/*.cpp)
-
   CheckPTHREAD()
   CheckPTHREAD()
 
 
-endif()
-
-# Platform-specific options and settings
-if(EMSCRIPTEN)
+elseif(EMSCRIPTEN)
   # Hide noisy warnings that intend to aid mostly during initial stages of porting a new
   # Hide noisy warnings that intend to aid mostly during initial stages of porting a new
   # project. Uncomment at will for verbose cross-compiling -I/../ path info.
   # project. Uncomment at will for verbose cross-compiling -I/../ path info.
   add_definitions(-Wno-warn-absolute-paths)
   add_definitions(-Wno-warn-absolute-paths)
@@ -973,6 +1087,7 @@ if(EMSCRIPTEN)
       set(SDL_VIDEO_RENDER_OGL_ES2 1)
       set(SDL_VIDEO_RENDER_OGL_ES2 1)
     endif()
     endif()
   endif()
   endif()
+
 elseif(UNIX AND NOT APPLE AND NOT ANDROID)
 elseif(UNIX AND NOT APPLE AND NOT ANDROID)
   if(SDL_AUDIO)
   if(SDL_AUDIO)
     if(SYSV5 OR SOLARIS OR HPUX)
     if(SYSV5 OR SOLARIS OR HPUX)
@@ -1072,6 +1187,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID)
         set(HAVE_IBUS_IBUS_H TRUE)
         set(HAVE_IBUS_IBUS_H TRUE)
         include_directories(${IBUS_INCLUDE_DIRS})
         include_directories(${IBUS_INCLUDE_DIRS})
         list(APPEND EXTRA_LIBS ${IBUS_LIBRARIES})
         list(APPEND EXTRA_LIBS ${IBUS_LIBRARIES})
+        add_definitions(-DSDL_USE_IME)
       endif()
       endif()
       if(HAVE_LIBUNWIND_H)
       if(HAVE_LIBUNWIND_H)
         # We've already found the header, so REQUIRE the lib to be present
         # We've already found the header, so REQUIRE the lib to be present
@@ -1095,7 +1211,10 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID)
   endif()
   endif()
 
 
   if(SDL_JOYSTICK)
   if(SDL_JOYSTICK)
-    CheckUSBHID()   # seems to be BSD specific - limit the test to BSD only?
+    if(FREEBSD OR NETBSD OR OPENBSD OR BSDI)
+      CheckUSBHID()
+    endif()
+    CheckHIDAPI()
     if(LINUX AND NOT ANDROID)
     if(LINUX AND NOT ANDROID)
       set(SDL_JOYSTICK_LINUX 1)
       set(SDL_JOYSTICK_LINUX 1)
       file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/linux/*.c ${SDL2_SOURCE_DIR}/src/joystick/steam/*.c)
       file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/linux/*.c ${SDL2_SOURCE_DIR}/src/joystick/steam/*.c)
@@ -1232,10 +1351,9 @@ elseif(WINDOWS)
     set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
     set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   endif()
   endif()
 
 
-  # headers needed elsewhere ...
+  # headers needed elsewhere
   check_include_file(mmdeviceapi.h HAVE_MMDEVICEAPI_H)
   check_include_file(mmdeviceapi.h HAVE_MMDEVICEAPI_H)
   check_include_file(audioclient.h HAVE_AUDIOCLIENT_H)
   check_include_file(audioclient.h HAVE_AUDIOCLIENT_H)
-  check_include_file(endpointvolume.h HAVE_ENDPOINTVOLUME_H)
 
 
   if(SDL_AUDIO)
   if(SDL_AUDIO)
     set(SDL_AUDIO_DRIVER_WINMM 1)
     set(SDL_AUDIO_DRIVER_WINMM 1)
@@ -1301,7 +1419,7 @@ elseif(WINDOWS)
   endif()
   endif()
 
 
   # Libraries for Win32 native and MinGW
   # Libraries for Win32 native and MinGW
-  list(APPEND EXTRA_LIBS user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 shell32)
+  list(APPEND EXTRA_LIBS user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32)
 
 
   # TODO: in configure.ac the check for timers is set on
   # TODO: in configure.ac the check for timers is set on
   # cygwin | mingw32* - does this include mingw32CE?
   # cygwin | mingw32* - does this include mingw32CE?
@@ -1339,6 +1457,11 @@ elseif(WINDOWS)
   endif()
   endif()
 
 
   if(SDL_JOYSTICK)
   if(SDL_JOYSTICK)
+    CheckHIDAPI()
+    # TODO: Remove this hid.c block when SDL_hidapi.c is supported on Windows!
+    if(HAVE_HIDAPI)
+      set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/hidapi/windows/hid.c)
+    endif()
     file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/windows/*.c)
     file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/windows/*.c)
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     if(HAVE_DINPUT_H)
     if(HAVE_DINPUT_H)
@@ -1384,6 +1507,7 @@ elseif(WINDOWS)
     set(SDL_CFLAGS "${SDL_CFLAGS} -Dmain=SDL_main")
     set(SDL_CFLAGS "${SDL_CFLAGS} -Dmain=SDL_main")
     list(APPEND SDL_LIBS "-lmingw32" "-lSDL2main" "-mwindows")
     list(APPEND SDL_LIBS "-lmingw32" "-lSDL2main" "-mwindows")
   endif()
   endif()
+
 elseif(APPLE)
 elseif(APPLE)
   # TODO: rework this all for proper MacOS X, iOS and Darwin support
   # TODO: rework this all for proper MacOS X, iOS and Darwin support
 
 
@@ -1391,10 +1515,11 @@ elseif(APPLE)
   # !!! FIXME: we need Carbon for some very old API calls in
   # !!! FIXME: we need Carbon for some very old API calls in
   # !!! FIXME:  src/video/cocoa/SDL_cocoakeyboard.c, but we should figure out
   # !!! FIXME:  src/video/cocoa/SDL_cocoakeyboard.c, but we should figure out
   # !!! FIXME:  how to dump those.
   # !!! FIXME:  how to dump those.
-  if(NOT IOS)
+  if(DARWIN OR MACOSX)
     set(SDL_FRAMEWORK_COCOA 1)
     set(SDL_FRAMEWORK_COCOA 1)
     set(SDL_FRAMEWORK_CARBON 1)
     set(SDL_FRAMEWORK_CARBON 1)
   endif()
   endif()
+  set(SDL_FRAMEWORK_FOUNDATION 1)
 
 
   # Requires the darwin file implementation
   # Requires the darwin file implementation
   if(SDL_FILE)
   if(SDL_FILE)
@@ -1418,48 +1543,63 @@ elseif(APPLE)
     set(HAVE_SDL_AUDIO TRUE)
     set(HAVE_SDL_AUDIO TRUE)
     set(SDL_FRAMEWORK_COREAUDIO 1)
     set(SDL_FRAMEWORK_COREAUDIO 1)
     set(SDL_FRAMEWORK_AUDIOTOOLBOX 1)
     set(SDL_FRAMEWORK_AUDIOTOOLBOX 1)
+    set(SDL_FRAMEWORK_AVFOUNDATION 1)
   endif()
   endif()
 
 
   if(SDL_JOYSTICK)
   if(SDL_JOYSTICK)
-    set(SDL_JOYSTICK_IOKIT 1)
-    if (IOS)
+    CheckHIDAPI()
+    if(HAVE_HIDAPI)
+      if(IOS OR TVOS)
+        set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/hidapi/ios/hid.m)
+        set(SDL_FRAMEWORK_COREBLUETOOTH 1)
+      endif()
+    endif()
+    if(IOS OR TVOS)
       file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m ${SDL2_SOURCE_DIR}/src/joystick/steam/*.c)
       file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m ${SDL2_SOURCE_DIR}/src/joystick/steam/*.c)
+      set(SDL_JOYSTICK_MFI 1)
+      if(IOS)
+        set(SDL_FRAMEWORK_COREMOTION 1)
+      endif()
+      set(SDL_FRAMEWORK_GAMECONTROLLER 1)
+      set(HAVE_SDL_SENSORS 1)
     else()
     else()
       file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/darwin/*.c)
       file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/darwin/*.c)
+      set(SDL_JOYSTICK_IOKIT 1)
+      set(SDL_FRAMEWORK_IOKIT 1)
+      set(SDL_FRAMEWORK_FF 1)
     endif()
     endif()
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     set(HAVE_SDL_JOYSTICK TRUE)
     set(HAVE_SDL_JOYSTICK TRUE)
-    set(SDL_FRAMEWORK_IOKIT 1)
-    set(SDL_FRAMEWORK_FF 1)
   endif()
   endif()
 
 
   if(SDL_HAPTIC)
   if(SDL_HAPTIC)
-    set(SDL_HAPTIC_IOKIT 1)
-    if (IOS)
+    if (IOS OR TVOS)
       file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/dummy/*.c)
       file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/dummy/*.c)
       set(SDL_HAPTIC_DUMMY 1)
       set(SDL_HAPTIC_DUMMY 1)
     else()
     else()
       file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/darwin/*.c)
       file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/darwin/*.c)
+      set(SDL_HAPTIC_IOKIT 1)
+      set(SDL_FRAMEWORK_IOKIT 1)
+      set(SDL_FRAMEWORK_FF 1)
     endif()
     endif()
     set(SOURCE_FILES ${SOURCE_FILES} ${HAPTIC_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${HAPTIC_SOURCES})
     set(HAVE_SDL_HAPTIC TRUE)
     set(HAVE_SDL_HAPTIC TRUE)
-    set(SDL_FRAMEWORK_IOKIT 1)
-    set(SDL_FRAMEWORK_FF 1)
     if(NOT SDL_JOYSTICK)
     if(NOT SDL_JOYSTICK)
       message(FATAL_ERROR "SDL_HAPTIC requires SDL_JOYSTICK to be enabled")
       message(FATAL_ERROR "SDL_HAPTIC requires SDL_JOYSTICK to be enabled")
     endif()
     endif()
   endif()
   endif()
 
 
   if(SDL_POWER)
   if(SDL_POWER)
-    set(SDL_POWER_MACOSX 1)
-    if (IOS)
+    if (IOS OR TVOS)
       file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m)
       file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m)
+      set(SDL_POWER_UIKIT 1)
     else()
     else()
       file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/macosx/*.c)
       file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/macosx/*.c)
+      set(SDL_POWER_MACOSX 1)
+      set(SDL_FRAMEWORK_IOKIT 1)
     endif()
     endif()
     set(SOURCE_FILES ${SOURCE_FILES} ${POWER_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${POWER_SOURCES})
     set(HAVE_SDL_POWER TRUE)
     set(HAVE_SDL_POWER TRUE)
-    set(SDL_FRAMEWORK_IOKIT 1)
   endif()
   endif()
 
 
   if(SDL_TIMERS)
   if(SDL_TIMERS)
@@ -1478,6 +1618,89 @@ elseif(APPLE)
     set(HAVE_SDL_FILESYSTEM TRUE)
     set(HAVE_SDL_FILESYSTEM TRUE)
   endif()
   endif()
 
 
+  if(SDL_SENSOR)
+    if(IOS)
+      set(SDL_SENSOR_COREMOTION 1)
+      set(HAVE_SDL_SENSORS TRUE)
+      file(GLOB SENSOR_SOURCES ${SDL2_SOURCE_DIR}/src/sensor/coremotion/*.m)
+      set(SOURCE_FILES ${SOURCE_FILES} ${SENSOR_SOURCES})
+    endif()
+  endif()
+
+  # iOS hack needed - http://code.google.com/p/ios-cmake/ ?
+  if(SDL_VIDEO)
+    if (IOS OR TVOS)
+      set(SDL_VIDEO_DRIVER_UIKIT 1)
+      set(SDL_FRAMEWORK_COREGRAPHICS 1)
+      set(SDL_FRAMEWORK_QUARTZCORE 1)
+      set(SDL_FRAMEWORK_UIKIT 1)
+      set(SDL_IPHONE_KEYBOARD 1)
+      set(SDL_IPHONE_LAUNCHSCREEN 1)
+      file(GLOB UIKITVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/uikit/*.m)
+      set(SOURCE_FILES ${SOURCE_FILES} ${UIKITVIDEO_SOURCES})
+    else()
+      CheckCOCOA()
+      if(VIDEO_OPENGL)
+        set(SDL_VIDEO_OPENGL 1)
+        set(SDL_VIDEO_OPENGL_CGL 1)
+        set(SDL_VIDEO_RENDER_OGL 1)
+        set(HAVE_VIDEO_OPENGL TRUE)
+      endif()
+    endif()
+
+    if(VIDEO_OPENGLES)
+      if(IOS OR TVOS)
+        set(SDL_FRAMEWORK_OPENGLES 1)
+        set(SDL_VIDEO_OPENGL_ES 1)
+        set(SDL_VIDEO_RENDER_OGL_ES 1)
+      else()
+        set(SDL_VIDEO_OPENGL_EGL 1)
+      endif()
+      set(SDL_VIDEO_OPENGL_ES2 1)
+      set(SDL_VIDEO_RENDER_OGL_ES2 1)
+      set(HAVE_VIDEO_OPENGLES TRUE)
+    endif()
+
+    if(VIDEO_VULKAN OR VIDEO_METAL OR RENDER_METAL)
+      set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+      set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -x objective-c")
+      check_c_source_compiles("
+        #include <AvailabilityMacros.h>
+        #import <Metal/Metal.h>
+        #import <QuartzCore/CAMetalLayer.h>
+
+        #if TARGET_OS_SIMULATOR || (!TARGET_CPU_X86_64 && !TARGET_CPU_ARM64)
+        #error Metal doesn't work on this configuration
+        #endif
+        int main()
+        {
+            return 0;
+        }
+        " HAVE_FRAMEWORK_METAL)
+      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+      if(HAVE_FRAMEWORK_METAL)
+        set(SDL_FRAMEWORK_METAL 1)
+        set(SDL_FRAMEWORK_QUARTZCORE 1)
+      else()
+        set(VIDEO_VULKAN 0)
+        set(VIDEO_METAL 0)
+        set(RENDER_METAL 0)
+      endif()
+    endif()
+
+    if(VIDEO_METAL)
+      set(SDL_VIDEO_METAL 1)
+      set(HAVE_VIDEO_METAL TRUE)
+    endif()
+
+    if(RENDER_METAL)
+      file(GLOB RENDER_METAL_SOURCES ${SDL2_SOURCE_DIR}/src/render/metal/*.m)
+      set(SOURCE_FILES ${SOURCE_FILES} ${RENDER_METAL_SOURCES})
+      set(SDL_VIDEO_RENDER_METAL 1)
+      set(HAVE_RENDER_METAL TRUE)
+    endif()
+  endif()
+
   # Actually load the frameworks at the end so we don't duplicate include.
   # Actually load the frameworks at the end so we don't duplicate include.
   if(SDL_FRAMEWORK_COREVIDEO)
   if(SDL_FRAMEWORK_COREVIDEO)
     find_library(COREVIDEO CoreVideo)
     find_library(COREVIDEO CoreVideo)
@@ -1507,32 +1730,57 @@ elseif(APPLE)
     find_library(AUDIOTOOLBOX AudioToolbox)
     find_library(AUDIOTOOLBOX AudioToolbox)
     list(APPEND EXTRA_LIBS ${AUDIOTOOLBOX})
     list(APPEND EXTRA_LIBS ${AUDIOTOOLBOX})
   endif()
   endif()
-
-  # iOS hack needed - http://code.google.com/p/ios-cmake/ ?
-  if(SDL_VIDEO)
-    if (IOS)
-      set(SDL_VIDEO_DRIVER_UIKIT 1)
-      file(GLOB UIKITVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/uikit/*.m)
-      set(SOURCE_FILES ${SOURCE_FILES} ${UIKITVIDEO_SOURCES})
+  if(SDL_FRAMEWORK_AVFOUNDATION)
+    find_library(AVFOUNDATION AVFoundation)
+    list(APPEND EXTRA_LIBS ${AVFOUNDATION})
+  endif()
+  if(SDL_FRAMEWORK_COREBLUETOOTH)
+    find_library(COREBLUETOOTH CoreBluetooth)
+    list(APPEND EXTRA_LIBS ${COREBLUETOOTH})
+  endif()
+  if(SDL_FRAMEWORK_COREGRAPHICS)
+    find_library(COREGRAPHICS CoreGraphics)
+    list(APPEND EXTRA_LIBS ${COREGRAPHICS})
+  endif()
+  if(SDL_FRAMEWORK_COREMOTION)
+    find_library(COREMOTION CoreMotion)
+    list(APPEND EXTRA_LIBS ${COREMOTION})
+  endif()
+  if(SDL_FRAMEWORK_FOUNDATION)
+    find_library(FOUNDATION Foundation)
+    list(APPEND EXTRA_LIBS ${FOUNDATION})
+  endif()
+  if(SDL_FRAMEWORK_GAMECONTROLLER)
+    find_library(GAMECONTROLLER GameController)
+    list(APPEND EXTRA_LIBS ${GAMECONTROLLER})
+  endif()
+  if(SDL_FRAMEWORK_METAL)
+    if(IOS OR TVOS)
+      find_library(METAL Metal)
+      list(APPEND EXTRA_LIBS ${METAL})
     else()
     else()
-      CheckCOCOA()
-      if(VIDEO_OPENGL)
-        set(SDL_VIDEO_OPENGL 1)
-        set(SDL_VIDEO_OPENGL_CGL 1)
-        set(SDL_VIDEO_RENDER_OGL 1)
-        set(HAVE_VIDEO_OPENGL TRUE)
-      endif()
-
-      if(VIDEO_OPENGLES)
-        set(SDL_VIDEO_OPENGL_EGL 1)
-        set(SDL_VIDEO_OPENGL_ES2 1)
-        set(SDL_VIDEO_RENDER_OGL_ES2 1)
-        set(HAVE_VIDEO_OPENGLES TRUE)
-      endif()
+      list(APPEND EXTRA_LDFLAGS "-Wl,-weak_framework,Metal")
+    endif()
+  endif()
+  if(SDL_FRAMEWORK_OPENGLES)
+    find_library(OPENGLES OpenGLES)
+    list(APPEND EXTRA_LIBS ${OPENGLES})
+  endif()
+  if(SDL_FRAMEWORK_QUARTZCORE)
+    if(IOS OR TVOS)
+      find_library(QUARTZCORE QuartzCore)
+      list(APPEND EXTRA_LIBS ${QUARTZCORE})
+    else()
+      list(APPEND EXTRA_LDFLAGS "-Wl,-weak_framework,QuartzCore")
     endif()
     endif()
   endif()
   endif()
+  if(SDL_FRAMEWORK_UIKIT)
+    find_library(UIKIT UIKit)
+    list(APPEND EXTRA_LIBS ${UIKIT})
+  endif()
 
 
   CheckPTHREAD()
   CheckPTHREAD()
+
 elseif(HAIKU)
 elseif(HAIKU)
   if(SDL_VIDEO)
   if(SDL_VIDEO)
     set(SDL_VIDEO_DRIVER_HAIKU 1)
     set(SDL_VIDEO_DRIVER_HAIKU 1)
@@ -1736,6 +1984,24 @@ if(UNIX)
   message(STATUS "")
   message(STATUS "")
 endif()
 endif()
 
 
+if(WARN_ABOUT_ARM_SIMD_ASM_MIT)
+  message(STATUS "")
+  message(STATUS "SDL is being built with ARM SIMD optimizations, which")
+  message(STATUS "uses code licensed under the MIT license. If this is a")
+  message(STATUS "problem, please disable that code by rerunning CMake with:")
+  message(STATUS "")
+  message(STATUS "    -DARMSIMD=OFF")
+endif()
+
+if(WARN_ABOUT_ARM_NEON_ASM_MIT)
+  message(STATUS "")
+  message(STATUS "SDL is being built with ARM NEON optimizations, which")
+  message(STATUS "uses code licensed under the MIT license. If this is a")
+  message(STATUS "problem, please disable that code by rerunning CMake with:")
+  message(STATUS "")
+  message(STATUS "    -DARMNEON=OFF")
+endif()
+
 # Ensure that the extra cflags are used at compile time
 # Ensure that the extra cflags are used at compile time
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 
 
@@ -1747,6 +2013,10 @@ if (NOT ANDROID)
   set_target_properties(SDL2main PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
   set_target_properties(SDL2main PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
 endif()
 endif()
 
 
+if (ANDROID AND HAVE_HIDAPI)
+  set(_INSTALL_LIBS ${_INSTALL_LIBS} "hidapi")
+endif()
+
 if(SDL_SHARED)
 if(SDL_SHARED)
   add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
   add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
   if(APPLE)
   if(APPLE)
@@ -1776,17 +2046,26 @@ if(SDL_SHARED)
   if (NOT ANDROID)
   if (NOT ANDROID)
     set_target_properties(SDL2 PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
     set_target_properties(SDL2 PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
   endif()
   endif()
+  if(IOS OR TVOS)
+    set_property(TARGET SDL2 APPEND_STRING PROPERTY COMPILE_FLAGS "-fobjc-arc")
+    target_compile_definitions(SDL2 PRIVATE IOS_DYLIB=1)
+  endif()
 endif()
 endif()
 
 
 if(ANDROID)
 if(ANDROID)
-  add_library(hidapi SHARED ${ANDROID_HIDAPI_SOURCES})
+  if(HAVE_HIDAPI)
+    add_library(hidapi SHARED ${SDL2_SOURCE_DIR}/src/hidapi/android/hid.cpp)
+  endif()
+
   if(MSVC AND NOT LIBC)
   if(MSVC AND NOT LIBC)
     # Don't try to link with the default set of libraries.
     # Don't try to link with the default set of libraries.
     set_target_properties(hidapi PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB")
     set_target_properties(hidapi PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB")
     set_target_properties(hidapi PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB")
     set_target_properties(hidapi PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB")
     set_target_properties(hidapi PROPERTIES STATIC_LIBRARY_FLAGS "/NODEFAULTLIB")
     set_target_properties(hidapi PROPERTIES STATIC_LIBRARY_FLAGS "/NODEFAULTLIB")
   endif()
   endif()
-  target_link_libraries(hidapi log)
+  if(HAVE_HIDAPI)
+    target_link_libraries(hidapi log)
+  endif()
 endif()
 endif()
 
 
 if(SDL_STATIC)
 if(SDL_STATIC)
@@ -1813,6 +2092,9 @@ if(SDL_STATIC)
   if (NOT ANDROID)
   if (NOT ANDROID)
     set_target_properties(SDL2-static PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
     set_target_properties(SDL2-static PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
   endif()
   endif()
+  if(IOS OR TVOS)
+    set_property(TARGET SDL2-static APPEND_STRING PROPERTY COMPILE_FLAGS "-fobjc-arc")
+  endif()
 endif()
 endif()
 
 
 ##### Tests #####
 ##### Tests #####
@@ -1831,9 +2113,7 @@ install(TARGETS ${_INSTALL_LIBS} EXPORT SDL2Targets
   RUNTIME DESTINATION bin)
   RUNTIME DESTINATION bin)
 
 
 ##### Export files #####
 ##### Export files #####
-if (APPLE)
-  set(PKG_PREFIX "SDL2.framework/Resources")
-elseif (WINDOWS)
+if (WINDOWS)
   set(PKG_PREFIX "cmake")
   set(PKG_PREFIX "cmake")
 else ()
 else ()
   set(PKG_PREFIX "lib/cmake/SDL2")
   set(PKG_PREFIX "lib/cmake/SDL2")

+ 1 - 0
sdl.mod/SDL/Makefile.in

@@ -84,6 +84,7 @@ HDRS = \
 	SDL_log.h \
 	SDL_log.h \
 	SDL_main.h \
 	SDL_main.h \
 	SDL_messagebox.h \
 	SDL_messagebox.h \
+	SDL_metal.h \
 	SDL_mouse.h \
 	SDL_mouse.h \
 	SDL_mutex.h \
 	SDL_mutex.h \
 	SDL_name.h \
 	SDL_name.h \

+ 4 - 1
sdl.mod/SDL/Makefile.os2

@@ -2,7 +2,7 @@
 # wmake -f Makefile.os2
 # wmake -f Makefile.os2
 
 
 LIBNAME = SDL2
 LIBNAME = SDL2
-VERSION = 2.0.9
+VERSION = 2.0.11
 DESCRIPTION = Simple DirectMedia Layer 2
 DESCRIPTION = Simple DirectMedia Layer 2
 
 
 LIBHOME = .
 LIBHOME = .
@@ -89,6 +89,9 @@ SDL_cpuinfo.obj: SDL_cpuinfo.c
 SDL_rwops.obj: SDL_rwops.c
 SDL_rwops.obj: SDL_rwops.c
     wcc386 $(CFLAGS) -wcd=136 -fo=$^@ $<
     wcc386 $(CFLAGS) -wcd=136 -fo=$^@ $<
 
 
+SDL_wave.obj: SDL_wave.c
+    wcc386 $(CFLAGS) -wcd=124 -fo=$^@ $<
+
 SDL_blendfillrect.obj: SDL_blendfillrect.c
 SDL_blendfillrect.obj: SDL_blendfillrect.c
     wcc386 $(CFLAGS) -wcd=200 -fo=$^@ $<
     wcc386 $(CFLAGS) -wcd=200 -fo=$^@ $<
 
 

+ 2 - 1
sdl.mod/SDL/SDL2.spec.in

@@ -74,7 +74,8 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/lib*.la
 %{_libdir}/lib*.la
 %{_libdir}/lib*.%{__soext}
 %{_libdir}/lib*.%{__soext}
 %{_includedir}/*/*.h
 %{_includedir}/*/*.h
-%{_libdir}/pkgconfig/*
+%{_libdir}/cmake/*
+%{_libdir}/pkgconfig/SDL2/*
 %{_datadir}/aclocal/*
 %{_datadir}/aclocal/*
 
 
 %changelog
 %changelog

+ 1 - 4
sdl.mod/SDL/VisualC/SDL/SDL.vcxproj

@@ -130,7 +130,6 @@
       <PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <OmitDefaultLibName>true</OmitDefaultLibName>
       <OmitDefaultLibName>true</OmitDefaultLibName>
@@ -196,7 +195,6 @@
       <PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <OmitDefaultLibName>true</OmitDefaultLibName>
       <OmitDefaultLibName>true</OmitDefaultLibName>
@@ -320,7 +318,7 @@
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
-    <ClInclude Include="..\..\src\joystick\hidapi\controller_type.h" />
+    <ClInclude Include="..\..\src\joystick\controller_type.h" />
     <ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
     <ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
@@ -421,7 +419,6 @@
     <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
     <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
     <ClCompile Include="..\..\src\hidapi\windows\hid.c" />
     <ClCompile Include="..\..\src\hidapi\windows\hid.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
-    <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360.c" />

+ 1 - 2
sdl.mod/SDL/VisualC/SDL/SDL.vcxproj.filters

@@ -259,7 +259,7 @@
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
-    <ClInclude Include="..\..\src\joystick\hidapi\controller_type.h" />
+    <ClInclude Include="..\..\src\joystick\controller_type.h" />
     <ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
     <ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
@@ -360,7 +360,6 @@
     <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
     <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
     <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
     <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
     <ClCompile Include="..\..\src\hidapi\windows\hid.c" />
     <ClCompile Include="..\..\src\hidapi\windows\hid.c" />
-    <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_switch.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360.c" />

+ 0 - 2
sdl.mod/SDL/VisualC/SDLmain/SDLmain.vcxproj

@@ -108,7 +108,6 @@
       <StringPooling>true</StringPooling>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <OmitDefaultLibName>true</OmitDefaultLibName>
       <OmitDefaultLibName>true</OmitDefaultLibName>
@@ -143,7 +142,6 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <OmitDefaultLibName>true</OmitDefaultLibName>
       <OmitDefaultLibName>true</OmitDefaultLibName>

+ 0 - 2
sdl.mod/SDL/VisualC/SDLtest/SDLtest.vcxproj

@@ -108,7 +108,6 @@
       <StringPooling>true</StringPooling>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <OmitDefaultLibName>true</OmitDefaultLibName>
       <OmitDefaultLibName>true</OmitDefaultLibName>
@@ -143,7 +142,6 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>
-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <DebugInformationFormat>OldStyle</DebugInformationFormat>
       <OmitDefaultLibName>true</OmitDefaultLibName>
       <OmitDefaultLibName>true</OmitDefaultLibName>

+ 28 - 0
sdl.mod/SDL/WhatsNew.txt

@@ -1,17 +1,45 @@
 
 
 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.0.11/12:
+---------------------------------------------------------------------------
+
+General:
+* Added SDL_LockTextureToSurface(), similar to SDL_LockTexture() but the locked area is exposed as a SDL surface.
+
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 2.0.10:
 2.0.10:
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
+
+General:
+* The SDL_RW* macros have been turned into functions that are available only in 2.0.10 and onward
+* Added SDL_SIMDGetAlignment(), SDL_SIMDAlloc(), and SDL_SIMDFree(), to allocate memory aligned for SIMD operations for the current CPU
+* Added SDL_RenderDrawPointF(), SDL_RenderDrawPointsF(), SDL_RenderDrawLineF(), SDL_RenderDrawLinesF(), SDL_RenderDrawRectF(), SDL_RenderDrawRectsF(), SDL_RenderFillRectF(), SDL_RenderFillRectsF(), SDL_RenderCopyF(), SDL_RenderCopyExF(), to allow floating point precision in the SDL rendering API.
+* Added SDL_GetTouchDeviceType() to get the type of a touch device, which can be a touch screen or a trackpad in relative or absolute coordinate mode.
+* The SDL rendering API now uses batched rendering by default, for improved performance
+* Added SDL_RenderFlush() to force batched render commands to execute, if you're going to mix SDL rendering with native rendering
+* Added the hint SDL_HINT_RENDER_BATCHING to control whether batching should be used for the rendering API. This defaults to "1" if you don't specify what rendering driver to use when creating the renderer.
+* Added the hint SDL_HINT_EVENT_LOGGING to enable logging of SDL events for debugging purposes
+* Added the hint SDL_HINT_GAMECONTROLLERCONFIG_FILE to specify a file that will be loaded at joystick initialization with game controller bindings
 * Added the hint SDL_HINT_MOUSE_TOUCH_EVENTS to control whether SDL will synthesize touch events from mouse events
 * Added the hint SDL_HINT_MOUSE_TOUCH_EVENTS to control whether SDL will synthesize touch events from mouse events
+* Improved handling of malformed WAVE and BMP files, fixing potential security exploits
+
+Linux:
+* Removed the Mir video driver in favor of Wayland
+
+iOS / tvOS:
+* Added support for Xbox and PS4 wireless controllers in iOS 13 and tvOS 13
+* Added support for text input using Bluetooth keyboards
 
 
 Android:
 Android:
+* Added low latency audio using OpenSL ES
 * Removed SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH (replaced by SDL_HINT_MOUSE_TOUCH_EVENTS and SDL_HINT_TOUCH_MOUSE_EVENTS)
 * Removed SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH (replaced by SDL_HINT_MOUSE_TOUCH_EVENTS and SDL_HINT_TOUCH_MOUSE_EVENTS)
   SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=1, should be replaced by setting both previous hints to 0.
   SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=1, should be replaced by setting both previous hints to 0.
   SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=0, should be replaced by setting both previous hints to 1.
   SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=0, should be replaced by setting both previous hints to 1.
 * Added the hint SDL_HINT_ANDROID_BLOCK_ON_PAUSE to set whether the event loop will block itself when the app is paused.
 * Added the hint SDL_HINT_ANDROID_BLOCK_ON_PAUSE to set whether the event loop will block itself when the app is paused.
 
 
+
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 2.0.9:
 2.0.9:
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 134 - 48
sdl.mod/SDL/Xcode-iOS/Demos/Demos.xcodeproj/project.pbxproj

@@ -10,6 +10,13 @@
 		1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; };
 		1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; };
 		1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
 		1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
 		1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
 		1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+		F3F7590022AC5EC7001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
+		F3F7590122AC5F00001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
+		F3F7590222AC5F3D001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
+		F3F7590322AC5F71001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
+		F3F7590422AC5F8D001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
+		F3F7590522AC5FB3001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
+		F3F7590622AC5FD1001D97F2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F758FF22AC5EC7001D97F2 /* Metal.framework */; };
 		FA30DEB01BBF5A8F009C397F /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = FD77A0060E26BC0500F39101 /* common.c */; };
 		FA30DEB01BBF5A8F009C397F /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = FD77A0060E26BC0500F39101 /* common.c */; };
 		FA30DEB11BBF5A93009C397F /* happy.c in Sources */ = {isa = PBXBuildFile; fileRef = FD77A0080E26BC0500F39101 /* happy.c */; };
 		FA30DEB11BBF5A93009C397F /* happy.c in Sources */ = {isa = PBXBuildFile; fileRef = FD77A0080E26BC0500F39101 /* happy.c */; };
 		FA30DEB31BBF5AD7009C397F /* icon.bmp in Resources */ = {isa = PBXBuildFile; fileRef = FDB651CC0E43D19800F688B5 /* icon.bmp */; };
 		FA30DEB31BBF5AD7009C397F /* icon.bmp in Resources */ = {isa = PBXBuildFile; fileRef = FDB651CC0E43D19800F688B5 /* icon.bmp */; };
@@ -40,7 +47,6 @@
 		FA8B4BA91967073D00F8EB7C /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA8B4BA21967070A00F8EB7C /* CoreMotion.framework */; };
 		FA8B4BA91967073D00F8EB7C /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA8B4BA21967070A00F8EB7C /* CoreMotion.framework */; };
 		FABA34D41D8B5E5600915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34D41D8B5E5600915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34D61D8B5E5A00915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34D61D8B5E5A00915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
-		FABA34D81D8B5E7700915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D71D8B5E7700915323 /* AVFoundation.framework */; };
 		FABA34D91D8B5E7B00915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34D91D8B5E7B00915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34DA1D8B5E7F00915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34DA1D8B5E7F00915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34DB1D8B5E8500915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
 		FABA34DB1D8B5E8500915323 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FABA34D31D8B5E5600915323 /* AVFoundation.framework */; };
@@ -197,6 +203,34 @@
 			remoteGlobalIDString = FD6526620DE8FCCB002AD96B;
 			remoteGlobalIDString = FD6526620DE8FCCB002AD96B;
 			remoteInfo = libSDL;
 			remoteInfo = libSDL;
 		};
 		};
+		F3F758F722AC5E8F001D97F2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = FD1B48920E313154007AB34E /* SDL.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 52ED1E5C222889500061FCE0;
+			remoteInfo = "libSDL-iOS-dylib";
+		};
+		F3F758F922AC5E8F001D97F2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = FD1B48920E313154007AB34E /* SDL.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = F3E3C7572241389A007D243C;
+			remoteInfo = "libSDL-tvOS-dylib";
+		};
+		F3F758FB22AC5E8F001D97F2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = FD1B48920E313154007AB34E /* SDL.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = F3E3C65222406928007D243C;
+			remoteInfo = "libSDLmain-iOS";
+		};
+		F3F758FD22AC5E8F001D97F2 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = FD1B48920E313154007AB34E /* SDL.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = F3E3C75F224138AE007D243C;
+			remoteInfo = "libSDLmain-tvOS";
+		};
 		FA30DEAB1BBF59D9009C397F /* PBXContainerItemProxy */ = {
 		FA30DEAB1BBF59D9009C397F /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			isa = PBXContainerItemProxy;
 			containerPortal = FD1B48920E313154007AB34E /* SDL.xcodeproj */;
 			containerPortal = FD1B48920E313154007AB34E /* SDL.xcodeproj */;
@@ -226,6 +260,7 @@
 		1D6058910D05DD3D006BFB54 /* Rectangles.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rectangles.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		1D6058910D05DD3D006BFB54 /* Rectangles.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rectangles.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
 		1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
 		8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		F3F758FF22AC5EC7001D97F2 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
 		FA30DE961BBF59D9009C397F /* Happy-TV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Happy-TV.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		FA30DE961BBF59D9009C397F /* Happy-TV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Happy-TV.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		FA86C0361D9765BA009CB637 /* iOS Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "iOS Launch Screen.storyboard"; sourceTree = "<group>"; };
 		FA86C0361D9765BA009CB637 /* iOS Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "iOS Launch Screen.storyboard"; sourceTree = "<group>"; };
 		FA8B4BA21967070A00F8EB7C /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
 		FA8B4BA21967070A00F8EB7C /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
@@ -271,17 +306,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34D41D8B5E5600915323 /* AVFoundation.framework in Frameworks */,
 				FD1B48DD0E313255007AB34E /* libSDL2.a in Frameworks */,
 				FD1B48DD0E313255007AB34E /* libSDL2.a in Frameworks */,
-				FAE0E96A1BAF96A00098DFA4 /* GameController.framework in Frameworks */,
-				FA8B4BA31967070A00F8EB7C /* CoreMotion.framework in Frameworks */,
-				FDF0D7AB0E12D53800247964 /* CoreAudio.framework in Frameworks */,
 				FDF0D7AC0E12D53800247964 /* AudioToolbox.framework in Frameworks */,
 				FDF0D7AC0E12D53800247964 /* AudioToolbox.framework in Frameworks */,
-				1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
-				1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+				FABA34D41D8B5E5600915323 /* AVFoundation.framework in Frameworks */,
+				FDF0D7AB0E12D53800247964 /* CoreAudio.framework in Frameworks */,
 				1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */,
 				1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */,
+				FA8B4BA31967070A00F8EB7C /* CoreMotion.framework in Frameworks */,
+				1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+				FAE0E96A1BAF96A00098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590022AC5EC7001D97F2 /* Metal.framework in Frameworks */,
 				FDB96ED40DEFC9C700FAF19F /* OpenGLES.framework in Frameworks */,
 				FDB96ED40DEFC9C700FAF19F /* OpenGLES.framework in Frameworks */,
 				FDB96EE00DEFC9DC00FAF19F /* QuartzCore.framework in Frameworks */,
 				FDB96EE00DEFC9DC00FAF19F /* QuartzCore.framework in Frameworks */,
+				1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -289,16 +325,15 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34D81D8B5E7700915323 /* AVFoundation.framework in Frameworks */,
 				FA30DEB71BBF5BB8009C397F /* libSDL2.a in Frameworks */,
 				FA30DEB71BBF5BB8009C397F /* libSDL2.a in Frameworks */,
-				FA30DEC81BBF5C14009C397F /* GameController.framework in Frameworks */,
 				FA30DEC91BBF5C14009C397F /* AudioToolbox.framework in Frameworks */,
 				FA30DEC91BBF5C14009C397F /* AudioToolbox.framework in Frameworks */,
+				FA30DECF1BBF5C14009C397F /* CoreAudio.framework in Frameworks */,
+				FA30DECC1BBF5C14009C397F /* CoreGraphics.framework in Frameworks */,
+				FA30DECE1BBF5C14009C397F /* Foundation.framework in Frameworks */,
+				FA30DEC81BBF5C14009C397F /* GameController.framework in Frameworks */,
 				FA30DECA1BBF5C14009C397F /* QuartzCore.framework in Frameworks */,
 				FA30DECA1BBF5C14009C397F /* QuartzCore.framework in Frameworks */,
 				FA30DECB1BBF5C14009C397F /* OpenGLES.framework in Frameworks */,
 				FA30DECB1BBF5C14009C397F /* OpenGLES.framework in Frameworks */,
-				FA30DECC1BBF5C14009C397F /* CoreGraphics.framework in Frameworks */,
 				FA30DECD1BBF5C14009C397F /* UIKit.framework in Frameworks */,
 				FA30DECD1BBF5C14009C397F /* UIKit.framework in Frameworks */,
-				FA30DECE1BBF5C14009C397F /* Foundation.framework in Frameworks */,
-				FA30DECF1BBF5C14009C397F /* CoreAudio.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -306,17 +341,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34D61D8B5E5A00915323 /* AVFoundation.framework in Frameworks */,
 				FD1B49980E313261007AB34E /* libSDL2.a in Frameworks */,
 				FD1B49980E313261007AB34E /* libSDL2.a in Frameworks */,
-				FAE0E96C1BAF96A90098DFA4 /* GameController.framework in Frameworks */,
-				FA8B4BA41967071300F8EB7C /* CoreMotion.framework in Frameworks */,
-				FDF0D7A90E12D53500247964 /* CoreAudio.framework in Frameworks */,
 				FDF0D7AA0E12D53500247964 /* AudioToolbox.framework in Frameworks */,
 				FDF0D7AA0E12D53500247964 /* AudioToolbox.framework in Frameworks */,
-				FD15FD690E086911003BDF25 /* Foundation.framework in Frameworks */,
-				FD15FD6A0E086911003BDF25 /* UIKit.framework in Frameworks */,
+				FABA34D61D8B5E5A00915323 /* AVFoundation.framework in Frameworks */,
+				FDF0D7A90E12D53500247964 /* CoreAudio.framework in Frameworks */,
 				FD15FD6B0E086911003BDF25 /* CoreGraphics.framework in Frameworks */,
 				FD15FD6B0E086911003BDF25 /* CoreGraphics.framework in Frameworks */,
+				FA8B4BA41967071300F8EB7C /* CoreMotion.framework in Frameworks */,
+				FD15FD690E086911003BDF25 /* Foundation.framework in Frameworks */,
+				FAE0E96C1BAF96A90098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590122AC5F00001D97F2 /* Metal.framework in Frameworks */,
 				FD15FD6C0E086911003BDF25 /* OpenGLES.framework in Frameworks */,
 				FD15FD6C0E086911003BDF25 /* OpenGLES.framework in Frameworks */,
 				FD15FD6D0E086911003BDF25 /* QuartzCore.framework in Frameworks */,
 				FD15FD6D0E086911003BDF25 /* QuartzCore.framework in Frameworks */,
+				FD15FD6A0E086911003BDF25 /* UIKit.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -324,17 +360,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34D91D8B5E7B00915323 /* AVFoundation.framework in Frameworks */,
 				FD1B499C0E313269007AB34E /* libSDL2.a in Frameworks */,
 				FD1B499C0E313269007AB34E /* libSDL2.a in Frameworks */,
-				FAE0E96D1BAF96AF0098DFA4 /* GameController.framework in Frameworks */,
-				FA8B4BA51967071A00F8EB7C /* CoreMotion.framework in Frameworks */,
-				FDF0D7A70E12D53200247964 /* CoreAudio.framework in Frameworks */,
 				FDF0D7A80E12D53200247964 /* AudioToolbox.framework in Frameworks */,
 				FDF0D7A80E12D53200247964 /* AudioToolbox.framework in Frameworks */,
+				FABA34D91D8B5E7B00915323 /* AVFoundation.framework in Frameworks */,
+				FDF0D7A70E12D53200247964 /* CoreAudio.framework in Frameworks */,
+				FD5F9CEA0E0E0741008E885B /* CoreGraphics.framework in Frameworks */,
+				FA8B4BA51967071A00F8EB7C /* CoreMotion.framework in Frameworks */,
+				FD5F9CE80E0E0741008E885B /* Foundation.framework in Frameworks */,
+				FAE0E96D1BAF96AF0098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590222AC5F3D001D97F2 /* Metal.framework in Frameworks */,
 				FD5F9CEB0E0E0741008E885B /* OpenGLES.framework in Frameworks */,
 				FD5F9CEB0E0E0741008E885B /* OpenGLES.framework in Frameworks */,
 				FD5F9CEC0E0E0741008E885B /* QuartzCore.framework in Frameworks */,
 				FD5F9CEC0E0E0741008E885B /* QuartzCore.framework in Frameworks */,
-				FD5F9CE80E0E0741008E885B /* Foundation.framework in Frameworks */,
 				FD5F9CE90E0E0741008E885B /* UIKit.framework in Frameworks */,
 				FD5F9CE90E0E0741008E885B /* UIKit.framework in Frameworks */,
-				FD5F9CEA0E0E0741008E885B /* CoreGraphics.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -342,17 +379,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34DD1D8B5E8D00915323 /* AVFoundation.framework in Frameworks */,
 				FDB652000E43D1F300F688B5 /* libSDL2.a in Frameworks */,
 				FDB652000E43D1F300F688B5 /* libSDL2.a in Frameworks */,
-				FAE0E9711BAF96BB0098DFA4 /* GameController.framework in Frameworks */,
+				FDB652080E43D1F300F688B5 /* AudioToolbox.framework in Frameworks */,
+				FABA34DD1D8B5E8D00915323 /* AVFoundation.framework in Frameworks */,
+				FDB652070E43D1F300F688B5 /* CoreAudio.framework in Frameworks */,
+				FDB652040E43D1F300F688B5 /* CoreGraphics.framework in Frameworks */,
 				FA8B4BA91967073D00F8EB7C /* CoreMotion.framework in Frameworks */,
 				FA8B4BA91967073D00F8EB7C /* CoreMotion.framework in Frameworks */,
 				FDB652020E43D1F300F688B5 /* Foundation.framework in Frameworks */,
 				FDB652020E43D1F300F688B5 /* Foundation.framework in Frameworks */,
-				FDB652030E43D1F300F688B5 /* UIKit.framework in Frameworks */,
-				FDB652040E43D1F300F688B5 /* CoreGraphics.framework in Frameworks */,
+				FAE0E9711BAF96BB0098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590622AC5FD1001D97F2 /* Metal.framework in Frameworks */,
 				FDB652050E43D1F300F688B5 /* OpenGLES.framework in Frameworks */,
 				FDB652050E43D1F300F688B5 /* OpenGLES.framework in Frameworks */,
 				FDB652060E43D1F300F688B5 /* QuartzCore.framework in Frameworks */,
 				FDB652060E43D1F300F688B5 /* QuartzCore.framework in Frameworks */,
-				FDB652070E43D1F300F688B5 /* CoreAudio.framework in Frameworks */,
-				FDB652080E43D1F300F688B5 /* AudioToolbox.framework in Frameworks */,
+				FDB652030E43D1F300F688B5 /* UIKit.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -360,17 +398,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34DA1D8B5E7F00915323 /* AVFoundation.framework in Frameworks */,
 				FD1B499E0E31326C007AB34E /* libSDL2.a in Frameworks */,
 				FD1B499E0E31326C007AB34E /* libSDL2.a in Frameworks */,
-				FAE0E96E1BAF96B10098DFA4 /* GameController.framework in Frameworks */,
-				FA8B4BA61967072100F8EB7C /* CoreMotion.framework in Frameworks */,
-				FDF0D7950E12D52900247964 /* CoreAudio.framework in Frameworks */,
 				FDF0D7960E12D52900247964 /* AudioToolbox.framework in Frameworks */,
 				FDF0D7960E12D52900247964 /* AudioToolbox.framework in Frameworks */,
-				FDC202E60E107B1200ABAC90 /* Foundation.framework in Frameworks */,
-				FDC202E70E107B1200ABAC90 /* UIKit.framework in Frameworks */,
+				FABA34DA1D8B5E7F00915323 /* AVFoundation.framework in Frameworks */,
+				FDF0D7950E12D52900247964 /* CoreAudio.framework in Frameworks */,
 				FDC202E80E107B1200ABAC90 /* CoreGraphics.framework in Frameworks */,
 				FDC202E80E107B1200ABAC90 /* CoreGraphics.framework in Frameworks */,
+				FA8B4BA61967072100F8EB7C /* CoreMotion.framework in Frameworks */,
+				FDC202E60E107B1200ABAC90 /* Foundation.framework in Frameworks */,
+				FAE0E96E1BAF96B10098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590322AC5F71001D97F2 /* Metal.framework in Frameworks */,
 				FDC202E90E107B1200ABAC90 /* OpenGLES.framework in Frameworks */,
 				FDC202E90E107B1200ABAC90 /* OpenGLES.framework in Frameworks */,
 				FDC202EA0E107B1200ABAC90 /* QuartzCore.framework in Frameworks */,
 				FDC202EA0E107B1200ABAC90 /* QuartzCore.framework in Frameworks */,
+				FDC202E70E107B1200ABAC90 /* UIKit.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -378,17 +417,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34DC1D8B5E8900915323 /* AVFoundation.framework in Frameworks */,
 				FD1B49A20E313273007AB34E /* libSDL2.a in Frameworks */,
 				FD1B49A20E313273007AB34E /* libSDL2.a in Frameworks */,
-				FAE0E9701BAF96B80098DFA4 /* GameController.framework in Frameworks */,
+				FDC52EDA0E2843D6008D768C /* AudioToolbox.framework in Frameworks */,
+				FABA34DC1D8B5E8900915323 /* AVFoundation.framework in Frameworks */,
+				FDC52ED90E2843D6008D768C /* CoreAudio.framework in Frameworks */,
+				FDC52ED60E2843D6008D768C /* CoreGraphics.framework in Frameworks */,
 				FA8B4BA81967073400F8EB7C /* CoreMotion.framework in Frameworks */,
 				FA8B4BA81967073400F8EB7C /* CoreMotion.framework in Frameworks */,
 				FDC52ED40E2843D6008D768C /* Foundation.framework in Frameworks */,
 				FDC52ED40E2843D6008D768C /* Foundation.framework in Frameworks */,
-				FDC52ED50E2843D6008D768C /* UIKit.framework in Frameworks */,
-				FDC52ED60E2843D6008D768C /* CoreGraphics.framework in Frameworks */,
+				FAE0E9701BAF96B80098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590522AC5FB3001D97F2 /* Metal.framework in Frameworks */,
 				FDC52ED70E2843D6008D768C /* OpenGLES.framework in Frameworks */,
 				FDC52ED70E2843D6008D768C /* OpenGLES.framework in Frameworks */,
 				FDC52ED80E2843D6008D768C /* QuartzCore.framework in Frameworks */,
 				FDC52ED80E2843D6008D768C /* QuartzCore.framework in Frameworks */,
-				FDC52ED90E2843D6008D768C /* CoreAudio.framework in Frameworks */,
-				FDC52EDA0E2843D6008D768C /* AudioToolbox.framework in Frameworks */,
+				FDC52ED50E2843D6008D768C /* UIKit.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -396,17 +436,18 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				FABA34DB1D8B5E8500915323 /* AVFoundation.framework in Frameworks */,
 				FD1B49A00E313270007AB34E /* libSDL2.a in Frameworks */,
 				FD1B49A00E313270007AB34E /* libSDL2.a in Frameworks */,
-				FAE0E96F1BAF96B50098DFA4 /* GameController.framework in Frameworks */,
+				FDF0D7230E12D31800247964 /* AudioToolbox.framework in Frameworks */,
+				FABA34DB1D8B5E8500915323 /* AVFoundation.framework in Frameworks */,
+				FDF0D71E0E12D2AB00247964 /* CoreAudio.framework in Frameworks */,
+				FDF0D69E0E12D05400247964 /* CoreGraphics.framework in Frameworks */,
 				FA8B4BA71967072800F8EB7C /* CoreMotion.framework in Frameworks */,
 				FA8B4BA71967072800F8EB7C /* CoreMotion.framework in Frameworks */,
 				FDF0D69C0E12D05400247964 /* Foundation.framework in Frameworks */,
 				FDF0D69C0E12D05400247964 /* Foundation.framework in Frameworks */,
-				FDF0D69D0E12D05400247964 /* UIKit.framework in Frameworks */,
-				FDF0D69E0E12D05400247964 /* CoreGraphics.framework in Frameworks */,
+				FAE0E96F1BAF96B50098DFA4 /* GameController.framework in Frameworks */,
+				F3F7590422AC5F8D001D97F2 /* Metal.framework in Frameworks */,
 				FDF0D69F0E12D05400247964 /* OpenGLES.framework in Frameworks */,
 				FDF0D69F0E12D05400247964 /* OpenGLES.framework in Frameworks */,
 				FDF0D6A00E12D05400247964 /* QuartzCore.framework in Frameworks */,
 				FDF0D6A00E12D05400247964 /* QuartzCore.framework in Frameworks */,
-				FDF0D71E0E12D2AB00247964 /* CoreAudio.framework in Frameworks */,
-				FDF0D7230E12D31800247964 /* AudioToolbox.framework in Frameworks */,
+				FDF0D69D0E12D05400247964 /* UIKit.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -455,6 +496,7 @@
 		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
 		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				F3F758FF22AC5EC7001D97F2 /* Metal.framework */,
 				FABA34D71D8B5E7700915323 /* AVFoundation.framework */,
 				FABA34D71D8B5E7700915323 /* AVFoundation.framework */,
 				FABA34D31D8B5E5600915323 /* AVFoundation.framework */,
 				FABA34D31D8B5E5600915323 /* AVFoundation.framework */,
 				FAE0E9691BAF96A00098DFA4 /* GameController.framework */,
 				FAE0E9691BAF96A00098DFA4 /* GameController.framework */,
@@ -474,7 +516,11 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				FD1B489E0E313154007AB34E /* libSDL2.a */,
 				FD1B489E0E313154007AB34E /* libSDL2.a */,
+				F3F758F822AC5E8F001D97F2 /* libSDL2.dylib */,
 				FA30DEAC1BBF59D9009C397F /* libSDL2.a */,
 				FA30DEAC1BBF59D9009C397F /* libSDL2.a */,
+				F3F758FA22AC5E8F001D97F2 /* libSDL2.dylib */,
+				F3F758FC22AC5E8F001D97F2 /* libSDLmain.a */,
+				F3F758FE22AC5E8F001D97F2 /* libSDLmain.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -725,6 +771,34 @@
 /* End PBXProject section */
 /* End PBXProject section */
 
 
 /* Begin PBXReferenceProxy section */
 /* Begin PBXReferenceProxy section */
+		F3F758F822AC5E8F001D97F2 /* libSDL2.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libSDL2.dylib;
+			remoteRef = F3F758F722AC5E8F001D97F2 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		F3F758FA22AC5E8F001D97F2 /* libSDL2.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libSDL2.dylib;
+			remoteRef = F3F758F922AC5E8F001D97F2 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		F3F758FC22AC5E8F001D97F2 /* libSDLmain.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libSDLmain.a;
+			remoteRef = F3F758FB22AC5E8F001D97F2 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		F3F758FE22AC5E8F001D97F2 /* libSDLmain.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libSDLmain.a;
+			remoteRef = F3F758FD22AC5E8F001D97F2 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
 		FA30DEAC1BBF59D9009C397F /* libSDL2.a */ = {
 		FA30DEAC1BBF59D9009C397F /* libSDL2.a */ = {
 			isa = PBXReferenceProxy;
 			isa = PBXReferenceProxy;
 			fileType = archive.ar;
 			fileType = archive.ar;
@@ -957,6 +1031,7 @@
 		1D6058940D05DD3E006BFB54 /* Debug */ = {
 		1D6058940D05DD3E006BFB54 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Rectangles;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Rectangles;
 				PRODUCT_NAME = Rectangles;
 				PRODUCT_NAME = Rectangles;
@@ -966,6 +1041,7 @@
 		1D6058950D05DD3E006BFB54 /* Release */ = {
 		1D6058950D05DD3E006BFB54 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Rectangles;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Rectangles;
 				PRODUCT_NAME = Rectangles;
 				PRODUCT_NAME = Rectangles;
@@ -1089,6 +1165,7 @@
 		FD15FCB50E086866003BDF25 /* Debug */ = {
 		FD15FCB50E086866003BDF25 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_DYNAMIC_NO_PIC = NO;
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Happy;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Happy;
@@ -1100,6 +1177,7 @@
 		FD15FCB60E086866003BDF25 /* Release */ = {
 		FD15FCB60E086866003BDF25 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Happy;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Happy;
 				PRODUCT_NAME = Happy;
 				PRODUCT_NAME = Happy;
@@ -1110,6 +1188,7 @@
 		FD5F9BE70E0DEBEB008E885B /* Debug */ = {
 		FD5F9BE70E0DEBEB008E885B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Accel;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Accel;
 				PRODUCT_NAME = Accel;
 				PRODUCT_NAME = Accel;
@@ -1120,6 +1199,7 @@
 		FD5F9BE80E0DEBEB008E885B /* Release */ = {
 		FD5F9BE80E0DEBEB008E885B /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Accel;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Accel;
 				PRODUCT_NAME = Accel;
 				PRODUCT_NAME = Accel;
@@ -1130,6 +1210,7 @@
 		FDB6520A0E43D1F300F688B5 /* Debug */ = {
 		FDB6520A0E43D1F300F688B5 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Keyboard;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Keyboard;
 				PRODUCT_NAME = Keyboard;
 				PRODUCT_NAME = Keyboard;
@@ -1140,6 +1221,7 @@
 		FDB6520B0E43D1F300F688B5 /* Release */ = {
 		FDB6520B0E43D1F300F688B5 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Keyboard;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Keyboard;
 				PRODUCT_NAME = Keyboard;
 				PRODUCT_NAME = Keyboard;
@@ -1150,6 +1232,7 @@
 		FDC202EC0E107B1200ABAC90 /* Debug */ = {
 		FDC202EC0E107B1200ABAC90 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Touch;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Touch;
 				PRODUCT_NAME = Touch;
 				PRODUCT_NAME = Touch;
@@ -1160,6 +1243,7 @@
 		FDC202ED0E107B1200ABAC90 /* Release */ = {
 		FDC202ED0E107B1200ABAC90 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Touch;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Touch;
 				PRODUCT_NAME = Touch;
 				PRODUCT_NAME = Touch;
@@ -1194,6 +1278,7 @@
 		FDF0D6A20E12D05400247964 /* Debug */ = {
 		FDF0D6A20E12D05400247964 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Mixer;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Mixer;
 				PRODUCT_NAME = Mixer;
 				PRODUCT_NAME = Mixer;
@@ -1204,6 +1289,7 @@
 		FDF0D6A30E12D05400247964 /* Release */ = {
 		FDF0D6A30E12D05400247964 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				DEVELOPMENT_TEAM = "";
 				INFOPLIST_FILE = Info.plist;
 				INFOPLIST_FILE = Info.plist;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Mixer;
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.Mixer;
 				PRODUCT_NAME = Mixer;
 				PRODUCT_NAME = Mixer;

+ 8 - 12
sdl.mod/SDL/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj

@@ -468,9 +468,6 @@
 		F3BDD79B20F51CB8004ECBF3 /* SDL_hidapijoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3BDD79020F51CB8004ECBF3 /* SDL_hidapijoystick_c.h */; };
 		F3BDD79B20F51CB8004ECBF3 /* SDL_hidapijoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3BDD79020F51CB8004ECBF3 /* SDL_hidapijoystick_c.h */; };
 		F3BDD79C20F51CB8004ECBF3 /* SDL_hidapijoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD79120F51CB8004ECBF3 /* SDL_hidapijoystick.c */; };
 		F3BDD79C20F51CB8004ECBF3 /* SDL_hidapijoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD79120F51CB8004ECBF3 /* SDL_hidapijoystick.c */; };
 		F3BDD79D20F51CB8004ECBF3 /* SDL_hidapijoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD79120F51CB8004ECBF3 /* SDL_hidapijoystick.c */; };
 		F3BDD79D20F51CB8004ECBF3 /* SDL_hidapijoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = F3BDD79120F51CB8004ECBF3 /* SDL_hidapijoystick.c */; };
-		F3E3C55D223DEC6C007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C55C223DEC6C007D243C /* SDL_hidapi_gamecube.c */; };
-		F3E3C55E223DEC6C007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C55C223DEC6C007D243C /* SDL_hidapi_gamecube.c */; };
-		F3E3C55F224065AE007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C55C223DEC6C007D243C /* SDL_hidapi_gamecube.c */; };
 		F3E3C658224069CE007D243C /* SDL_uikit_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C657224069CE007D243C /* SDL_uikit_main.c */; };
 		F3E3C658224069CE007D243C /* SDL_uikit_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C657224069CE007D243C /* SDL_uikit_main.c */; };
 		F3E3C65B2241389A007D243C /* SDL_blit.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA683010DF2374E00F98A1A /* SDL_blit.h */; };
 		F3E3C65B2241389A007D243C /* SDL_blit.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA683010DF2374E00F98A1A /* SDL_blit.h */; };
 		F3E3C65C2241389A007D243C /* SDL_uikitmetalview.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D7517191EE1D32200820EEA /* SDL_uikitmetalview.h */; };
 		F3E3C65C2241389A007D243C /* SDL_uikitmetalview.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D7517191EE1D32200820EEA /* SDL_uikitmetalview.h */; };
@@ -657,7 +654,6 @@
 		F3E3C7122241389A007D243C /* SDL_uikitevents.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F0D0E26E5D900F90B21 /* SDL_uikitevents.m */; };
 		F3E3C7122241389A007D243C /* SDL_uikitevents.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F0D0E26E5D900F90B21 /* SDL_uikitevents.m */; };
 		F3E3C7132241389A007D243C /* yuv_rgb.c in Sources */ = {isa = PBXBuildFile; fileRef = AA13B3561FB8B46300D9FEE6 /* yuv_rgb.c */; };
 		F3E3C7132241389A007D243C /* yuv_rgb.c in Sources */ = {isa = PBXBuildFile; fileRef = AA13B3561FB8B46300D9FEE6 /* yuv_rgb.c */; };
 		F3E3C7142241389A007D243C /* SDL_uikitopengles.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F0F0E26E5D900F90B21 /* SDL_uikitopengles.m */; };
 		F3E3C7142241389A007D243C /* SDL_uikitopengles.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F0F0E26E5D900F90B21 /* SDL_uikitopengles.m */; };
-		F3E3C7152241389A007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C55C223DEC6C007D243C /* SDL_hidapi_gamecube.c */; };
 		F3E3C7162241389A007D243C /* SDL_uikitvideo.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F110E26E5D900F90B21 /* SDL_uikitvideo.m */; };
 		F3E3C7162241389A007D243C /* SDL_uikitvideo.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F110E26E5D900F90B21 /* SDL_uikitvideo.m */; };
 		F3E3C7172241389A007D243C /* SDL_uikitview.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F130E26E5D900F90B21 /* SDL_uikitview.m */; };
 		F3E3C7172241389A007D243C /* SDL_uikitview.m in Sources */ = {isa = PBXBuildFile; fileRef = FD689F130E26E5D900F90B21 /* SDL_uikitview.m */; };
 		F3E3C7182241389A007D243C /* SDL_displayevents.c in Sources */ = {isa = PBXBuildFile; fileRef = A7C19D28212E552B00DF2152 /* SDL_displayevents.c */; };
 		F3E3C7182241389A007D243C /* SDL_displayevents.c in Sources */ = {isa = PBXBuildFile; fileRef = A7C19D28212E552B00DF2152 /* SDL_displayevents.c */; };
@@ -721,6 +717,7 @@
 		F3E3C75B224138AE007D243C /* SDL_uikit_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C657224069CE007D243C /* SDL_uikit_main.c */; };
 		F3E3C75B224138AE007D243C /* SDL_uikit_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C657224069CE007D243C /* SDL_uikit_main.c */; };
 		FA1DC2721C62BE65008F99A0 /* SDL_uikitclipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */; };
 		FA1DC2721C62BE65008F99A0 /* SDL_uikitclipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */; };
 		FA1DC2731C62BE65008F99A0 /* SDL_uikitclipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */; };
 		FA1DC2731C62BE65008F99A0 /* SDL_uikitclipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */; };
+		FA24348D21D4201400B8918A /* SDL_metal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348C21D4201400B8918A /* SDL_metal.h */; };
 		FAB5981D1BB5C31500BE72C5 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */; };
 		FAB5981D1BB5C31500BE72C5 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */; };
 		FAB5981E1BB5C31500BE72C5 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */; };
 		FAB5981E1BB5C31500BE72C5 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */; };
 		FAB5981F1BB5C31500BE72C5 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 56EA86F913E9EC2B002E47EB /* SDL_coreaudio.m */; };
 		FAB5981F1BB5C31500BE72C5 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 56EA86F913E9EC2B002E47EB /* SDL_coreaudio.m */; };
@@ -1062,13 +1059,14 @@
 		F3BDD78E20F51CB8004ECBF3 /* SDL_hidapi_ps4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_ps4.c; sourceTree = "<group>"; };
 		F3BDD78E20F51CB8004ECBF3 /* SDL_hidapi_ps4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_ps4.c; sourceTree = "<group>"; };
 		F3BDD79020F51CB8004ECBF3 /* SDL_hidapijoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hidapijoystick_c.h; sourceTree = "<group>"; };
 		F3BDD79020F51CB8004ECBF3 /* SDL_hidapijoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hidapijoystick_c.h; sourceTree = "<group>"; };
 		F3BDD79120F51CB8004ECBF3 /* SDL_hidapijoystick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapijoystick.c; sourceTree = "<group>"; };
 		F3BDD79120F51CB8004ECBF3 /* SDL_hidapijoystick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapijoystick.c; sourceTree = "<group>"; };
-		F3E3C55C223DEC6C007D243C /* SDL_hidapi_gamecube.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_gamecube.c; sourceTree = "<group>"; };
 		F3E3C65222406928007D243C /* libSDLmain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDLmain.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		F3E3C65222406928007D243C /* libSDLmain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDLmain.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		F3E3C657224069CE007D243C /* SDL_uikit_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_uikit_main.c; sourceTree = "<group>"; };
 		F3E3C657224069CE007D243C /* SDL_uikit_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_uikit_main.c; sourceTree = "<group>"; };
 		F3E3C7572241389A007D243C /* libSDL2.dylib */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		F3E3C7572241389A007D243C /* libSDL2.dylib */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		F3E3C75F224138AE007D243C /* libSDLmain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDLmain.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		F3E3C75F224138AE007D243C /* libSDLmain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDLmain.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitclipboard.h; sourceTree = "<group>"; };
 		FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitclipboard.h; sourceTree = "<group>"; };
 		FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitclipboard.m; sourceTree = "<group>"; };
 		FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitclipboard.m; sourceTree = "<group>"; };
+		FA20874D2307894C0029758C /* SDL_shaders_metal_tvos.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_shaders_metal_tvos.h; sourceTree = "<group>"; };
+		FA24348C21D4201400B8918A /* SDL_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_metal.h; sourceTree = "<group>"; };
 		FAB598141BB5C1B100BE72C5 /* libSDL2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		FAB598141BB5C1B100BE72C5 /* libSDL2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		FAD4F7011BA3C4E8008346CE /* SDL_sysjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysjoystick_c.h; sourceTree = "<group>"; };
 		FAD4F7011BA3C4E8008346CE /* SDL_sysjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysjoystick_c.h; sourceTree = "<group>"; };
 		FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitview.h; sourceTree = "<group>"; };
 		FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitview.h; sourceTree = "<group>"; };
@@ -1410,6 +1408,7 @@
 			children = (
 			children = (
 				AADC5A621FDA10C800960936 /* SDL_render_metal.m */,
 				AADC5A621FDA10C800960936 /* SDL_render_metal.m */,
 				AADC5A611FDA10C800960936 /* SDL_shaders_metal_ios.h */,
 				AADC5A611FDA10C800960936 /* SDL_shaders_metal_ios.h */,
+				FA20874D2307894C0029758C /* SDL_shaders_metal_tvos.h */,
 			);
 			);
 			path = metal;
 			path = metal;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -1463,7 +1462,6 @@
 		F3BDD78A20F51C8D004ECBF3 /* hidapi */ = {
 		F3BDD78A20F51C8D004ECBF3 /* hidapi */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				F3E3C55C223DEC6C007D243C /* SDL_hidapi_gamecube.c */,
 				F3BDD78E20F51CB8004ECBF3 /* SDL_hidapi_ps4.c */,
 				F3BDD78E20F51CB8004ECBF3 /* SDL_hidapi_ps4.c */,
 				F3BDD78C20F51CB8004ECBF3 /* SDL_hidapi_switch.c */,
 				F3BDD78C20F51CB8004ECBF3 /* SDL_hidapi_switch.c */,
 				F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */,
 				F3BDD78B20F51CB8004ECBF3 /* SDL_hidapi_xbox360.c */,
@@ -1582,15 +1580,14 @@
 			children = (
 			children = (
 				AA7558651595D55500BBD41B /* begin_code.h */,
 				AA7558651595D55500BBD41B /* begin_code.h */,
 				AA7558661595D55500BBD41B /* close_code.h */,
 				AA7558661595D55500BBD41B /* close_code.h */,
-				AA7558971595D55500BBD41B /* SDL.h */,
 				AA7558671595D55500BBD41B /* SDL_assert.h */,
 				AA7558671595D55500BBD41B /* SDL_assert.h */,
 				AA7558681595D55500BBD41B /* SDL_atomic.h */,
 				AA7558681595D55500BBD41B /* SDL_atomic.h */,
 				AA7558691595D55500BBD41B /* SDL_audio.h */,
 				AA7558691595D55500BBD41B /* SDL_audio.h */,
 				AADA5B8E16CCAB7C00107CF7 /* SDL_bits.h */,
 				AADA5B8E16CCAB7C00107CF7 /* SDL_bits.h */,
 				AA75586A1595D55500BBD41B /* SDL_blendmode.h */,
 				AA75586A1595D55500BBD41B /* SDL_blendmode.h */,
 				AA75586B1595D55500BBD41B /* SDL_clipboard.h */,
 				AA75586B1595D55500BBD41B /* SDL_clipboard.h */,
-				AA75586D1595D55500BBD41B /* SDL_config.h */,
 				AA75586C1595D55500BBD41B /* SDL_config_iphoneos.h */,
 				AA75586C1595D55500BBD41B /* SDL_config_iphoneos.h */,
+				AA75586D1595D55500BBD41B /* SDL_config.h */,
 				AA75586E1595D55500BBD41B /* SDL_copying.h */,
 				AA75586E1595D55500BBD41B /* SDL_copying.h */,
 				AA75586F1595D55500BBD41B /* SDL_cpuinfo.h */,
 				AA75586F1595D55500BBD41B /* SDL_cpuinfo.h */,
 				AA7558701595D55500BBD41B /* SDL_endian.h */,
 				AA7558701595D55500BBD41B /* SDL_endian.h */,
@@ -1608,6 +1605,7 @@
 				AA75587B1595D55500BBD41B /* SDL_log.h */,
 				AA75587B1595D55500BBD41B /* SDL_log.h */,
 				AA75587C1595D55500BBD41B /* SDL_main.h */,
 				AA75587C1595D55500BBD41B /* SDL_main.h */,
 				AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */,
 				AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */,
+				FA24348C21D4201400B8918A /* SDL_metal.h */,
 				AA75587D1595D55500BBD41B /* SDL_mouse.h */,
 				AA75587D1595D55500BBD41B /* SDL_mouse.h */,
 				AA75587E1595D55500BBD41B /* SDL_mutex.h */,
 				AA75587E1595D55500BBD41B /* SDL_mutex.h */,
 				AA75587F1595D55500BBD41B /* SDL_name.h */,
 				AA75587F1595D55500BBD41B /* SDL_name.h */,
@@ -1636,6 +1634,7 @@
 				AA7558951595D55500BBD41B /* SDL_version.h */,
 				AA7558951595D55500BBD41B /* SDL_version.h */,
 				AA7558961595D55500BBD41B /* SDL_video.h */,
 				AA7558961595D55500BBD41B /* SDL_video.h */,
 				4D7516FE1EE1C5B400820EEA /* SDL_vulkan.h */,
 				4D7516FE1EE1C5B400820EEA /* SDL_vulkan.h */,
+				AA7558971595D55500BBD41B /* SDL.h */,
 			);
 			);
 			name = "Public Headers";
 			name = "Public Headers";
 			path = ../../include;
 			path = ../../include;
@@ -2189,6 +2188,7 @@
 				AA75589D1595D55500BBD41B /* SDL_blendmode.h in Headers */,
 				AA75589D1595D55500BBD41B /* SDL_blendmode.h in Headers */,
 				F30D9C9E212CD0990047DF2E /* SDL_sensor_c.h in Headers */,
 				F30D9C9E212CD0990047DF2E /* SDL_sensor_c.h in Headers */,
 				AA75589E1595D55500BBD41B /* SDL_clipboard.h in Headers */,
 				AA75589E1595D55500BBD41B /* SDL_clipboard.h in Headers */,
+				FA24348D21D4201400B8918A /* SDL_metal.h in Headers */,
 				AA75589F1595D55500BBD41B /* SDL_config_iphoneos.h in Headers */,
 				AA75589F1595D55500BBD41B /* SDL_config_iphoneos.h in Headers */,
 				AA7558A01595D55500BBD41B /* SDL_config.h in Headers */,
 				AA7558A01595D55500BBD41B /* SDL_config.h in Headers */,
 				AA7558A11595D55500BBD41B /* SDL_copying.h in Headers */,
 				AA7558A11595D55500BBD41B /* SDL_copying.h in Headers */,
@@ -2518,7 +2518,6 @@
 				52ED1E24222889500061FCE0 /* SDL_uikitevents.m in Sources */,
 				52ED1E24222889500061FCE0 /* SDL_uikitevents.m in Sources */,
 				52ED1E25222889500061FCE0 /* yuv_rgb.c in Sources */,
 				52ED1E25222889500061FCE0 /* yuv_rgb.c in Sources */,
 				52ED1E26222889500061FCE0 /* SDL_uikitopengles.m in Sources */,
 				52ED1E26222889500061FCE0 /* SDL_uikitopengles.m in Sources */,
-				F3E3C55F224065AE007D243C /* SDL_hidapi_gamecube.c in Sources */,
 				52ED1E27222889500061FCE0 /* SDL_uikitvideo.m in Sources */,
 				52ED1E27222889500061FCE0 /* SDL_uikitvideo.m in Sources */,
 				52ED1E28222889500061FCE0 /* SDL_uikitview.m in Sources */,
 				52ED1E28222889500061FCE0 /* SDL_uikitview.m in Sources */,
 				52ED1E29222889500061FCE0 /* SDL_displayevents.c in Sources */,
 				52ED1E29222889500061FCE0 /* SDL_displayevents.c in Sources */,
@@ -2647,7 +2646,6 @@
 				F3E3C7122241389A007D243C /* SDL_uikitevents.m in Sources */,
 				F3E3C7122241389A007D243C /* SDL_uikitevents.m in Sources */,
 				F3E3C7132241389A007D243C /* yuv_rgb.c in Sources */,
 				F3E3C7132241389A007D243C /* yuv_rgb.c in Sources */,
 				F3E3C7142241389A007D243C /* SDL_uikitopengles.m in Sources */,
 				F3E3C7142241389A007D243C /* SDL_uikitopengles.m in Sources */,
-				F3E3C7152241389A007D243C /* SDL_hidapi_gamecube.c in Sources */,
 				F3E3C7162241389A007D243C /* SDL_uikitvideo.m in Sources */,
 				F3E3C7162241389A007D243C /* SDL_uikitvideo.m in Sources */,
 				F3E3C7172241389A007D243C /* SDL_uikitview.m in Sources */,
 				F3E3C7172241389A007D243C /* SDL_uikitview.m in Sources */,
 				F3E3C7182241389A007D243C /* SDL_displayevents.c in Sources */,
 				F3E3C7182241389A007D243C /* SDL_displayevents.c in Sources */,
@@ -2824,7 +2822,6 @@
 				FAB598BD1BB5C31600BE72C5 /* SDL_hints.c in Sources */,
 				FAB598BD1BB5C31600BE72C5 /* SDL_hints.c in Sources */,
 				FAB598BE1BB5C31600BE72C5 /* SDL_log.c in Sources */,
 				FAB598BE1BB5C31600BE72C5 /* SDL_log.c in Sources */,
 				FAB598BF1BB5C31600BE72C5 /* SDL.c in Sources */,
 				FAB598BF1BB5C31600BE72C5 /* SDL.c in Sources */,
-				F3E3C55E223DEC6C007D243C /* SDL_hidapi_gamecube.c in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -2895,7 +2892,6 @@
 				FD689F1D0E26E5D900F90B21 /* SDL_uikitevents.m in Sources */,
 				FD689F1D0E26E5D900F90B21 /* SDL_uikitevents.m in Sources */,
 				AA13B35A1FB8B46400D9FEE6 /* yuv_rgb.c in Sources */,
 				AA13B35A1FB8B46400D9FEE6 /* yuv_rgb.c in Sources */,
 				FD689F1F0E26E5D900F90B21 /* SDL_uikitopengles.m in Sources */,
 				FD689F1F0E26E5D900F90B21 /* SDL_uikitopengles.m in Sources */,
-				F3E3C55D223DEC6C007D243C /* SDL_hidapi_gamecube.c in Sources */,
 				FD689F210E26E5D900F90B21 /* SDL_uikitvideo.m in Sources */,
 				FD689F210E26E5D900F90B21 /* SDL_uikitvideo.m in Sources */,
 				FD689F230E26E5D900F90B21 /* SDL_uikitview.m in Sources */,
 				FD689F230E26E5D900F90B21 /* SDL_uikitview.m in Sources */,
 				A7C19D2A212E552C00DF2152 /* SDL_displayevents.c in Sources */,
 				A7C19D2A212E552C00DF2152 /* SDL_displayevents.c in Sources */,

+ 1 - 1
sdl.mod/SDL/Xcode-iOS/Test/Info.plist

@@ -11,7 +11,7 @@
 	<key>CFBundleIconFile</key>
 	<key>CFBundleIconFile</key>
 	<string></string>
 	<string></string>
 	<key>CFBundleIdentifier</key>
 	<key>CFBundleIdentifier</key>
-	<string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+	<string>com.yourcompany.${PRODUCT_NAME}</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<string>6.0</string>
 	<key>CFBundleName</key>
 	<key>CFBundleName</key>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 297 - 181
sdl.mod/SDL/Xcode-iOS/Test/TestiPhoneOS.xcodeproj/project.pbxproj


+ 2 - 2
sdl.mod/SDL/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.0.9</string>
+	<string>2.0.11</string>
 	<key>CFBundleSignature</key>
 	<key>CFBundleSignature</key>
 	<string>SDLX</string>
 	<string>SDLX</string>
 	<key>CFBundleVersion</key>
 	<key>CFBundleVersion</key>
-	<string>2.0.9</string>
+	<string>2.0.11</string>
 </dict>
 </dict>
 </plist>
 </plist>

+ 9 - 11
sdl.mod/SDL/Xcode/SDL/SDL.xcodeproj/project.pbxproj

@@ -919,9 +919,7 @@
 		F3950CD8212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CD8212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CD9212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CD9212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CDA212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3950CDA212BC88D00F51292 /* SDL_sensor.h in Headers */ = {isa = PBXBuildFile; fileRef = F3950CD7212BC88D00F51292 /* SDL_sensor.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		F3E3C559223DEBC7007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C558223DEBC7007D243C /* SDL_hidapi_gamecube.c */; };
-		F3E3C55A223DEBC7007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C558223DEBC7007D243C /* SDL_hidapi_gamecube.c */; };
-		F3E3C55B223DEBC7007D243C /* SDL_hidapi_gamecube.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E3C558223DEBC7007D243C /* SDL_hidapi_gamecube.c */; };
+		FA24348B21D41FFB00B8918A /* SDL_metal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA24348A21D41FFB00B8918A /* SDL_metal.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
@@ -1252,12 +1250,13 @@
 		F30D9CCB212EB4810047DF2E /* SDL_displayevents_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_displayevents_c.h; sourceTree = "<group>"; };
 		F30D9CCB212EB4810047DF2E /* SDL_displayevents_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_displayevents_c.h; sourceTree = "<group>"; };
 		F30D9CCC212EB4810047DF2E /* SDL_displayevents.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_displayevents.c; sourceTree = "<group>"; };
 		F30D9CCC212EB4810047DF2E /* SDL_displayevents.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_displayevents.c; sourceTree = "<group>"; };
 		F3950CD7212BC88D00F51292 /* SDL_sensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sensor.h; sourceTree = "<group>"; };
 		F3950CD7212BC88D00F51292 /* SDL_sensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sensor.h; sourceTree = "<group>"; };
-		F3E3C558223DEBC7007D243C /* SDL_hidapi_gamecube.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_gamecube.c; sourceTree = "<group>"; };
 		F59C710300D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; };
 		F59C710300D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; };
 		F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
 		F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
 		F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
 		F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
+		FA24348A21D41FFB00B8918A /* SDL_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_metal.h; sourceTree = "<group>"; };
 		FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
 		FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
 		FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coreaudio.m; sourceTree = "<group>"; };
 		FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coreaudio.m; sourceTree = "<group>"; };
+		FAF136422308312A00F414DE /* SDL_shaders_metal.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = SDL_shaders_metal.metal; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -1346,6 +1345,7 @@
 				AA7557DD1595D4D800BBD41B /* SDL_log.h */,
 				AA7557DD1595D4D800BBD41B /* SDL_log.h */,
 				AA7557DE1595D4D800BBD41B /* SDL_main.h */,
 				AA7557DE1595D4D800BBD41B /* SDL_main.h */,
 				AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */,
 				AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */,
+				FA24348A21D41FFB00B8918A /* SDL_metal.h */,
 				AA7557DF1595D4D800BBD41B /* SDL_mouse.h */,
 				AA7557DF1595D4D800BBD41B /* SDL_mouse.h */,
 				AA7557E01595D4D800BBD41B /* SDL_mutex.h */,
 				AA7557E01595D4D800BBD41B /* SDL_mutex.h */,
 				AA7557E11595D4D800BBD41B /* SDL_name.h */,
 				AA7557E11595D4D800BBD41B /* SDL_name.h */,
@@ -1932,7 +1932,6 @@
 		A704170C20F09AA600A82227 /* hidapi */ = {
 		A704170C20F09AA600A82227 /* hidapi */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				F3E3C558223DEBC7007D243C /* SDL_hidapi_gamecube.c */,
 				A704171120F09AC900A82227 /* SDL_hidapi_ps4.c */,
 				A704171120F09AC900A82227 /* SDL_hidapi_ps4.c */,
 				A704170F20F09AC800A82227 /* SDL_hidapi_switch.c */,
 				A704170F20F09AC800A82227 /* SDL_hidapi_switch.c */,
 				A704171320F09AC900A82227 /* SDL_hidapi_xbox360.c */,
 				A704171320F09AC900A82227 /* SDL_hidapi_xbox360.c */,
@@ -1965,6 +1964,7 @@
 			children = (
 			children = (
 				AADC5A421FDA035D00960936 /* SDL_render_metal.m */,
 				AADC5A421FDA035D00960936 /* SDL_render_metal.m */,
 				AADC5A411FDA035D00960936 /* SDL_shaders_metal_osx.h */,
 				AADC5A411FDA035D00960936 /* SDL_shaders_metal_osx.h */,
+				FAF136422308312A00F414DE /* SDL_shaders_metal.metal */,
 			);
 			);
 			path = metal;
 			path = metal;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -2043,6 +2043,7 @@
 				AA75581E1595D4D800BBD41B /* SDL_joystick.h in Headers */,
 				AA75581E1595D4D800BBD41B /* SDL_joystick.h in Headers */,
 				AA7558201595D4D800BBD41B /* SDL_keyboard.h in Headers */,
 				AA7558201595D4D800BBD41B /* SDL_keyboard.h in Headers */,
 				F3950CD8212BC88D00F51292 /* SDL_sensor.h in Headers */,
 				F3950CD8212BC88D00F51292 /* SDL_sensor.h in Headers */,
+				FA24348B21D41FFB00B8918A /* SDL_metal.h in Headers */,
 				AA7558221595D4D800BBD41B /* SDL_keycode.h in Headers */,
 				AA7558221595D4D800BBD41B /* SDL_keycode.h in Headers */,
 				F30D9C84212BC94F0047DF2E /* SDL_sensor_c.h in Headers */,
 				F30D9C84212BC94F0047DF2E /* SDL_sensor_c.h in Headers */,
 				AA7558241595D4D800BBD41B /* SDL_loadso.h in Headers */,
 				AA7558241595D4D800BBD41B /* SDL_loadso.h in Headers */,
@@ -2671,7 +2672,7 @@
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
-			shellScript = "# Sign framework\nif [ \"$SDL_CODESIGN_IDENTITY\" != \"\" ]; then\n    codesign --force --deep --sign \"$SDL_CODESIGN_IDENTITY\" $TARGET_BUILD_DIR/SDL2.framework/Versions/A\nfi\n\n# clean up the framework, remove headers, extra files\nmkdir -p build/dmg-tmp\nxcrun CpMac -r $TARGET_BUILD_DIR/SDL2.framework build/dmg-tmp/\n\ncp pkg-support/resources/License.txt build/dmg-tmp\ncp pkg-support/resources/ReadMe.txt build/dmg-tmp\n\n# remove the .DS_Store files if any (we may want to provide one in the future for fancy .dmgs)\nfind build/dmg-tmp -name .DS_Store -exec rm -f \"{}\" \\;\n\n# for fancy .dmg\nmkdir -p build/dmg-tmp/.logo\ncp pkg-support/resources/SDL_DS_Store build/dmg-tmp/.DS_Store\ncp pkg-support/sdl_logo.pdf build/dmg-tmp/.logo\n\n# create the dmg\nhdiutil create -ov -fs HFS+ -volname SDL2 -srcfolder build/dmg-tmp build/SDL2.dmg\n\n# clean up\nrm -rf build/dmg-tmp";
+			shellScript = "# Sign framework\nif [ \"$SDL_CODESIGN_IDENTITY\" != \"\" ]; then\n    codesign --force --deep --sign \"$SDL_CODESIGN_IDENTITY\" $TARGET_BUILD_DIR/SDL2.framework/Versions/A || exit $?\nfi\n\n# clean up the framework, remove headers, extra files\nmkdir -p build/dmg-tmp\ncp -a $TARGET_BUILD_DIR/SDL2.framework build/dmg-tmp/\n\ncp pkg-support/resources/License.txt build/dmg-tmp\ncp pkg-support/resources/ReadMe.txt build/dmg-tmp\n\n# remove the .DS_Store files if any (we may want to provide one in the future for fancy .dmgs)\nfind build/dmg-tmp -name .DS_Store -exec rm -f \"{}\" \\;\n\n# for fancy .dmg\nmkdir -p build/dmg-tmp/.logo\ncp pkg-support/resources/SDL_DS_Store build/dmg-tmp/.DS_Store\ncp pkg-support/sdl_logo.pdf build/dmg-tmp/.logo\n\n# create the dmg\nhdiutil create -ov -fs HFS+ -volname SDL2 -srcfolder build/dmg-tmp build/SDL2.dmg\n\n# clean up\nrm -rf build/dmg-tmp\n";
 		};
 		};
 /* End PBXShellScriptBuildPhase section */
 /* End PBXShellScriptBuildPhase section */
 
 
@@ -2707,7 +2708,6 @@
 				04BD005B12E6671800899322 /* SDL_syshaptic.c in Sources */,
 				04BD005B12E6671800899322 /* SDL_syshaptic.c in Sources */,
 				04BD005F12E6671800899322 /* SDL_haptic.c in Sources */,
 				04BD005F12E6671800899322 /* SDL_haptic.c in Sources */,
 				4D1664551EDD60AD003DE88E /* SDL_cocoavulkan.m in Sources */,
 				4D1664551EDD60AD003DE88E /* SDL_cocoavulkan.m in Sources */,
-				F3E3C559223DEBC7007D243C /* SDL_hidapi_gamecube.c in Sources */,
 				04BD006612E6671800899322 /* SDL_sysjoystick.c in Sources */,
 				04BD006612E6671800899322 /* SDL_sysjoystick.c in Sources */,
 				04BD007012E6671800899322 /* SDL_joystick.c in Sources */,
 				04BD007012E6671800899322 /* SDL_joystick.c in Sources */,
 				04BD008812E6671800899322 /* SDL_sysloadso.c in Sources */,
 				04BD008812E6671800899322 /* SDL_sysloadso.c in Sources */,
@@ -2846,7 +2846,6 @@
 				04BD026D12E6671800899322 /* SDL_quit.c in Sources */,
 				04BD026D12E6671800899322 /* SDL_quit.c in Sources */,
 				04BD026F12E6671800899322 /* SDL_touch.c in Sources */,
 				04BD026F12E6671800899322 /* SDL_touch.c in Sources */,
 				04BD027112E6671800899322 /* SDL_windowevents.c in Sources */,
 				04BD027112E6671800899322 /* SDL_windowevents.c in Sources */,
-				F3E3C55A223DEBC7007D243C /* SDL_hidapi_gamecube.c in Sources */,
 				04BD027412E6671800899322 /* SDL_rwopsbundlesupport.m in Sources */,
 				04BD027412E6671800899322 /* SDL_rwopsbundlesupport.m in Sources */,
 				04BD027512E6671800899322 /* SDL_rwops.c in Sources */,
 				04BD027512E6671800899322 /* SDL_rwops.c in Sources */,
 				04BD027612E6671800899322 /* SDL_syshaptic.c in Sources */,
 				04BD027612E6671800899322 /* SDL_syshaptic.c in Sources */,
@@ -2985,7 +2984,6 @@
 				DB31401017554B71006C0E22 /* SDL_quit.c in Sources */,
 				DB31401017554B71006C0E22 /* SDL_quit.c in Sources */,
 				DB31401117554B71006C0E22 /* SDL_touch.c in Sources */,
 				DB31401117554B71006C0E22 /* SDL_touch.c in Sources */,
 				DB31401217554B71006C0E22 /* SDL_windowevents.c in Sources */,
 				DB31401217554B71006C0E22 /* SDL_windowevents.c in Sources */,
-				F3E3C55B223DEBC7007D243C /* SDL_hidapi_gamecube.c in Sources */,
 				DB31401317554B71006C0E22 /* SDL_rwopsbundlesupport.m in Sources */,
 				DB31401317554B71006C0E22 /* SDL_rwopsbundlesupport.m in Sources */,
 				DB31401417554B71006C0E22 /* SDL_rwops.c in Sources */,
 				DB31401417554B71006C0E22 /* SDL_rwops.c in Sources */,
 				DB31401517554B71006C0E22 /* SDL_syshaptic.c in Sources */,
 				DB31401517554B71006C0E22 /* SDL_syshaptic.c in Sources */,
@@ -3160,7 +3158,7 @@
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				COMBINE_HIDPI_IMAGES = YES;
 				COMBINE_HIDPI_IMAGES = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
-				DYLIB_CURRENT_VERSION = 10.0.0;
+				DYLIB_CURRENT_VERSION = 12.0.0;
 				FRAMEWORK_SEARCH_PATHS = (
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"$(PROJECT_DIR)",
 					"$(PROJECT_DIR)",
@@ -3259,7 +3257,7 @@
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				COMBINE_HIDPI_IMAGES = YES;
 				COMBINE_HIDPI_IMAGES = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
-				DYLIB_CURRENT_VERSION = 10.0.0;
+				DYLIB_CURRENT_VERSION = 12.0.0;
 				FRAMEWORK_SEARCH_PATHS = (
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"$(PROJECT_DIR)",
 					"$(PROJECT_DIR)",

+ 8 - 0
sdl.mod/SDL/android-project/app/build.gradle

@@ -22,6 +22,11 @@ android {
                 arguments "APP_PLATFORM=android-16"
                 arguments "APP_PLATFORM=android-16"
                 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
             }
             }
+            // cmake {
+            //     arguments "-DANDROID_APP_PLATFORM=android-16", "-DANDROID_STL=c++_static"
+            //     // abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
+            //     abiFilters 'arm64-v8a'
+            // }
         }
         }
     }
     }
     buildTypes {
     buildTypes {
@@ -38,6 +43,9 @@ android {
             ndkBuild {
             ndkBuild {
                 path 'jni/Android.mk'
                 path 'jni/Android.mk'
             }
             }
+            // cmake {
+            //     path 'jni/CMakeLists.txt'
+            // }
         }
         }
        
        
     }
     }

+ 20 - 0
sdl.mod/SDL/android-project/app/jni/CMakeLists.txt

@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(GAME)
+
+# armeabi-v7a requires cpufeatures library
+# include(AndroidNdkModules)
+# android_ndk_import_module_cpufeatures()
+
+
+# SDL sources are in a subfolder named "SDL"
+add_subdirectory(SDL)
+
+# Compilation of companion libraries
+#add_subdirectory(SDL_image)
+#add_subdirectory(SDL_mixer)
+#add_subdirectory(SDL_ttf)
+
+# Your game and its CMakeLists.txt are in a subfolder named "src"
+add_subdirectory(src)
+

+ 13 - 0
sdl.mod/SDL/android-project/app/jni/src/CMakeLists.txt

@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(MY_APP)
+
+find_library(SDL2 SDL2)
+
+add_library(main SHARED)
+
+target_sources(main PRIVATE YourSourceHere.c)
+
+target_link_libraries(main SDL2)
+
+

+ 70 - 8
sdl.mod/SDL/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java

@@ -846,6 +846,45 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
         }
         }
     }
     }
 
 
+    /**
+     * This method is called by SDL using JNI.
+     */
+    public static void minimizeWindow() {
+
+        if (mSingleton == null) {
+            return;
+        }
+
+        Intent startMain = new Intent(Intent.ACTION_MAIN);
+        startMain.addCategory(Intent.CATEGORY_HOME);
+        startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mSingleton.startActivity(startMain);
+    }
+
+    /**
+     * This method is called by SDL using JNI.
+     */
+    public static boolean shouldMinimizeOnFocusLoss() {
+/*
+        if (Build.VERSION.SDK_INT >= 24) {
+            if (mSingleton == null) {
+                return true;
+            }
+
+            if (mSingleton.isInMultiWindowMode()) {
+                return false;
+            }
+
+            if (mSingleton.isInPictureInPictureMode()) {
+                return false;
+            }
+        }
+
+        return true;
+*/
+        return false;
+    }
+
     /**
     /**
      * This method is called by SDL using JNI.
      * This method is called by SDL using JNI.
      */
      */
@@ -1700,6 +1739,8 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
         SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, sdlFormat, mDisplay.getRefreshRate());
         SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, sdlFormat, mDisplay.getRefreshRate());
         SDLActivity.onNativeResize();
         SDLActivity.onNativeResize();
 
 
+        // Prevent a screen distortion glitch,
+        // for instance when the device is in Landscape and a Portrait App is resumed.
         boolean skip = false;
         boolean skip = false;
         int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
         int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
 
 
@@ -1729,6 +1770,16 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
            }
            }
         }
         }
 
 
+        // Don't skip in MultiWindow.
+        if (skip) {
+            if (Build.VERSION.SDK_INT >= 24) {
+                if (SDLActivity.mSingleton.isInMultiWindowMode()) {
+                    Log.v("SDL", "Don't skip in Multi-Window");
+                    skip = false;
+                }
+            }
+        }
+
         if (skip) {
         if (skip) {
            Log.v("SDL", "Skip .. Surface is not ready.");
            Log.v("SDL", "Skip .. Surface is not ready.");
            mIsSurfaceReady = false;
            mIsSurfaceReady = false;
@@ -1748,6 +1799,10 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
     // Key events
     // Key events
     @Override
     @Override
     public boolean onKey(View  v, int keyCode, KeyEvent event) {
     public boolean onKey(View  v, int keyCode, KeyEvent event) {
+
+        int deviceId = event.getDeviceId();
+        int source = event.getSource();
+
         // Dispatch the different events depending on where they come from
         // Dispatch the different events depending on where they come from
         // Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
         // Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
         // So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
         // So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
@@ -1755,20 +1810,27 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
         // Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
         // Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
         // SOURCE_JOYSTICK, while its key events arrive from the keyboard source
         // SOURCE_JOYSTICK, while its key events arrive from the keyboard source
         // So, retrieve the device itself and check all of its sources
         // So, retrieve the device itself and check all of its sources
-        if (SDLControllerManager.isDeviceSDLJoystick(event.getDeviceId())) {
+        if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
             // Note that we process events with specific key codes here
             // Note that we process events with specific key codes here
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                if (SDLControllerManager.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
+                if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) {
                     return true;
                     return true;
                 }
                 }
             } else if (event.getAction() == KeyEvent.ACTION_UP) {
             } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                if (SDLControllerManager.onNativePadUp(event.getDeviceId(), keyCode) == 0) {
+                if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) {
                     return true;
                     return true;
                 }
                 }
             }
             }
         }
         }
 
 
-        if ((event.getSource() & InputDevice.SOURCE_KEYBOARD) != 0) {
+        if (source == InputDevice.SOURCE_UNKNOWN) {
+            InputDevice device = InputDevice.getDevice(deviceId);
+            if (device != null) {
+                source = device.getSources();
+            }
+        }
+
+        if ((source & InputDevice.SOURCE_KEYBOARD) != 0) {
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
                 //Log.v("SDL", "key down: " + keyCode);
                 //Log.v("SDL", "key down: " + keyCode);
                 if (SDLActivity.isTextInputEvent(event)) {
                 if (SDLActivity.isTextInputEvent(event)) {
@@ -1784,7 +1846,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
             }
             }
         }
         }
 
 
-        if ((event.getSource() & InputDevice.SOURCE_MOUSE) != 0) {
+        if ((source & InputDevice.SOURCE_MOUSE) != 0) {
             // 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
             if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
             if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
@@ -1932,8 +1994,8 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
                     newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
                     newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
                     break;
                     break;
                 case Surface.ROTATION_180:
                 case Surface.ROTATION_180:
-                    x = -event.values[1];
-                    y = -event.values[0];
+                    x = -event.values[0];
+                    y = -event.values[1];
                     newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
                     newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
                     break;
                     break;
                 default:
                 default:
@@ -2058,7 +2120,7 @@ class DummyEdit extends View implements View.OnKeyListener {
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
         ic = new SDLInputConnection(this, true);
         ic = new SDLInputConnection(this, true);
 
 
-        outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
+        outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
         outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
         outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
                 | EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
                 | EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
 
 

+ 1 - 1
sdl.mod/SDL/build-scripts/winrtbuild.ps1

@@ -39,7 +39,7 @@
 #
 #
 
 
 # Base version of SDL, used for packaging purposes
 # Base version of SDL, used for packaging purposes
-$SDLVersion = "2.0.9"
+$SDLVersion = "2.0.11"
 
 
 # Gets the .bat file that sets up an MSBuild environment, given one of
 # Gets the .bat file that sets up an MSBuild environment, given one of
 # Visual Studio's, "PlatformToolset"s.
 # Visual Studio's, "PlatformToolset"s.

+ 38 - 0
sdl.mod/SDL/cmake/sdlchecks.cmake

@@ -1065,6 +1065,44 @@ macro(CheckUSBHID)
   endif()
   endif()
 endmacro()
 endmacro()
 
 
+# Check for HIDAPI joystick drivers. This is currently a Unix thing, not Windows or macOS!
+macro(CheckHIDAPI)
+  if(HIDAPI)
+    if(HIDAPI_SKIP_LIBUSB)
+      set(HAVE_HIDAPI TRUE)
+    else()
+      set(HAVE_HIDAPI FALSE)
+      pkg_check_modules(LIBUSB libusb)
+      if (LIBUSB_FOUND)
+        check_include_file(libusb.h HAVE_LIBUSB_H ${LIBUSB_CFLAGS})
+        if (HAVE_LIBUSB_H)
+          set(HAVE_HIDAPI TRUE)
+        endif()
+      endif()
+    endif()
+
+    if(HAVE_HIDAPI)
+      set(SDL_JOYSTICK_HIDAPI 1)
+      set(HAVE_SDL_JOYSTICK TRUE)
+      file(GLOB HIDAPI_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/hidapi/*.c)
+      set(SOURCE_FILES ${SOURCE_FILES} ${HIDAPI_SOURCES})
+      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBUSB_CFLAGS} -I${SDL2_SOURCE_DIR}/src/hidapi/hidapi")
+      if(NOT HIDAPI_SKIP_LIBUSB)
+        if(HIDAPI_ONLY_LIBUSB)
+          set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/hidapi/libusb/hid.c)
+          list(APPEND EXTRA_LIBS ${LIBUSB_LIBS})
+        else()
+          set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/hidapi/SDL_hidapi.c)
+          # libusb is loaded dynamically, so don't add it to EXTRA_LIBS
+          FindLibraryAndSONAME("usb-1.0")
+          set(SDL_LIBUSB_DYNAMIC "\"${USB_LIB_SONAME}\"")
+        endif()
+      endif()
+    endif()
+  endif()
+endmacro()
+
+
 # Requires:
 # Requires:
 # - n/a
 # - n/a
 macro(CheckRPI)
 macro(CheckRPI)

+ 271 - 55
sdl.mod/SDL/configure

@@ -852,6 +852,8 @@ enable_diskaudio
 enable_dummyaudio
 enable_dummyaudio
 enable_libsamplerate
 enable_libsamplerate
 enable_libsamplerate_shared
 enable_libsamplerate_shared
+enable_arm_simd
+enable_arm_neon
 enable_video_wayland
 enable_video_wayland
 enable_video_wayland_qt_touch
 enable_video_wayland_qt_touch
 enable_wayland_shared
 enable_wayland_shared
@@ -869,6 +871,7 @@ enable_video_x11_xshape
 enable_video_x11_vm
 enable_video_x11_vm
 enable_video_vivante
 enable_video_vivante
 enable_video_cocoa
 enable_video_cocoa
+enable_video_metal
 enable_render_metal
 enable_render_metal
 enable_video_directfb
 enable_video_directfb
 enable_directfb_shared
 enable_directfb_shared
@@ -1621,12 +1624,14 @@ Optional Features:
                           [[default=yes]]
                           [[default=yes]]
   --enable-libsamplerate-shared
   --enable-libsamplerate-shared
                           dynamically load libsamplerate [[default=yes]]
                           dynamically load libsamplerate [[default=yes]]
+  --enable-arm-simd       use SIMD assembly blitters on ARM [[default=yes]]
+  --enable-arm-neon       use NEON assembly blitters on ARM [[default=yes]]
   --enable-video-wayland  use Wayland video driver [[default=yes]]
   --enable-video-wayland  use Wayland video driver [[default=yes]]
   --enable-video-wayland-qt-touch
   --enable-video-wayland-qt-touch
                           QtWayland server support for Wayland video driver
                           QtWayland server support for Wayland video driver
                           [[default=yes]]
                           [[default=yes]]
   --enable-wayland-shared dynamically load Wayland support [[default=maybe]]
   --enable-wayland-shared dynamically load Wayland support [[default=maybe]]
-  --enable-video-rpi      use Raspberry Pi video driver [[default=no]]
+  --enable-video-rpi      use Raspberry Pi video driver [[default=yes]]
   --enable-video-x11      use X11 video driver [[default=yes]]
   --enable-video-x11      use X11 video driver [[default=yes]]
   --enable-x11-shared     dynamically load X11 support [[default=maybe]]
   --enable-x11-shared     dynamically load X11 support [[default=maybe]]
   --enable-video-x11-xcursor
   --enable-video-x11-xcursor
@@ -1647,6 +1652,7 @@ Optional Features:
   --enable-video-x11-vm   use X11 VM extension for fullscreen [[default=yes]]
   --enable-video-x11-vm   use X11 VM extension for fullscreen [[default=yes]]
   --enable-video-vivante  use Vivante EGL video driver [[default=yes]]
   --enable-video-vivante  use Vivante EGL video driver [[default=yes]]
   --enable-video-cocoa    use Cocoa video driver [[default=yes]]
   --enable-video-cocoa    use Cocoa video driver [[default=yes]]
+  --enable-video-metal    include Metal support [[default=yes]]
   --enable-render-metal   enable the Metal render driver [[default=yes]]
   --enable-render-metal   enable the Metal render driver [[default=yes]]
   --enable-video-directfb use DirectFB video driver [[default=no]]
   --enable-video-directfb use DirectFB video driver [[default=no]]
   --enable-directfb-shared
   --enable-directfb-shared
@@ -2811,9 +2817,9 @@ orig_CFLAGS="$CFLAGS"
 #
 #
 SDL_MAJOR_VERSION=2
 SDL_MAJOR_VERSION=2
 SDL_MINOR_VERSION=0
 SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=9
+SDL_MICRO_VERSION=11
 SDL_INTERFACE_AGE=0
 SDL_INTERFACE_AGE=0
-SDL_BINARY_AGE=9
+SDL_BINARY_AGE=11
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 
 
 
@@ -19356,6 +19362,106 @@ _ACEOF
     fi
     fi
 }
 }
 
 
+CheckARM()
+{
+    # Check whether --enable-arm-simd was given.
+if test "${enable_arm_simd+set}" = set; then :
+  enableval=$enable_arm_simd; enable_arm_simd=$enableval
+else
+  enable_arm_simd=yes
+fi
+
+    if test x$enable_video = xyes -a x$enable_assembly = xyes -a x$enable_arm_simd = xyes; then
+        save_CFLAGS="$CFLAGS"
+        have_arm_simd=no
+        CFLAGS="-x assembler-with-cpp $CFLAGS"
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM SIMD" >&5
+$as_echo_n "checking for ARM SIMD... " >&6; }
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+        .text
+        .arch armv6
+        .object_arch armv4
+        .arm
+        .altmacro
+        #ifndef __ARM_EABI__
+        #error EABI is required (to be sure that calling conventions are compatible)
+        #endif
+        pld [r0]
+        uqadd8 r0, r0, r0
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  have_arm_simd=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_arm_simd" >&5
+$as_echo "$have_arm_simd" >&6; }
+
+        CFLAGS="$save_CFLAGS"
+
+        if test x$have_arm_simd = xyes; then
+            $as_echo "#define SDL_ARM_SIMD_BLITTERS 1" >>confdefs.h
+
+            SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-simd*.S"
+            WARN_ABOUT_ARM_SIMD_ASM_MIT="yes"
+        fi
+    fi
+}
+
+CheckNEON()
+{
+    # Check whether --enable-arm-neon was given.
+if test "${enable_arm_neon+set}" = set; then :
+  enableval=$enable_arm_neon; enable_arm_neon=$enableval
+else
+  enable_arm_neon=yes
+fi
+
+    if test x$enable_video = xyes -a x$enable_assembly = xyes -a x$enable_arm_neon = xyes; then
+        save_CFLAGS="$CFLAGS"
+        have_arm_neon=no
+        CFLAGS="-x assembler-with-cpp $CFLAGS"
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM NEON" >&5
+$as_echo_n "checking for ARM NEON... " >&6; }
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+        .text
+        .fpu neon
+        .arch armv7a
+        .object_arch armv4
+        .eabi_attribute 10, 0
+        .arm
+        .altmacro
+        #ifndef __ARM_EABI__
+        #error EABI is required (to be sure that calling conventions are compatible)
+        #endif
+        pld [r0]
+        vmovn.u16 d0, q0
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  have_arm_neon=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_arm_neon" >&5
+$as_echo "$have_arm_neon" >&6; }
+
+        CFLAGS="$save_CFLAGS"
+
+        if test x$have_arm_neon = xyes; then
+            $as_echo "#define SDL_ARM_NEON_BLITTERS 1" >>confdefs.h
+
+            SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-neon*.S"
+            WARN_ABOUT_ARM_NEON_ASM_MIT="yes"
+        fi
+    fi
+}
+
 CheckVisibilityHidden()
 CheckVisibilityHidden()
 {
 {
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -fvisibility=hidden option" >&5
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -fvisibility=hidden option" >&5
@@ -19396,6 +19502,43 @@ $as_echo "$have_gcc_fvisibility" >&6; }
     fi
     fi
 }
 }
 
 
+CheckNoStrictAliasing()
+{
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -fno-strict-aliasing option" >&5
+$as_echo_n "checking for GCC -fno-strict-aliasing option... " >&6; }
+    have_gcc_no_strict_aliasing=no
+
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$save_CFLAGS -fno-strict-aliasing"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+    int x = 0;
+
+int
+main ()
+{
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+    have_gcc_no_strict_aliasing=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_no_strict_aliasing" >&5
+$as_echo "$have_gcc_no_strict_aliasing" >&6; }
+    CFLAGS="$save_CFLAGS"
+
+    if test x$have_gcc_no_strict_aliasing = xyes; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -fno-strict-aliasing"
+    fi
+}
+
 CheckStackBoundary()
 CheckStackBoundary()
 {
 {
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -mpreferred-stack-boundary option" >&5
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -mpreferred-stack-boundary option" >&5
@@ -19697,7 +19840,7 @@ CheckRPI()
 if test "${enable_video_rpi+set}" = set; then :
 if test "${enable_video_rpi+set}" = set; then :
   enableval=$enable_video_rpi;
   enableval=$enable_video_rpi;
 else
 else
-  enable_video_rpi=no
+  enable_video_rpi=yes
 fi
 fi
 
 
     if test x$enable_video = xyes -a x$enable_video_rpi = xyes; then
     if test x$enable_video = xyes -a x$enable_video_rpi = xyes; then
@@ -19847,10 +19990,10 @@ fi
                 # This isn't necessary for X11, but fixes GLX detection
                 # This isn't necessary for X11, but fixes GLX detection
                 if test "x$x_includes" = xNONE && \
                 if test "x$x_includes" = xNONE && \
                    test "x$x_libraries" = xNONE && \
                    test "x$x_libraries" = xNONE && \
-                   test -d /usr/X11R6/include && \
-                   test -d /usr/X11R6/lib; then
-                    x_includes="/usr/X11R6/include"
-                    x_libraries="/usr/X11R6/lib"
+                   test -d /opt/X11/include && \
+                   test -d /opt/X11/lib; then
+                    x_includes="/opt/X11/include"
+                    x_libraries="/opt/X11/lib"
                 fi
                 fi
                 ;;
                 ;;
         esac
         esac
@@ -20548,15 +20691,16 @@ fi
 
 
             case "$host" in
             case "$host" in
                 *-*-darwin*)
                 *-*-darwin*)
-                    x11_lib='/usr/X11R6/lib/libX11.6.dylib'
-                    x11ext_lib='/usr/X11R6/lib/libXext.6.dylib'
-                    xcursor_lib='/usr/X11R6/lib/libXcursor.1.dylib'
-                    xinerama_lib='/usr/X11R6/lib/libXinerama.1.dylib'
-                    xinput_lib='/usr/X11R6/lib/libXi.6.dylib'
-                    xrandr_lib='/usr/X11R6/lib/libXrandr.2.dylib'
-                    xrender_lib='/usr/X11R6/lib/libXrender.1.dylib'
-                    xss_lib='/usr/X11R6/lib/libXss.1.dylib'
-                    xvidmode_lib='/usr/X11R6/lib/libXxf86vm.1.dylib'
+                    # Apple now puts this in /opt/X11
+                    x11_lib='/opt/X11/lib/libX11.6.dylib'
+                    x11ext_lib='/opt/X11/lib/libXext.6.dylib'
+                    xcursor_lib='/opt/X11/lib/libXcursor.1.dylib'
+                    xinerama_lib='/opt/X11/lib/libXinerama.1.dylib'
+                    xinput_lib='/opt/X11/lib/libXi.6.dylib'
+                    xrandr_lib='/opt/X11/lib/libXrandr.2.dylib'
+                    xrender_lib='/opt/X11/lib/libXrender.1.dylib'
+                    xss_lib='/opt/X11/lib/libXss.1.dylib'
+                    xvidmode_lib='/opt/X11/lib/libXxf86vm.1.dylib'
                     ;;
                     ;;
                 *-*-openbsd*)
                 *-*-openbsd*)
                     x11_lib='libX11.so'
                     x11_lib='libX11.so'
@@ -21493,6 +21637,13 @@ $as_echo "#define SDL_VIDEO_DRIVER_COCOA 1" >>confdefs.h
 
 
 CheckMETAL()
 CheckMETAL()
 {
 {
+    # Check whether --enable-video-metal was given.
+if test "${enable_video_metal+set}" = set; then :
+  enableval=$enable_video_metal;
+else
+  enable_video_metal=yes
+fi
+
     # Check whether --enable-render-metal was given.
     # Check whether --enable-render-metal was given.
 if test "${enable_render_metal+set}" = set; then :
 if test "${enable_render_metal+set}" = set; then :
   enableval=$enable_render_metal;
   enableval=$enable_render_metal;
@@ -21500,7 +21651,7 @@ else
   enable_render_metal=yes
   enable_render_metal=yes
 fi
 fi
 
 
-    if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+    if test x$enable_video = xyes -a x$enable_video_metal = xyes; then
         save_CFLAGS="$CFLAGS"
         save_CFLAGS="$CFLAGS"
                 CFLAGS="$CFLAGS -x objective-c"
                 CFLAGS="$CFLAGS -x objective-c"
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Metal framework" >&5
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Metal framework" >&5
@@ -21537,11 +21688,17 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 $as_echo "$have_metal" >&6; }
 $as_echo "$have_metal" >&6; }
         if test x$have_metal = xyes; then
         if test x$have_metal = xyes; then
 
 
+$as_echo "#define SDL_VIDEO_METAL 1" >>confdefs.h
+
+            if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+
 $as_echo "#define SDL_VIDEO_RENDER_METAL 1" >>confdefs.h
 $as_echo "#define SDL_VIDEO_RENDER_METAL 1" >>confdefs.h
 
 
-            SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+                SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+            fi
             SUMMARY_video="${SUMMARY_video} metal"
             SUMMARY_video="${SUMMARY_video} metal"
         else
         else
+            enable_video_metal=no
             enable_render_metal=no
             enable_render_metal=no
         fi
         fi
     fi
     fi
@@ -22679,7 +22836,7 @@ fi
 
 
 $as_echo "#define SDL_USE_IME 1" >>confdefs.h
 $as_echo "#define SDL_USE_IME 1" >>confdefs.h
 
 
-            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
+        SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
     fi
     fi
 }
 }
 
 
@@ -23571,14 +23728,6 @@ fi
 
 
     fi
     fi
 
 
-    ac_fn_c_check_header_mongrel "$LINENO" "endpointvolume.h" "ac_cv_header_endpointvolume_h" "$ac_includes_default"
-if test "x$ac_cv_header_endpointvolume_h" = xyes; then :
-  $as_echo "#define HAVE_ENDPOINTVOLUME_H 1" >>confdefs.h
-
-fi
-
-
-
     # Check whether --enable-wasapi was given.
     # Check whether --enable-wasapi was given.
 if test "${enable_wasapi+set}" = set; then :
 if test "${enable_wasapi+set}" = set; then :
   enableval=$enable_wasapi;
   enableval=$enable_wasapi;
@@ -24068,8 +24217,17 @@ CheckHIDAPI()
 {
 {
     # The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers,
     # The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers,
     # so we'll just use libusb when it's available.
     # so we'll just use libusb when it's available.
-    #
-    # Except that libusb requires root permissions to open devices, so that's not generally useful, and we'll disable this by default.
+    case "$host" in
+        # libusb does not support iOS
+        arm*-apple-darwin* | *-ios-* )
+            skiplibusb=yes
+            ;;
+        # On the other hand, *BSD specifically uses libusb only
+        *-*-*bsd* )
+            onlylibusb=yes
+            ;;
+    esac
+
     # Check whether --enable-hidapi was given.
     # Check whether --enable-hidapi was given.
 if test "${enable_hidapi+set}" = set; then :
 if test "${enable_hidapi+set}" = set; then :
   enableval=$enable_hidapi;
   enableval=$enable_hidapi;
@@ -24078,6 +24236,9 @@ else
 fi
 fi
 
 
     if test x$enable_joystick = xyes -a x$enable_hidapi = xyes; then
     if test x$enable_joystick = xyes -a x$enable_hidapi = xyes; then
+        if test x$skiplibusb = xyes; then
+            hidapi_support=yes
+        else
 
 
 pkg_failed=no
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB" >&5
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUSB" >&5
@@ -24147,28 +24308,73 @@ else
 $as_echo "yes" >&6; }
 $as_echo "yes" >&6; }
 	have_libusb=yes
 	have_libusb=yes
 fi
 fi
-        hidapi_support=no
-        save_CFLAGS="$CFLAGS"
-        CFLAGS="$save_CFLAGS $LIBUSB_CFLAGS"
-        ac_fn_c_check_header_mongrel "$LINENO" "libusb.h" "ac_cv_header_libusb_h" "$ac_includes_default"
+            save_CFLAGS="$CFLAGS"
+            CFLAGS="$save_CFLAGS $LIBUSB_CFLAGS"
+            ac_fn_c_check_header_mongrel "$LINENO" "libusb.h" "ac_cv_header_libusb_h" "$ac_includes_default"
 if test "x$ac_cv_header_libusb_h" = xyes; then :
 if test "x$ac_cv_header_libusb_h" = xyes; then :
   have_libusb_h=yes
   have_libusb_h=yes
 fi
 fi
 
 
 
 
-        CFLAGS="$save_CFLAGS"
+            CFLAGS="$save_CFLAGS"
+            if test x$have_libusb_h = xyes; then
+                hidapi_support=yes
+            elif test x$onlylibusb = xyes; then
+                hidapi_support=no
+            else
+                hidapi_support=yes
+            fi
+        fi
 
 
-        if test x$have_libusb_h = xyes; then
-            hidapi_support=yes
+        if test x$hidapi_support = xyes; then
 
 
 $as_echo "#define SDL_JOYSTICK_HIDAPI 1" >>confdefs.h
 $as_echo "#define SDL_JOYSTICK_HIDAPI 1" >>confdefs.h
 
 
             EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
             SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
-            SOURCES="$SOURCES $srcdir/src/hidapi/libusb/hid.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBUSB_CFLAGS"
-            EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBUSB_LIBS"
+
+            if test x$have_libusb_h = xyes; then
+                EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBUSB_CFLAGS"
+                if test x$onlylibusb = xyes; then
+                    SOURCES="$SOURCES $srcdir/src/hidapi/libusb/hid.c"
+                    EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBUSB_LIBS"
+                else
+                    if test x$have_loadso != xyes; then
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You must have SDL_LoadObject() support for dynamic libusb loading" >&5
+$as_echo "$as_me: WARNING: You must have SDL_LoadObject() support for dynamic libusb loading" >&2;}
+                    fi
+                    SOURCES="$SOURCES $srcdir/src/hidapi/SDL_hidapi.c"
+                    # libusb is loaded dynamically, so don't add it to LDFLAGS
+                    libusb_lib=""
+                    case "$host" in
+                        *-*-darwin* )
+                            libusb_lib="libusb-1.0.0.dylib"
+                            ;;
+                        *-*-cygwin* | *-*-mingw32* )
+                            libusb_lib="libusb-1.0.dll"
+                            ;;
+                    esac
+                    if test x$libusb_lib = x; then
+                        libusb_lib=`find_lib "libusb-1.0.so.*" "" | sed 's/.*\/\(.*\)/\1/; q'`
+                    fi
+
+cat >>confdefs.h <<_ACEOF
+#define SDL_LIBUSB_DYNAMIC "$libusb_lib"
+_ACEOF
+
+                fi
+            else
+                case "$host" in
+                *-*-cygwin* | *-*-mingw32* )
+                    SOURCES="$SOURCES $srcdir/src/hidapi/windows/hid.c"
+                    ;;
+                *-*-darwin* )
+                    SOURCES="$SOURCES $srcdir/src/hidapi/mac/hid.c"
+                    ;;
+                esac
+            fi
         fi
         fi
+
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hidapi support" >&5
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hidapi support" >&5
 $as_echo_n "checking for hidapi support... " >&6; }
 $as_echo_n "checking for hidapi support... " >&6; }
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hidapi_support" >&5
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hidapi_support" >&5
@@ -24334,6 +24540,7 @@ fi
 
 
 
 
 CheckWarnAll
 CheckWarnAll
+CheckNoStrictAliasing
 
 
 CheckEventSignals
 CheckEventSignals
 
 
@@ -24383,6 +24590,8 @@ case "$host" in
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
         CheckDLOPEN
         CheckDLOPEN
+        CheckARM
+        CheckNEON
         CheckOSS
         CheckOSS
         CheckALSA
         CheckALSA
         CheckPulseAudio
         CheckPulseAudio
@@ -24402,6 +24611,7 @@ case "$host" in
         CheckOpenGLESX11
         CheckOpenGLESX11
         CheckVulkan
         CheckVulkan
         CheckWayland
         CheckWayland
+        CheckInputEvents
         CheckLibUDev
         CheckLibUDev
         CheckDBus
         CheckDBus
         CheckIME
         CheckIME
@@ -24409,7 +24619,6 @@ case "$host" in
         CheckFcitx
         CheckFcitx
         case $ARCH in
         case $ARCH in
           linux)
           linux)
-              CheckInputEvents
               CheckInputKD
               CheckInputKD
           ;;
           ;;
         esac
         esac
@@ -24594,6 +24803,7 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
         CheckWINDOWSGLES
         CheckWINDOWSGLES
         CheckVulkan
         CheckVulkan
         CheckDIRECTX
         CheckDIRECTX
+        CheckHIDAPI
 
 
         # Set up the core platform files
         # Set up the core platform files
         SOURCES="$SOURCES $srcdir/src/core/windows/*.c"
         SOURCES="$SOURCES $srcdir/src/core/windows/*.c"
@@ -24667,13 +24877,7 @@ $as_echo "#define SDL_JOYSTICK_DINPUT 1" >>confdefs.h
 $as_echo "#define SDL_JOYSTICK_WINMM 1" >>confdefs.h
 $as_echo "#define SDL_JOYSTICK_WINMM 1" >>confdefs.h
 
 
             fi
             fi
-
-$as_echo "#define SDL_JOYSTICK_HIDAPI 1" >>confdefs.h
-
             SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
             SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
-            SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
-            SOURCES="$SOURCES $srcdir/src/hidapi/windows/hid.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             have_joystick=yes
             have_joystick=yes
         fi
         fi
         if test x$enable_haptic = xyes; then
         if test x$enable_haptic = xyes; then
@@ -24970,7 +25174,7 @@ $as_echo "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
 
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Metal"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Metal"
         fi
         fi
         ;;
         ;;
@@ -24998,6 +25202,7 @@ $as_echo "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
         CheckOpenGLX11
         CheckOpenGLX11
         CheckVulkan
         CheckVulkan
         CheckPTHREAD
         CheckPTHREAD
+        CheckHIDAPI
 
 
         # 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
@@ -25014,13 +25219,7 @@ $as_echo "#define SDL_AUDIO_DRIVER_COREAUDIO 1" >>confdefs.h
 
 
 $as_echo "#define SDL_JOYSTICK_IOKIT 1" >>confdefs.h
 $as_echo "#define SDL_JOYSTICK_IOKIT 1" >>confdefs.h
 
 
-
-$as_echo "#define SDL_JOYSTICK_HIDAPI 1" >>confdefs.h
-
             SOURCES="$SOURCES $srcdir/src/joystick/darwin/*.c"
             SOURCES="$SOURCES $srcdir/src/joystick/darwin/*.c"
-            SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
-            SOURCES="$SOURCES $srcdir/src/hidapi/mac/hid.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             have_joystick=yes
             have_joystick=yes
         fi
         fi
         # Set up files for the haptic library
         # Set up files for the haptic library
@@ -25069,7 +25268,7 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
 
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal"
         fi
         fi
         ;;
         ;;
@@ -25458,6 +25657,23 @@ if test x$have_fcitx_frontend_h_hdr = xyes; then
 else
 else
     SUMMARY="${SUMMARY}Using fcitx         : NO\n"
     SUMMARY="${SUMMARY}Using fcitx         : NO\n"
 fi
 fi
+
+if test x$WARN_ABOUT_ARM_SIMD_ASM_MIT = xyes; then
+    SUMMARY="${SUMMARY}\nSDL is being built with ARM SIMD optimizations, which\n"
+    SUMMARY="${SUMMARY}uses code licensed under the MIT license. If this is a\n"
+    SUMMARY="${SUMMARY}problem, please disable that code by rerunning the\n"
+    SUMMARY="${SUMMARY}configure script with:\n"
+    SUMMARY="${SUMMARY}\n    --disable-arm-simd\n"
+fi
+
+if test x$WARN_ABOUT_ARM_NEON_ASM_MIT = xyes; then
+    SUMMARY="${SUMMARY}\nSDL is being built with ARM NEON optimizations, which\n"
+    SUMMARY="${SUMMARY}uses code licensed under the MIT license. If this is a\n"
+    SUMMARY="${SUMMARY}problem, please disable that code by rerunning the\n"
+    SUMMARY="${SUMMARY}configure script with:\n"
+    SUMMARY="${SUMMARY}\n    --disable-arm-neon\n"
+fi
+
 ac_config_commands="$ac_config_commands summary"
 ac_config_commands="$ac_config_commands summary"
 
 
 
 

+ 220 - 49
sdl.mod/SDL/configure.ac

@@ -20,9 +20,9 @@ dnl Set various version strings - taken gratefully from the GTk sources
 #
 #
 SDL_MAJOR_VERSION=2
 SDL_MAJOR_VERSION=2
 SDL_MINOR_VERSION=0
 SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=9
+SDL_MICRO_VERSION=11
 SDL_INTERFACE_AGE=0
 SDL_INTERFACE_AGE=0
-SDL_BINARY_AGE=9
+SDL_BINARY_AGE=11
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 
 AC_SUBST(SDL_MAJOR_VERSION)
 AC_SUBST(SDL_MAJOR_VERSION)
@@ -1303,6 +1303,82 @@ AS_HELP_STRING([--enable-libsamplerate-shared], [dynamically load libsamplerate
     fi
     fi
 }
 }
 
 
+dnl Check for ARM instruction support using gas syntax
+CheckARM()
+{
+    AC_ARG_ENABLE(arm-simd,
+AC_HELP_STRING([--enable-arm-simd], [use SIMD assembly blitters on ARM [[default=yes]]]),
+                  enable_arm_simd=$enableval, enable_arm_simd=yes)
+    if test x$enable_video = xyes -a x$enable_assembly = xyes -a x$enable_arm_simd = xyes; then
+        save_CFLAGS="$CFLAGS"
+        have_arm_simd=no
+        CFLAGS="-x assembler-with-cpp $CFLAGS"
+        
+        AC_MSG_CHECKING(for ARM SIMD)
+        AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+        .text
+        .arch armv6
+        .object_arch armv4
+        .arm
+        .altmacro
+        #ifndef __ARM_EABI__
+        #error EABI is required (to be sure that calling conventions are compatible)
+        #endif
+        pld [r0]
+        uqadd8 r0, r0, r0
+        ]])], have_arm_simd=yes)
+        AC_MSG_RESULT($have_arm_simd)
+        
+        CFLAGS="$save_CFLAGS"
+        
+        if test x$have_arm_simd = xyes; then
+            AC_DEFINE(SDL_ARM_SIMD_BLITTERS)
+dnl            SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-simd*.c"
+            SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-simd*.S"
+            WARN_ABOUT_ARM_SIMD_ASM_MIT="yes"
+        fi
+    fi
+}
+
+dnl Check for ARM NEON instruction support using gas syntax
+CheckNEON()
+{
+    AC_ARG_ENABLE(arm-neon,
+AC_HELP_STRING([--enable-arm-neon], [use NEON assembly blitters on ARM [[default=yes]]]),
+                  enable_arm_neon=$enableval, enable_arm_neon=yes)
+    if test x$enable_video = xyes -a x$enable_assembly = xyes -a x$enable_arm_neon = xyes; then
+        save_CFLAGS="$CFLAGS"
+        have_arm_neon=no
+        CFLAGS="-x assembler-with-cpp $CFLAGS"
+        
+        AC_MSG_CHECKING(for ARM NEON)
+        AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+        .text
+        .fpu neon
+        .arch armv7a
+        .object_arch armv4
+        .eabi_attribute 10, 0
+        .arm
+        .altmacro
+        #ifndef __ARM_EABI__
+        #error EABI is required (to be sure that calling conventions are compatible)
+        #endif
+        pld [r0]
+        vmovn.u16 d0, q0
+        ]])], have_arm_neon=yes)
+        AC_MSG_RESULT($have_arm_neon)
+        
+        CFLAGS="$save_CFLAGS"
+        
+        if test x$have_arm_neon = xyes; then
+            AC_DEFINE(SDL_ARM_NEON_BLITTERS)
+dnl            SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-neon*.c"
+            SOURCES="$SOURCES $srcdir/src/video/arm/pixman-arm-neon*.S"
+            WARN_ABOUT_ARM_NEON_ASM_MIT="yes"
+        fi
+    fi
+}
+
 dnl See if GCC's -fvisibility=hidden is supported (gcc4 and later, usually).
 dnl See if GCC's -fvisibility=hidden is supported (gcc4 and later, usually).
 dnl  Details of this flag are here: http://gcc.gnu.org/wiki/Visibility
 dnl  Details of this flag are here: http://gcc.gnu.org/wiki/Visibility
 CheckVisibilityHidden()
 CheckVisibilityHidden()
@@ -1329,6 +1405,29 @@ CheckVisibilityHidden()
     fi
     fi
 }
 }
 
 
+dnl See if GCC's -fno-strict-aliasingis supported.
+dnl  Reference: https://bugzilla.libsdl.org/show_bug.cgi?id=4254
+CheckNoStrictAliasing()
+{
+    AC_MSG_CHECKING(for GCC -fno-strict-aliasing option)
+    have_gcc_no_strict_aliasing=no
+
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$save_CFLAGS -fno-strict-aliasing"
+    AC_TRY_COMPILE([
+    int x = 0;
+    ],[
+    ],[
+    have_gcc_no_strict_aliasing=yes
+    ])
+    AC_MSG_RESULT($have_gcc_no_strict_aliasing)
+    CFLAGS="$save_CFLAGS"
+
+    if test x$have_gcc_no_strict_aliasing = xyes; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -fno-strict-aliasing"
+    fi
+}
+
 dnl See if GCC's -mpreferred-stack-boundary is supported.
 dnl See if GCC's -mpreferred-stack-boundary is supported.
 dnl  Reference: http://bugzilla.libsdl.org/show_bug.cgi?id=1296
 dnl  Reference: http://bugzilla.libsdl.org/show_bug.cgi?id=1296
 CheckStackBoundary()
 CheckStackBoundary()
@@ -1527,8 +1626,8 @@ CheckNativeClient()
 CheckRPI()
 CheckRPI()
 {
 {
     AC_ARG_ENABLE(video-rpi,
     AC_ARG_ENABLE(video-rpi,
-AS_HELP_STRING([--enable-video-rpi], [use Raspberry Pi video driver [[default=no]]]),
-                  , enable_video_rpi=no)
+AS_HELP_STRING([--enable-video-rpi], [use Raspberry Pi video driver [[default=yes]]]),
+                  , enable_video_rpi=yes)
     if test x$enable_video = xyes -a x$enable_video_rpi = xyes; then
     if test x$enable_video = xyes -a x$enable_video_rpi = xyes; then
         PKG_CHECK_MODULES([RPI], [bcm_host brcmegl], video_rpi=yes, video_rpi=no)
         PKG_CHECK_MODULES([RPI], [bcm_host brcmegl], video_rpi=yes, video_rpi=no)
 
 
@@ -1587,10 +1686,10 @@ AS_HELP_STRING([--enable-video-x11], [use X11 video driver [[default=yes]]]),
                 # This isn't necessary for X11, but fixes GLX detection
                 # This isn't necessary for X11, but fixes GLX detection
                 if test "x$x_includes" = xNONE && \
                 if test "x$x_includes" = xNONE && \
                    test "x$x_libraries" = xNONE && \
                    test "x$x_libraries" = xNONE && \
-                   test -d /usr/X11R6/include && \
-                   test -d /usr/X11R6/lib; then
-                    x_includes="/usr/X11R6/include"
-                    x_libraries="/usr/X11R6/lib"
+                   test -d /opt/X11/include && \
+                   test -d /opt/X11/lib; then
+                    x_includes="/opt/X11/include"
+                    x_libraries="/opt/X11/lib"
                 fi
                 fi
                 ;;
                 ;;
         esac
         esac
@@ -1603,15 +1702,16 @@ AS_HELP_STRING([--enable-x11-shared], [dynamically load X11 support [[default=ma
 
 
             case "$host" in
             case "$host" in
                 *-*-darwin*)
                 *-*-darwin*)
-                    x11_lib='/usr/X11R6/lib/libX11.6.dylib'
-                    x11ext_lib='/usr/X11R6/lib/libXext.6.dylib'
-                    xcursor_lib='/usr/X11R6/lib/libXcursor.1.dylib'
-                    xinerama_lib='/usr/X11R6/lib/libXinerama.1.dylib'
-                    xinput_lib='/usr/X11R6/lib/libXi.6.dylib'
-                    xrandr_lib='/usr/X11R6/lib/libXrandr.2.dylib'
-                    xrender_lib='/usr/X11R6/lib/libXrender.1.dylib'
-                    xss_lib='/usr/X11R6/lib/libXss.1.dylib'
-                    xvidmode_lib='/usr/X11R6/lib/libXxf86vm.1.dylib'
+                    # Apple now puts this in /opt/X11
+                    x11_lib='/opt/X11/lib/libX11.6.dylib'
+                    x11ext_lib='/opt/X11/lib/libXext.6.dylib'
+                    xcursor_lib='/opt/X11/lib/libXcursor.1.dylib'
+                    xinerama_lib='/opt/X11/lib/libXinerama.1.dylib'
+                    xinput_lib='/opt/X11/lib/libXi.6.dylib'
+                    xrandr_lib='/opt/X11/lib/libXrandr.2.dylib'
+                    xrender_lib='/opt/X11/lib/libXrender.1.dylib'
+                    xss_lib='/opt/X11/lib/libXss.1.dylib'
+                    xvidmode_lib='/opt/X11/lib/libXxf86vm.1.dylib'
                     ;;
                     ;;
                 *-*-openbsd*)
                 *-*-openbsd*)
                     x11_lib='libX11.so'
                     x11_lib='libX11.so'
@@ -2025,10 +2125,13 @@ AS_HELP_STRING([--enable-video-cocoa], [use Cocoa video driver [[default=yes]]])
 
 
 CheckMETAL()
 CheckMETAL()
 {
 {
+    AC_ARG_ENABLE(video-metal,
+AC_HELP_STRING([--enable-video-metal], [include Metal support [[default=yes]]]),
+              , enable_video_metal=yes)
     AC_ARG_ENABLE(render-metal,
     AC_ARG_ENABLE(render-metal,
 AS_HELP_STRING([--enable-render-metal], [enable the Metal render driver [[default=yes]]]),
 AS_HELP_STRING([--enable-render-metal], [enable the Metal render driver [[default=yes]]]),
                                 , enable_render_metal=yes)
                                 , enable_render_metal=yes)
-    if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+    if test x$enable_video = xyes -a x$enable_video_metal = xyes; then
         save_CFLAGS="$CFLAGS"
         save_CFLAGS="$CFLAGS"
         dnl Work around that we don't have Objective-C support in autoconf
         dnl Work around that we don't have Objective-C support in autoconf
         CFLAGS="$CFLAGS -x objective-c"
         CFLAGS="$CFLAGS -x objective-c"
@@ -2049,10 +2152,14 @@ AS_HELP_STRING([--enable-render-metal], [enable the Metal render driver [[defaul
         CFLAGS="$save_CFLAGS"
         CFLAGS="$save_CFLAGS"
         AC_MSG_RESULT($have_metal)
         AC_MSG_RESULT($have_metal)
         if test x$have_metal = xyes; then
         if test x$have_metal = xyes; then
-            AC_DEFINE(SDL_VIDEO_RENDER_METAL, 1, [ ])
-            SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+            AC_DEFINE(SDL_VIDEO_METAL, 1, [ ])
+            if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+                AC_DEFINE(SDL_VIDEO_RENDER_METAL, 1, [ ])
+                SOURCES="$SOURCES $srcdir/src/render/metal/*.m"
+            fi
             SUMMARY_video="${SUMMARY_video} metal"
             SUMMARY_video="${SUMMARY_video} metal"
         else
         else
+            enable_video_metal=no
             enable_render_metal=no
             enable_render_metal=no
         fi
         fi
     fi
     fi
@@ -2261,7 +2368,7 @@ CheckOpenGLESX11()
         if test x$video_opengl_egl = xyes; then
         if test x$video_opengl_egl = xyes; then
             AC_DEFINE(SDL_VIDEO_OPENGL_EGL, 1, [ ])
             AC_DEFINE(SDL_VIDEO_OPENGL_EGL, 1, [ ])
         fi
         fi
-            
+        
         if test x$enable_video_opengles1 = xyes; then
         if test x$enable_video_opengles1 = xyes; then
             AC_MSG_CHECKING(for OpenGL ES v1 headers)
             AC_MSG_CHECKING(for OpenGL ES v1 headers)
             video_opengles_v1=no
             video_opengles_v1=no
@@ -2572,7 +2679,7 @@ AS_HELP_STRING([--enable-ime], [enable IME support [[default=yes]]]),
                   , enable_ime=yes)
                   , enable_ime=yes)
     if test x$enable_ime = xyes; then
     if test x$enable_ime = xyes; then
         AC_DEFINE(SDL_USE_IME, 1, [ ])
         AC_DEFINE(SDL_USE_IME, 1, [ ])
-            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
+        SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
     fi
     fi
 }
 }
 
 
@@ -2991,8 +3098,6 @@ XINPUT_STATE_EX s1;
         AC_DEFINE(HAVE_AUDIOCLIENT_H,1,[])
         AC_DEFINE(HAVE_AUDIOCLIENT_H,1,[])
     fi
     fi
 
 
-    AC_CHECK_HEADER(endpointvolume.h,AC_DEFINE(HAVE_ENDPOINTVOLUME_H,1,[]))
-
     AC_ARG_ENABLE(wasapi,
     AC_ARG_ENABLE(wasapi,
 AS_HELP_STRING([--enable-wasapi], [use the Windows WASAPI audio driver [[default=yes]]]),
 AS_HELP_STRING([--enable-wasapi], [use the Windows WASAPI audio driver [[default=yes]]]),
                                 , enable_wasapi=yes)
                                 , enable_wasapi=yes)
@@ -3044,7 +3149,7 @@ CheckUSBHID()
                     AC_CHECK_HEADER(libusb.h, [USB_CFLAGS="-DHAVE_LIBUSB_H"])
                     AC_CHECK_HEADER(libusb.h, [USB_CFLAGS="-DHAVE_LIBUSB_H"])
                     AC_CHECK_LIB(usb, hid_init, [USB_LIBS="$USB_LIBS -lusb"])
                     AC_CHECK_LIB(usb, hid_init, [USB_LIBS="$USB_LIBS -lusb"])
                 fi
                 fi
-                    
+                
                 save_CFLAGS="$CFLAGS"
                 save_CFLAGS="$CFLAGS"
                 CFLAGS="$CFLAGS $USB_CFLAGS"
                 CFLAGS="$CFLAGS $USB_CFLAGS"
 
 
@@ -3174,28 +3279,80 @@ CheckHIDAPI()
 {
 {
     # The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers,
     # The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers,
     # so we'll just use libusb when it's available.
     # so we'll just use libusb when it's available.
-    #
-    # Except that libusb requires root permissions to open devices, so that's not generally useful, and we'll disable this by default.
+    case "$host" in
+        # libusb does not support iOS
+        arm*-apple-darwin* | *-ios-* )
+            skiplibusb=yes
+            ;;
+        # On the other hand, *BSD specifically uses libusb only
+        *-*-*bsd* )
+            onlylibusb=yes
+            ;;
+    esac
+
     AC_ARG_ENABLE(hidapi,
     AC_ARG_ENABLE(hidapi,
 AS_HELP_STRING([--enable-hidapi], [use HIDAPI for low level joystick drivers [[default=no]]]),
 AS_HELP_STRING([--enable-hidapi], [use HIDAPI for low level joystick drivers [[default=no]]]),
                   , enable_hidapi=no)
                   , enable_hidapi=no)
     if test x$enable_joystick = xyes -a x$enable_hidapi = xyes; then
     if test x$enable_joystick = xyes -a x$enable_hidapi = xyes; then
-        PKG_CHECK_MODULES([LIBUSB], [libusb-1.0], have_libusb=yes, have_libusb=no)
-        hidapi_support=no
-        save_CFLAGS="$CFLAGS"
-        CFLAGS="$save_CFLAGS $LIBUSB_CFLAGS"
-        AC_CHECK_HEADER(libusb.h, have_libusb_h=yes)
-        CFLAGS="$save_CFLAGS"
-
-        if test x$have_libusb_h = xyes; then
+        if test x$skiplibusb = xyes; then
             hidapi_support=yes
             hidapi_support=yes
+        else
+            PKG_CHECK_MODULES([LIBUSB], [libusb-1.0], have_libusb=yes, have_libusb=no)
+            save_CFLAGS="$CFLAGS"
+            CFLAGS="$save_CFLAGS $LIBUSB_CFLAGS"
+            AC_CHECK_HEADER(libusb.h, have_libusb_h=yes)
+            CFLAGS="$save_CFLAGS"
+            if test x$have_libusb_h = xyes; then
+                hidapi_support=yes
+            elif test x$onlylibusb = xyes; then
+                hidapi_support=no
+            else
+                hidapi_support=yes
+            fi
+        fi
+
+        if test x$hidapi_support = xyes; then
             AC_DEFINE(SDL_JOYSTICK_HIDAPI, 1, [ ])
             AC_DEFINE(SDL_JOYSTICK_HIDAPI, 1, [ ])
             EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
             SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
-            SOURCES="$SOURCES $srcdir/src/hidapi/libusb/hid.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBUSB_CFLAGS"
-            EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBUSB_LIBS"
+
+            if test x$have_libusb_h = xyes; then
+                EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBUSB_CFLAGS"
+                if test x$onlylibusb = xyes; then
+                    SOURCES="$SOURCES $srcdir/src/hidapi/libusb/hid.c"
+                    EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBUSB_LIBS"
+                else
+                    if test x$have_loadso != xyes; then
+                        AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic libusb loading])
+                    fi
+                    SOURCES="$SOURCES $srcdir/src/hidapi/SDL_hidapi.c"
+                    # libusb is loaded dynamically, so don't add it to LDFLAGS
+                    libusb_lib=""
+                    case "$host" in
+                        *-*-darwin* )
+                            libusb_lib="libusb-1.0.0.dylib"
+                            ;;
+                        *-*-cygwin* | *-*-mingw32* )
+                            libusb_lib="libusb-1.0.dll"
+                            ;;
+                    esac
+                    if test x$libusb_lib = x; then
+                        libusb_lib=[`find_lib "libusb-1.0.so.*" "" | sed 's/.*\/\(.*\)/\1/; q'`]
+                    fi
+                    AC_DEFINE_UNQUOTED(SDL_LIBUSB_DYNAMIC, "$libusb_lib", [ ])
+                fi
+            else
+                case "$host" in
+                *-*-cygwin* | *-*-mingw32* )
+                    SOURCES="$SOURCES $srcdir/src/hidapi/windows/hid.c"
+                    ;;
+                *-*-darwin* )
+                    SOURCES="$SOURCES $srcdir/src/hidapi/mac/hid.c"
+                    ;;
+                esac
+            fi
         fi
         fi
+
         AC_MSG_CHECKING(for hidapi support)
         AC_MSG_CHECKING(for hidapi support)
         AC_MSG_RESULT($hidapi_support)
         AC_MSG_RESULT($hidapi_support)
     fi
     fi
@@ -3263,6 +3420,7 @@ AS_HELP_STRING([--enable-foregrounding-signal], [number to use for magic foregro
 
 
 dnl Do this on all platforms, before everything else (other things might want to override it).
 dnl Do this on all platforms, before everything else (other things might want to override it).
 CheckWarnAll
 CheckWarnAll
+CheckNoStrictAliasing
 
 
 dnl Do this for every platform, but for some it doesn't mean anything, but better to catch it here anyhow.
 dnl Do this for every platform, but for some it doesn't mean anything, but better to catch it here anyhow.
 CheckEventSignals
 CheckEventSignals
@@ -3314,6 +3472,8 @@ case "$host" in
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
         CheckDLOPEN
         CheckDLOPEN
+        CheckARM
+        CheckNEON
         CheckOSS
         CheckOSS
         CheckALSA
         CheckALSA
         CheckPulseAudio
         CheckPulseAudio
@@ -3333,6 +3493,7 @@ case "$host" in
         CheckOpenGLESX11
         CheckOpenGLESX11
         CheckVulkan
         CheckVulkan
         CheckWayland
         CheckWayland
+        CheckInputEvents
         CheckLibUDev
         CheckLibUDev
         CheckDBus
         CheckDBus
         CheckIME
         CheckIME
@@ -3340,7 +3501,6 @@ case "$host" in
         CheckFcitx
         CheckFcitx
         case $ARCH in
         case $ARCH in
           linux)
           linux)
-              CheckInputEvents
               CheckInputKD
               CheckInputKD
           ;;
           ;;
         esac
         esac
@@ -3497,6 +3657,7 @@ case "$host" in
         CheckWINDOWSGLES
         CheckWINDOWSGLES
         CheckVulkan
         CheckVulkan
         CheckDIRECTX
         CheckDIRECTX
+        CheckHIDAPI
 
 
         # Set up the core platform files
         # Set up the core platform files
         SOURCES="$SOURCES $srcdir/src/core/windows/*.c"
         SOURCES="$SOURCES $srcdir/src/core/windows/*.c"
@@ -3548,11 +3709,7 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
             else
             else
                 AC_DEFINE(SDL_JOYSTICK_WINMM, 1, [ ])
                 AC_DEFINE(SDL_JOYSTICK_WINMM, 1, [ ])
             fi
             fi
-            AC_DEFINE(SDL_JOYSTICK_HIDAPI, 1, [ ])
             SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
             SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
-            SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
-            SOURCES="$SOURCES $srcdir/src/hidapi/windows/hid.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             have_joystick=yes
             have_joystick=yes
         fi
         fi
         if test x$enable_haptic = xyes; then
         if test x$enable_haptic = xyes; then
@@ -3751,7 +3908,7 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
 
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Metal"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Metal"
         fi
         fi
         ;;
         ;;
@@ -3779,6 +3936,7 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         CheckOpenGLX11
         CheckOpenGLX11
         CheckVulkan
         CheckVulkan
         CheckPTHREAD
         CheckPTHREAD
+        CheckHIDAPI
 
 
         # 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
@@ -3791,11 +3949,7 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         # Set up files for the joystick library
         # Set up files for the joystick library
         if test x$enable_joystick = xyes; then
         if test x$enable_joystick = xyes; then
             AC_DEFINE(SDL_JOYSTICK_IOKIT, 1, [ ])
             AC_DEFINE(SDL_JOYSTICK_IOKIT, 1, [ ])
-            AC_DEFINE(SDL_JOYSTICK_HIDAPI, 1, [ ])
             SOURCES="$SOURCES $srcdir/src/joystick/darwin/*.c"
             SOURCES="$SOURCES $srcdir/src/joystick/darwin/*.c"
-            SOURCES="$SOURCES $srcdir/src/joystick/hidapi/*.c"
-            SOURCES="$SOURCES $srcdir/src/hidapi/mac/hid.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS -I$srcdir/src/hidapi/hidapi"
             have_joystick=yes
             have_joystick=yes
         fi
         fi
         # Set up files for the haptic library
         # Set up files for the haptic library
@@ -3836,7 +3990,7 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
 
 
-        if test x$enable_render = xyes -a x$enable_render_metal = xyes; then
+        if test x$enable_video_metal = xyes -o x$enable_video_vulkan = xyes; then
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal"
         fi
         fi
         ;;
         ;;
@@ -4172,6 +4326,23 @@ if test x$have_fcitx_frontend_h_hdr = xyes; then
 else
 else
     SUMMARY="${SUMMARY}Using fcitx         : NO\n"
     SUMMARY="${SUMMARY}Using fcitx         : NO\n"
 fi
 fi
+
+if test x$WARN_ABOUT_ARM_SIMD_ASM_MIT = xyes; then
+    SUMMARY="${SUMMARY}\nSDL is being built with ARM SIMD optimizations, which\n"
+    SUMMARY="${SUMMARY}uses code licensed under the MIT license. If this is a\n"
+    SUMMARY="${SUMMARY}problem, please disable that code by rerunning the\n"
+    SUMMARY="${SUMMARY}configure script with:\n"
+    SUMMARY="${SUMMARY}\n    --disable-arm-simd\n"
+fi
+
+if test x$WARN_ABOUT_ARM_NEON_ASM_MIT = xyes; then
+    SUMMARY="${SUMMARY}\nSDL is being built with ARM NEON optimizations, which\n"
+    SUMMARY="${SUMMARY}uses code licensed under the MIT license. If this is a\n"
+    SUMMARY="${SUMMARY}problem, please disable that code by rerunning the\n"
+    SUMMARY="${SUMMARY}configure script with:\n"
+    SUMMARY="${SUMMARY}\n    --disable-arm-neon\n"
+fi
+
 AC_CONFIG_COMMANDS([summary], [echo -en "$SUMMARY"], [SUMMARY="$SUMMARY"])
 AC_CONFIG_COMMANDS([summary], [echo -en "$SUMMARY"], [SUMMARY="$SUMMARY"])
 
 
 AC_OUTPUT
 AC_OUTPUT

+ 12 - 0
sdl.mod/SDL/debian/changelog

@@ -1,3 +1,15 @@
+libsdl2 (2.0.11) UNRELEASED; urgency=low
+
+  * Updated SDL to version 2.0.11 for development builds
+
+ -- Sam Lantinga <[email protected]>  Sun, 22 Sep 2019 10:33:03 -0800
+
+libsdl2 (2.0.10) UNRELEASED; urgency=low
+
+  * Updated SDL to version 2.0.10
+
+ -- Sam Lantinga <[email protected]>  Mon, 17 Jun 2019 08:48:47 -0800
+
 libsdl2 (2.0.9) UNRELEASED; urgency=low
 libsdl2 (2.0.9) UNRELEASED; urgency=low
 
 
   * Updated SDL to version 2.0.9
   * Updated SDL to version 2.0.9

+ 19 - 0
sdl.mod/SDL/docs/README-android.md

@@ -82,6 +82,23 @@ For more complex projects, follow these instructions:
 
 
 4b. If you want to build manually, run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device
 4b. If you want to build manually, run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device
 
 
+
+If you already have a project that uses CMake, the instructions change somewhat:
+
+1. Do points 1 and 2 from the instruction above.
+2. Edit "<project>/app/build.gradle" to comment out or remove sections containing ndk-build
+   and uncomment the cmake sections. Add arguments to the CMake invocation as needed.
+3. Edit "<project>/app/jni/CMakeLists.txt" to include your project (it defaults to
+   adding the "src" subdirectory). Note that you'll have SDL2, SDL2main and SDL2-static
+   as targets in your project, so you should have "target_link_libraries(yourgame SDL2 SDL2main)"
+   in your CMakeLists.txt file. Also be aware that you should use add_library() instead of
+   add_executable() for the target containing your "main" function.
+
+If you wish to use Android Studio, you can skip the last step.
+
+4. Run './gradlew installDebug' or './gradlew installRelease' in the project directory. It will build and install your .apk on any
+   connected Android device
+
 Here's an explanation of the files in the Android project, so you can customize them:
 Here's an explanation of the files in the Android project, so you can customize them:
 
 
     android-project/app
     android-project/app
@@ -90,10 +107,12 @@ Here's an explanation of the files in the Android project, so you can customize
         jni/			- directory holding native code
         jni/			- directory holding native code
         jni/Application.mk	- Application JNI settings, including target platform and STL library
         jni/Application.mk	- Application JNI settings, including target platform and STL library
         jni/Android.mk		- Android makefile that can call recursively the Android.mk files in all subdirectories
         jni/Android.mk		- Android makefile that can call recursively the Android.mk files in all subdirectories
+        jni/CMakeLists.txt	- Top-level CMake project that adds SDL as a subproject
         jni/SDL/		- (symlink to) directory holding the SDL library files
         jni/SDL/		- (symlink to) directory holding the SDL library files
         jni/SDL/Android.mk	- Android makefile for creating the SDL shared library
         jni/SDL/Android.mk	- Android makefile for creating the SDL shared library
         jni/src/		- directory holding your C/C++ source
         jni/src/		- directory holding your C/C++ source
         jni/src/Android.mk	- Android makefile that you should customize to include your source code and any library references
         jni/src/Android.mk	- Android makefile that you should customize to include your source code and any library references
+        jni/src/CMakeLists.txt	- CMake file that you may customize to include your source code and any library references
         src/main/assets/	- directory holding asset files for your application
         src/main/assets/	- directory holding asset files for your application
         src/main/res/		- directory holding resources for your application
         src/main/res/		- directory holding resources for your application
         src/main/res/mipmap-*	- directories holding icons for different phone hardware
         src/main/res/mipmap-*	- directories holding icons for different phone hardware

+ 53 - 1
sdl.mod/SDL/docs/README-cmake.md

@@ -15,7 +15,7 @@ platforms:
 * Linux
 * Linux
 * VS.NET 2010
 * VS.NET 2010
 * MinGW and Msys
 * MinGW and Msys
-* OS X with support for XCode
+* macOS, iOS, and tvOS, with support for XCode
 
 
 
 
 ================================================================================
 ================================================================================
@@ -30,3 +30,55 @@ Assuming the source for SDL is located at ~/sdl
     cmake ../sdl
     cmake ../sdl
 
 
 This will build the static and dynamic versions of SDL in the ~/build directory.
 This will build the static and dynamic versions of SDL in the ~/build directory.
+
+
+================================================================================
+Usage, iOS/tvOS
+================================================================================
+
+CMake 3.14+ natively includes support for iOS and tvOS.  SDL binaries may be built
+using Xcode or Make, possibly among other build-systems.
+
+When using a recent version of CMake (3.14+), it should be possible to:
+
+- build SDL for iOS, both static and dynamic
+- build SDL test apps (as iOS/tvOS .app bundles)
+- generate a working SDL_config.h for iOS (using SDL_config.h.cmake as a basis)
+
+To use, set the following CMake variables when running CMake's configuration stage:
+
+- `CMAKE_SYSTEM_NAME=<OS>`   (either `iOS` or `tvOS`)
+- `CMAKE_OSX_SYSROOT=<SDK>`  (examples: `iphoneos`, `iphonesimulator`, `iphoneos12.4`, `/full/path/to/iPhoneOS.sdk`,
+                              `appletvos`, `appletvsimulator`, `appletvos12.4`, `/full/path/to/AppleTVOS.sdk`, etc.)
+- `CMAKE_OSX_ARCHITECTURES=<semicolon-separated list of CPU architectures>` (example: "arm64;armv7s;x86_64")
+
+
+### Examples (for iOS/tvOS):
+
+- for iOS-Simulator, using the latest, installed SDK:
+
+    `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64`
+
+- for iOS-Device, using the latest, installed SDK, 64-bit only
+
+    `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES=arm64`
+
+- for iOS-Device, using the latest, installed SDK, mixed 32/64 bit
+
+    `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES="arm64;armv7s"`
+
+- for iOS-Device, using a specific SDK revision (iOS 12.4, in this example):
+
+    `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos12.4 -DCMAKE_OSX_ARCHITECTURES=arm64`
+
+- for iOS-Simulator, using the latest, installed SDK, and building SDL test apps (as .app bundles):
+
+    `cmake ~/sdl -DSDL_TEST=1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64`
+
+- for tvOS-Simulator, using the latest, installed SDK:
+
+    `cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_ARCHITECTURES=x86_64`
+
+- for tvOS-Device, using the latest, installed SDK:
+
+    `cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_ARCHITECTURES=arm64`

+ 5 - 2
sdl.mod/SDL/docs/README-winrt.md

@@ -296,7 +296,7 @@ A few files should be included directly in your app's MSVC project, specifically
    included, mouse-position reporting may fail if and when the cursor is
    included, mouse-position reporting may fail if and when the cursor is
    hidden, due to possible bugs/design-oddities in Windows itself.*
    hidden, due to possible bugs/design-oddities in Windows itself.*
 
 
-To include these files:
+To include these files for C/C++ projects:
 
 
 1. right-click on your project (again, in Visual C++'s Solution Explorer), 
 1. right-click on your project (again, in Visual C++'s Solution Explorer), 
    navigate to "Add", then choose "Existing Item...".
    navigate to "Add", then choose "Existing Item...".
@@ -313,11 +313,14 @@ To include these files:
 7. change the setting for "Consume Windows Runtime Extension" to "Yes (/ZW)".
 7. change the setting for "Consume Windows Runtime Extension" to "Yes (/ZW)".
 8. click the OK button.  This will close the dialog.
 8. click the OK button.  This will close the dialog.
 
 
-
 **NOTE: C++/CX compilation is currently required in at least one file of your 
 **NOTE: C++/CX compilation is currently required in at least one file of your 
 app's project.  This is to make sure that Visual C++'s linker builds a 'Windows 
 app's project.  This is to make sure that Visual C++'s linker builds a 'Windows 
 Metadata' file (.winmd) for your app.  Not doing so can lead to build errors.**
 Metadata' file (.winmd) for your app.  Not doing so can lead to build errors.**
 
 
+For non-C++ projects, you will need to call SDL_WinRTRunApp from your language's
+main function, and generate SDL2-WinRTResources.res manually by using `rc` via
+the Developer Command Prompt and including it as a <Win32Resource> within the
+first <PropertyGroup> block in your Visual Studio project file.
 
 
 ### 6. Add app code and assets ###
 ### 6. Add app code and assets ###
 
 

+ 1 - 0
sdl.mod/SDL/include/SDL.h

@@ -47,6 +47,7 @@
 #include "SDL_loadso.h"
 #include "SDL_loadso.h"
 #include "SDL_log.h"
 #include "SDL_log.h"
 #include "SDL_messagebox.h"
 #include "SDL_messagebox.h"
+#include "SDL_metal.h"
 #include "SDL_mutex.h"
 #include "SDL_mutex.h"
 #include "SDL_power.h"
 #include "SDL_power.h"
 #include "SDL_render.h"
 #include "SDL_render.h"

+ 18 - 0
sdl.mod/SDL/include/SDL_atomic.h

@@ -162,12 +162,29 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
 #define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #elif defined(__GNUC__) && defined(__arm__)
 #elif defined(__GNUC__) && defined(__arm__)
+#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */
+/* Information from:
+   https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19
+
+   The Linux kernel provides a helper function which provides the right code for a memory barrier,
+   hard-coded at address 0xffff0fa0
+*/
+typedef void (*SDL_KernelMemoryBarrierFunc)();
+#define SDL_MemoryBarrierRelease()	((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#define SDL_MemoryBarrierAcquire()	((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#elif 0 /* defined(__QNXNTO__) */
+#include <sys/cpuinline.h>
+
+#define SDL_MemoryBarrierRelease()   __cpu_membarrier()
+#define SDL_MemoryBarrierAcquire()   __cpu_membarrier()
+#else
 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
 #define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("dmb ish" : : : "memory")
 #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__)
 #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__)
 #ifdef __thumb__
 #ifdef __thumb__
 /* The mcr instruction isn't available in thumb mode, use real functions */
 /* The mcr instruction isn't available in thumb mode, use real functions */
+#define SDL_MEMORY_BARRIER_USES_FUNCTION
 #define SDL_MemoryBarrierRelease()   SDL_MemoryBarrierReleaseFunction()
 #define SDL_MemoryBarrierRelease()   SDL_MemoryBarrierReleaseFunction()
 #define SDL_MemoryBarrierAcquire()   SDL_MemoryBarrierAcquireFunction()
 #define SDL_MemoryBarrierAcquire()   SDL_MemoryBarrierAcquireFunction()
 #else
 #else
@@ -177,6 +194,7 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
 #else
 #else
 #define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("" : : : "memory")
 #define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("" : : : "memory")
+#endif /* __LINUX__ || __ANDROID__ */
 #endif /* __GNUC__ && __arm__ */
 #endif /* __GNUC__ && __arm__ */
 #else
 #else
 #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
 #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))

+ 46 - 13
sdl.mod/SDL/include/SDL_audio.h

@@ -420,23 +420,56 @@ extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
 /* @} *//* Pause audio functions */
 /* @} *//* Pause audio functions */
 
 
 /**
 /**
- *  This function loads a WAVE from the data source, automatically freeing
- *  that source if \c freesrc is non-zero.  For example, to load a WAVE file,
- *  you could do:
+ *  \brief Load the audio data of a WAVE file into memory
+ *
+ *  Loading a WAVE file requires \c src, \c spec, \c audio_buf and \c audio_len
+ *  to be valid pointers. The entire data portion of the file is then loaded
+ *  into memory and decoded if necessary.
+ *
+ *  If \c freesrc is non-zero, the data source gets automatically closed and
+ *  freed before the function returns.
+ *
+ *  Supported are RIFF WAVE files with the formats PCM (8, 16, 24, and 32 bits),
+ *  IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and A-law and
+ *  µ-law (8 bits). Other formats are currently unsupported and cause an error.
+ *
+ *  If this function succeeds, the pointer returned by it is equal to \c spec
+ *  and the pointer to the audio data allocated by the function is written to
+ *  \c audio_buf and its length in bytes to \c audio_len. The \ref SDL_AudioSpec
+ *  members \c freq, \c channels, and \c format are set to the values of the
+ *  audio data in the buffer. The \c samples member is set to a sane default and
+ *  all others are set to zero.
+ *
+ *  It's necessary to use SDL_FreeWAV() to free the audio data returned in
+ *  \c audio_buf when it is no longer used.
+ *
+ *  Because of the underspecification of the Waveform format, there are many
+ *  problematic files in the wild that cause issues with strict decoders. To
+ *  provide compatibility with these files, this decoder is lenient in regards
+ *  to the truncation of the file, the fact chunk, and the size of the RIFF
+ *  chunk. The hints SDL_HINT_WAVE_RIFF_CHUNK_SIZE, SDL_HINT_WAVE_TRUNCATION,
+ *  and SDL_HINT_WAVE_FACT_CHUNK can be used to tune the behavior of the
+ *  loading process.
+ *
+ *  Any file that is invalid (due to truncation, corruption, or wrong values in
+ *  the headers), too big, or unsupported causes an error. Additionally, any
+ *  critical I/O error from the data source will terminate the loading process
+ *  with an error. The function returns NULL on error and in all cases (with the
+ *  exception of \c src being NULL), an appropriate error message will be set.
+ *
+ *  It is required that the data source supports seeking.
+ *
+ *  Example:
  *  \code
  *  \code
  *      SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...);
  *      SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...);
  *  \endcode
  *  \endcode
  *
  *
- *  If this function succeeds, it returns the given SDL_AudioSpec,
- *  filled with the audio data format of the wave data, and sets
- *  \c *audio_buf to a malloc()'d buffer containing the audio data,
- *  and sets \c *audio_len to the length of that audio buffer, in bytes.
- *  You need to free the audio buffer with SDL_FreeWAV() when you are
- *  done with it.
- *
- *  This function returns NULL and sets the SDL error message if the
- *  wave file cannot be opened, uses an unknown data format, or is
- *  corrupt.  Currently raw and MS-ADPCM WAVE files are supported.
+ *  \param src The data source with the WAVE data
+ *  \param freesrc A integer value that makes the function close the data source if non-zero
+ *  \param spec A pointer filled with the audio format of the audio data
+ *  \param audio_buf A pointer filled with the audio data allocated by the function
+ *  \param audio_len A pointer filled with the length of the audio data buffer in bytes
+ *  \return NULL on error, or non-NULL on success.
  */
  */
 extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
 extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
                                                       int freesrc,
                                                       int freesrc,

+ 14 - 1
sdl.mod/SDL/include/SDL_config.h.cmake

@@ -211,7 +211,6 @@
 #cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@
 #cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@
 #cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@
 #cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@
 
 
-#cmakedefine HAVE_ENDPOINTVOLUME_H @HAVE_ENDPOINTVOLUME_H@
 #cmakedefine HAVE_MMDEVICEAPI_H @HAVE_MMDEVICEAPI_H@
 #cmakedefine HAVE_MMDEVICEAPI_H @HAVE_MMDEVICEAPI_H@
 #cmakedefine HAVE_AUDIOCLIENT_H @HAVE_AUDIOCLIENT_H@
 #cmakedefine HAVE_AUDIOCLIENT_H @HAVE_AUDIOCLIENT_H@
 
 
@@ -286,6 +285,7 @@
 #cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@
 #cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@
 #cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@
 #cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@
 #cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
 #cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
+#cmakedefine SDL_JOYSTICK_HIDAPI @SDL_JOYSTICK_HIDAPI@
 #cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
 #cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
 #cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
 #cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
 #cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
 #cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
@@ -293,9 +293,11 @@
 #cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@
 #cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@
 #cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@
 #cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@
 #cmakedefine SDL_HAPTIC_ANDROID @SDL_HAPTIC_ANDROID@
 #cmakedefine SDL_HAPTIC_ANDROID @SDL_HAPTIC_ANDROID@
+#cmakedefine SDL_LIBUSB_DYNAMIC @SDL_LIBUSB_DYNAMIC@
 
 
 /* Enable various sensor drivers */
 /* Enable various sensor drivers */
 #cmakedefine SDL_SENSOR_ANDROID @SDL_SENSOR_ANDROID@
 #cmakedefine SDL_SENSOR_ANDROID @SDL_SENSOR_ANDROID@
+#cmakedefine SDL_SENSOR_COREMOTION @SDL_SENSOR_COREMOTION@
 #cmakedefine SDL_SENSOR_DUMMY @SDL_SENSOR_DUMMY@
 #cmakedefine SDL_SENSOR_DUMMY @SDL_SENSOR_DUMMY@
 
 
 /* Enable various shared object loading systems */
 /* Enable various shared object loading systems */
@@ -321,9 +323,11 @@
 #cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
 #cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
 #cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
 #cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
 #cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
 #cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
+#cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@
 #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
 #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
 #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
 #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
 #cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
 #cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
+#cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN @SDL_VIDEO_DRIVER_OFFSCREEN@
 #cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
 #cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
 #cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
 #cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
 #cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@
 #cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@
@@ -386,11 +390,15 @@
 /* Enable Vulkan support */
 /* Enable Vulkan support */
 #cmakedefine SDL_VIDEO_VULKAN @SDL_VIDEO_VULKAN@
 #cmakedefine SDL_VIDEO_VULKAN @SDL_VIDEO_VULKAN@
 
 
+/* Enable Metal support */
+#cmakedefine SDL_VIDEO_METAL @SDL_VIDEO_METAL@
+
 /* Enable system power support */
 /* Enable system power support */
 #cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
 #cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
 #cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@
 #cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@
 #cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@
 #cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@
 #cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@
 #cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@
+#cmakedefine SDL_POWER_UIKIT @SDL_POWER_UIKIT@
 #cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@
 #cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@
 #cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@
 #cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@
 #cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
 #cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
@@ -407,11 +415,16 @@
 /* Enable assembly routines */
 /* Enable assembly routines */
 #cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@
 #cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@
 #cmakedefine SDL_ALTIVEC_BLITTERS @SDL_ALTIVEC_BLITTERS@
 #cmakedefine SDL_ALTIVEC_BLITTERS @SDL_ALTIVEC_BLITTERS@
+#cmakedefine SDL_ARM_SIMD_BLITTERS @SDL_ARM_SIMD_BLITTERS@
+#cmakedefine SDL_ARM_NEON_BLITTERS @SDL_ARM_NEON_BLITTERS@
 
 
 /* Enable dynamic libsamplerate support */
 /* Enable dynamic libsamplerate support */
 #cmakedefine SDL_LIBSAMPLERATE_DYNAMIC @SDL_LIBSAMPLERATE_DYNAMIC@
 #cmakedefine SDL_LIBSAMPLERATE_DYNAMIC @SDL_LIBSAMPLERATE_DYNAMIC@
 
 
 /* Platform specific definitions */
 /* Platform specific definitions */
+#cmakedefine SDL_IPHONE_KEYBOARD @SDL_IPHONE_KEYBOARD@
+#cmakedefine SDL_IPHONE_LAUNCHSCREEN @SDL_IPHONE_LAUNCHSCREEN@
+
 #if !defined(__WIN32__)
 #if !defined(__WIN32__)
 #  if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
 #  if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
 typedef unsigned int size_t;
 typedef unsigned int size_t;

+ 12 - 5
sdl.mod/SDL/include/SDL_config.h.in

@@ -33,7 +33,7 @@
 
 
 /* Make sure that this isn't included by Visual C++ */
 /* Make sure that this isn't included by Visual C++ */
 #ifdef _MSC_VER
 #ifdef _MSC_VER
-#error You should run hg revert SDL_config.h 
+#error You should run hg revert SDL_config.h
 #endif
 #endif
 
 
 /* C language features */
 /* C language features */
@@ -192,9 +192,9 @@
 #undef HAVE__EXIT
 #undef HAVE__EXIT
 
 
 #else
 #else
-#define HAVE_STDARG_H   1
-#define HAVE_STDDEF_H   1
-#define HAVE_STDINT_H   1
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
 #endif /* HAVE_LIBC */
 #endif /* HAVE_LIBC */
 
 
 #undef HAVE_ALTIVEC_H
 #undef HAVE_ALTIVEC_H
@@ -210,7 +210,6 @@
 #undef HAVE_DSOUND_H
 #undef HAVE_DSOUND_H
 #undef HAVE_DXGI_H
 #undef HAVE_DXGI_H
 #undef HAVE_XINPUT_H
 #undef HAVE_XINPUT_H
-#undef HAVE_ENDPOINTVOLUME_H
 #undef HAVE_MMDEVICEAPI_H
 #undef HAVE_MMDEVICEAPI_H
 #undef HAVE_AUDIOCLIENT_H
 #undef HAVE_AUDIOCLIENT_H
 #undef HAVE_XINPUT_GAMEPAD_EX
 #undef HAVE_XINPUT_GAMEPAD_EX
@@ -383,6 +382,9 @@
 /* Enable Vulkan support */
 /* Enable Vulkan support */
 #undef SDL_VIDEO_VULKAN
 #undef SDL_VIDEO_VULKAN
 
 
+/* Enable Metal support */
+#undef SDL_VIDEO_METAL
+
 /* Enable system power support */
 /* Enable system power support */
 #undef SDL_POWER_LINUX
 #undef SDL_POWER_LINUX
 #undef SDL_POWER_WINDOWS
 #undef SDL_POWER_WINDOWS
@@ -405,6 +407,8 @@
 /* Enable assembly routines */
 /* Enable assembly routines */
 #undef SDL_ASSEMBLY_ROUTINES
 #undef SDL_ASSEMBLY_ROUTINES
 #undef SDL_ALTIVEC_BLITTERS
 #undef SDL_ALTIVEC_BLITTERS
+#undef SDL_ARM_SIMD_BLITTERS
+#undef SDL_ARM_NEON_BLITTERS
 
 
 /* Enable ime support */
 /* Enable ime support */
 #undef SDL_USE_IME
 #undef SDL_USE_IME
@@ -412,6 +416,9 @@
 /* Enable dynamic udev support */
 /* Enable dynamic udev support */
 #undef SDL_UDEV_DYNAMIC
 #undef SDL_UDEV_DYNAMIC
 
 
+/* Enable dynamic libusb support */
+#undef SDL_LIBUSB_DYNAMIC
+
 /* Enable dynamic libsamplerate support */
 /* Enable dynamic libsamplerate support */
 #undef SDL_LIBSAMPLERATE_DYNAMIC
 #undef SDL_LIBSAMPLERATE_DYNAMIC
 
 

+ 4 - 0
sdl.mod/SDL/include/SDL_config_iphoneos.h

@@ -181,6 +181,10 @@
 #define SDL_VIDEO_VULKAN 1
 #define SDL_VIDEO_VULKAN 1
 #endif
 #endif
 
 
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_METAL 1
+#endif
+
 /* Enable system power support */
 /* Enable system power support */
 #define SDL_POWER_UIKIT 1
 #define SDL_POWER_UIKIT 1
 
 

+ 28 - 11
sdl.mod/SDL/include/SDL_config_macosx.h

@@ -130,6 +130,8 @@
 #define HAVE_SYSCONF    1
 #define HAVE_SYSCONF    1
 #define HAVE_SYSCTLBYNAME 1
 #define HAVE_SYSCTLBYNAME 1
 
 
+#define HAVE_GCC_ATOMICS 1
+
 /* Enable various audio drivers */
 /* Enable various audio drivers */
 #define SDL_AUDIO_DRIVER_COREAUDIO  1
 #define SDL_AUDIO_DRIVER_COREAUDIO  1
 #define SDL_AUDIO_DRIVER_DISK   1
 #define SDL_AUDIO_DRIVER_DISK   1
@@ -157,13 +159,13 @@
 #define SDL_VIDEO_DRIVER_COCOA  1
 #define SDL_VIDEO_DRIVER_COCOA  1
 #define SDL_VIDEO_DRIVER_DUMMY  1
 #define SDL_VIDEO_DRIVER_DUMMY  1
 #undef SDL_VIDEO_DRIVER_X11
 #undef SDL_VIDEO_DRIVER_X11
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib"
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib"
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib"
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib"
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib"
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib"
-#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/opt/X11/lib/libX11.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/opt/X11/lib/libXext.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/opt/X11/lib/libXinerama.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/opt/X11/lib/libXi.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/opt/X11/lib/libXrandr.2.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/opt/X11/lib/libXss.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/opt/X11/lib/libXxf86vm.1.dylib"
 #define SDL_VIDEO_DRIVER_X11_XDBE 1
 #define SDL_VIDEO_DRIVER_X11_XDBE 1
 #define SDL_VIDEO_DRIVER_X11_XINERAMA 1
 #define SDL_VIDEO_DRIVER_X11_XINERAMA 1
 #define SDL_VIDEO_DRIVER_X11_XRANDR 1
 #define SDL_VIDEO_DRIVER_X11_XRANDR 1
@@ -191,9 +193,15 @@
 #define SDL_VIDEO_RENDER_OGL_ES2 1
 #define SDL_VIDEO_RENDER_OGL_ES2 1
 #endif
 #endif
 
 
-#ifndef SDL_VIDEO_RENDER_METAL
 /* Metal only supported on 64-bit architectures with 10.11+ */
 /* Metal only supported on 64-bit architectures with 10.11+ */
 #if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
 #if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+#define SDL_PLATFORM_SUPPORTS_METAL    1
+#else
+#define SDL_PLATFORM_SUPPORTS_METAL    0
+#endif
+
+#ifndef SDL_VIDEO_RENDER_METAL
+#if SDL_PLATFORM_SUPPORTS_METAL
 #define SDL_VIDEO_RENDER_METAL    1
 #define SDL_VIDEO_RENDER_METAL    1
 #else
 #else
 #define SDL_VIDEO_RENDER_METAL    0
 #define SDL_VIDEO_RENDER_METAL    0
@@ -217,13 +225,22 @@
 #define SDL_VIDEO_OPENGL_GLX    1
 #define SDL_VIDEO_OPENGL_GLX    1
 #endif
 #endif
 
 
-/* Enable Vulkan support */
-/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures with 10.11+ */
-#if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+/* Enable Vulkan and Metal support */
+#ifndef SDL_VIDEO_VULKAN
+#if SDL_PLATFORM_SUPPORTS_METAL
 #define SDL_VIDEO_VULKAN 1
 #define SDL_VIDEO_VULKAN 1
 #else
 #else
 #define SDL_VIDEO_VULKAN 0
 #define SDL_VIDEO_VULKAN 0
 #endif
 #endif
+#endif
+
+#ifndef SDL_VIDEO_METAL
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_METAL 1
+#else
+#define SDL_VIDEO_METAL 0
+#endif
+#endif
 
 
 /* Enable system power support */
 /* Enable system power support */
 #define SDL_POWER_MACOSX 1
 #define SDL_POWER_MACOSX 1

+ 2 - 3
sdl.mod/SDL/include/SDL_config_windows.h

@@ -84,7 +84,6 @@ typedef unsigned int uintptr_t;
 #define HAVE_XINPUT_H 1
 #define HAVE_XINPUT_H 1
 #define HAVE_MMDEVICEAPI_H 1
 #define HAVE_MMDEVICEAPI_H 1
 #define HAVE_AUDIOCLIENT_H 1
 #define HAVE_AUDIOCLIENT_H 1
-#define HAVE_ENDPOINTVOLUME_H 1
 
 
 /* This is disabled by default to avoid C runtime dependencies and manifest requirements */
 /* This is disabled by default to avoid C runtime dependencies and manifest requirements */
 #ifdef HAVE_LIBC
 #ifdef HAVE_LIBC
@@ -139,7 +138,7 @@ typedef unsigned int uintptr_t;
 #define HAVE_ATAN2  1
 #define HAVE_ATAN2  1
 #define HAVE_ATAN2F 1
 #define HAVE_ATAN2F 1
 #define HAVE_CEILF  1
 #define HAVE_CEILF  1
-#define HAVE__COPYSIGN  1
+#define HAVE__COPYSIGN 1
 #define HAVE_COS    1
 #define HAVE_COS    1
 #define HAVE_COSF   1
 #define HAVE_COSF   1
 #define HAVE_EXP    1
 #define HAVE_EXP    1
@@ -168,7 +167,7 @@ typedef unsigned int uintptr_t;
 #define HAVE_STRTOLL 1
 #define HAVE_STRTOLL 1
 #define HAVE_VSSCANF 1
 #define HAVE_VSSCANF 1
 #define HAVE_SCALBN 1
 #define HAVE_SCALBN 1
-#define HAVE_SCALBNF    1
+#define HAVE_SCALBNF 1
 #endif
 #endif
 /* This function is available with at least the VC++ 2008 C runtime library */
 /* This function is available with at least the VC++ 2008 C runtime library */
 #if _MSC_VER >= 1400
 #if _MSC_VER >= 1400

+ 0 - 1
sdl.mod/SDL/include/SDL_config_winrt.h

@@ -100,7 +100,6 @@ typedef unsigned int uintptr_t;
 
 
 #define HAVE_MMDEVICEAPI_H 1
 #define HAVE_MMDEVICEAPI_H 1
 #define HAVE_AUDIOCLIENT_H 1
 #define HAVE_AUDIOCLIENT_H 1
-#define HAVE_ENDPOINTVOLUME_H 1
 
 
 #define HAVE_LIBC 1
 #define HAVE_LIBC 1
 #define STDC_HEADERS 1
 #define STDC_HEADERS 1

+ 72 - 4
sdl.mod/SDL/include/SDL_cpuinfo.h

@@ -70,13 +70,13 @@
 #    if defined(_M_ARM)
 #    if defined(_M_ARM)
 #      include <armintr.h>
 #      include <armintr.h>
 #      include <arm_neon.h>
 #      include <arm_neon.h>
+#      define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
 #    endif
 #    endif
 #    if defined (_M_ARM64)
 #    if defined (_M_ARM64)
-#      include <armintr.h>
-#      include <arm_neon.h>
+#      include <arm64intr.h>
+#      include <arm64_neon.h>
+#      define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
 #    endif
 #    endif
-/* Set __ARM_NEON so that it can be used elsewhere, at compile time */
-#    define __ARM_NEON 1
 #  endif
 #  endif
 #endif
 #endif
 #if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
 #if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
@@ -186,6 +186,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
  */
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
 extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
 
 
+/**
+ *  This function returns true if the CPU has ARM SIMD (ARMv6) features.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void);
+
 /**
 /**
  *  This function returns true if the CPU has NEON (ARM SIMD) features.
  *  This function returns true if the CPU has NEON (ARM SIMD) features.
  */
  */
@@ -196,6 +201,69 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
  */
  */
 extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
 extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
 
 
+/**
+ * \brief Report the alignment this system needs for SIMD allocations.
+ *
+ * This will return the minimum number of bytes to which a pointer must be
+ *  aligned to be compatible with SIMD instructions on the current machine.
+ *  For example, if the machine supports SSE only, it will return 16, but if
+ *  it supports AVX-512F, it'll return 64 (etc). This only reports values for
+ *  instruction sets SDL knows about, so if your SDL build doesn't have
+ *  SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and
+ *  not 64 for the AVX-512 instructions that exist but SDL doesn't know about.
+ *  Plan accordingly.
+ */
+extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void);
+
+/**
+ * \brief Allocate memory in a SIMD-friendly way.
+ *
+ * This will allocate a block of memory that is suitable for use with SIMD
+ *  instructions. Specifically, it will be properly aligned and padded for
+ *  the system's supported vector instructions.
+ *
+ * The memory returned will be padded such that it is safe to read or write
+ *  an incomplete vector at the end of the memory block. This can be useful
+ *  so you don't have to drop back to a scalar fallback at the end of your
+ *  SIMD processing loop to deal with the final elements without overflowing
+ *  the allocated buffer.
+ *
+ * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free()
+ *  or delete[], etc.
+ *
+ * Note that SDL will only deal with SIMD instruction sets it is aware of;
+ *  for example, SDL 2.0.8 knows that SSE wants 16-byte vectors
+ *  (SDL_HasSSE()), and AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't
+ *  know that AVX-512 wants 64. To be clear: if you can't decide to use an
+ *  instruction set with an SDL_Has*() function, don't use that instruction
+ *  set with memory allocated through here.
+ *
+ * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't
+ *  out of memory.
+ *
+ *  \param len The length, in bytes, of the block to allocated. The actual
+ *             allocated block might be larger due to padding, etc.
+ * \return Pointer to newly-allocated block, NULL if out of memory.
+ *
+ * \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
+
+/**
+ * \brief Deallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ *  SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
+ *  SDL_malloc, memalign, new[], etc.
+ *
+ * However, SDL_SIMDFree(NULL) is a legal no-op.
+ *
+ * \sa SDL_SIMDAlloc
+ */
+extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
+
+/* vi: set ts=4 sw=4 expandtab: */
 /* Ends C function definitions when using C++ */
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 3 - 0
sdl.mod/SDL/include/SDL_egl.h

@@ -390,6 +390,9 @@ typedef enum {
 #ifndef WIN32_LEAN_AND_MEAN
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
 #define WIN32_LEAN_AND_MEAN 1
 #endif
 #endif
+#ifndef NOMINMAX   /* don't define min() and max(). */
+#define NOMINMAX
+#endif
 #include <windows.h>
 #include <windows.h>
 
 
 #if __WINRT__
 #if __WINRT__

+ 5 - 2
sdl.mod/SDL/include/SDL_endian.h

@@ -42,10 +42,13 @@
 #ifdef __linux__
 #ifdef __linux__
 #include <endian.h>
 #include <endian.h>
 #define SDL_BYTEORDER  __BYTE_ORDER
 #define SDL_BYTEORDER  __BYTE_ORDER
-#else /* __linux__ */
+#elif defined(__OpenBSD__)
+#include <endian.h>
+#define SDL_BYTEORDER  BYTE_ORDER
+#else
 #if defined(__hppa__) || \
 #if defined(__hppa__) || \
     defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
     defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
-    (defined(__MIPS__) && defined(__MISPEB__)) || \
+    (defined(__MIPS__) && defined(__MIPSEB__)) || \
     defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
     defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
     defined(__sparc__)
     defined(__sparc__)
 #define SDL_BYTEORDER   SDL_BIG_ENDIAN
 #define SDL_BYTEORDER   SDL_BIG_ENDIAN

+ 5 - 1
sdl.mod/SDL/include/SDL_events.h

@@ -442,6 +442,7 @@ typedef struct SDL_TouchFingerEvent
     float dx;           /**< Normalized in the range -1...1 */
     float dx;           /**< Normalized in the range -1...1 */
     float dy;           /**< Normalized in the range -1...1 */
     float dy;           /**< Normalized in the range -1...1 */
     float pressure;     /**< Normalized in the range 0...1 */
     float pressure;     /**< Normalized in the range 0...1 */
+    Uint32 windowID;    /**< The window underneath the finger, if any */
 } SDL_TouchFingerEvent;
 } SDL_TouchFingerEvent;
 
 
 
 
@@ -558,7 +559,7 @@ typedef union SDL_Event
 {
 {
     Uint32 type;                    /**< Event type, shared with all events */
     Uint32 type;                    /**< Event type, shared with all events */
     SDL_CommonEvent common;         /**< Common event data */
     SDL_CommonEvent common;         /**< Common event data */
-    SDL_DisplayEvent display;       /**< Window event data */
+    SDL_DisplayEvent display;       /**< Display event data */
     SDL_WindowEvent window;         /**< Window event data */
     SDL_WindowEvent window;         /**< Window event data */
     SDL_KeyboardEvent key;          /**< Keyboard event data */
     SDL_KeyboardEvent key;          /**< Keyboard event data */
     SDL_TextEditingEvent edit;      /**< Text editing event data */
     SDL_TextEditingEvent edit;      /**< Text editing event data */
@@ -594,6 +595,9 @@ typedef union SDL_Event
     Uint8 padding[56];
     Uint8 padding[56];
 } SDL_Event;
 } SDL_Event;
 
 
+/* Make sure we haven't broken binary compatibility */
+SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == 56);
+
 
 
 /* Function prototypes */
 /* Function prototypes */
 
 

+ 93 - 11
sdl.mod/SDL/include/SDL_hints.h

@@ -197,6 +197,12 @@ extern "C" {
  */
  */
 #define SDL_HINT_VIDEO_X11_XRANDR           "SDL_VIDEO_X11_XRANDR"
 #define SDL_HINT_VIDEO_X11_XRANDR           "SDL_VIDEO_X11_XRANDR"
 
 
+/**
+ *  \brief  A variable forcing the visual ID chosen for new X11 windows
+ *
+ */
+#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID      "SDL_VIDEO_X11_WINDOW_VISUALID"
+
 /**
 /**
  *  \brief  A variable controlling whether the X11 _NET_WM_PING protocol should be supported.
  *  \brief  A variable controlling whether the X11 _NET_WM_PING protocol should be supported.
  *
  *
@@ -482,6 +488,29 @@ extern "C" {
  */
  */
 #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
 #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
 
 
+/**
+ *  \brief  If set, game controller face buttons report their values according to their labels instead of their positional layout.
+ * 
+ *  For example, on Nintendo Switch controllers, normally you'd get:
+ *
+ *      (Y)
+ *  (X)     (B)
+ *      (A)
+ *
+ *  but if this hint is set, you'll get:
+ *
+ *      (X)
+ *  (Y)     (A)
+ *      (B)
+ *
+ *  The variable can be set to the following values:
+ *    "0"       - Report the face buttons by position, as though they were on an Xbox controller.
+ *    "1"       - Report the face buttons by label instead of position
+ *
+ *  The default value is "0".  This hint may be set at any time.
+ */
+#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS"
+
 /**
 /**
  *  \brief  A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
  *  \brief  A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
  *
  *
@@ -565,17 +594,6 @@ extern "C" {
  */
  */
 #define SDL_HINT_JOYSTICK_HIDAPI_XBOX   "SDL_JOYSTICK_HIDAPI_XBOX"
 #define SDL_HINT_JOYSTICK_HIDAPI_XBOX   "SDL_JOYSTICK_HIDAPI_XBOX"
 
 
-/**
- *  \brief  A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
- *
- *  This variable can be set to the following values:
- *    "0"       - HIDAPI driver is not used
- *    "1"       - HIDAPI driver is used
- *
- *  The default is the value of SDL_HINT_JOYSTICK_HIDAPI
- */
-#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
-
 /**
 /**
  *  \brief  A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
  *  \brief  A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
  *
  *
@@ -1121,6 +1139,70 @@ extern "C" {
 
 
 
 
 
 
+/**
+ *  \brief  Controls how the size of the RIFF chunk affects the loading of a WAVE file.
+ *
+ *  The size of the RIFF chunk (which includes all the sub-chunks of the WAVE
+ *  file) is not always reliable. In case the size is wrong, it's possible to
+ *  just ignore it and step through the chunks until a fixed limit is reached.
+ *
+ *  Note that files that have trailing data unrelated to the WAVE file or
+ *  corrupt files may slow down the loading process without a reliable boundary.
+ *  By default, SDL stops after 10000 chunks to prevent wasting time. Use the
+ *  environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value.
+ *
+ *  This variable can be set to the following values:
+ *
+ *    "force"        - Always use the RIFF chunk size as a boundary for the chunk search
+ *    "ignorezero"   - Like "force", but a zero size searches up to 4 GiB (default)
+ *    "ignore"       - Ignore the RIFF chunk size and always search up to 4 GiB
+ *    "maximum"      - Search for chunks until the end of file (not recommended)
+ */
+#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE   "SDL_WAVE_RIFF_CHUNK_SIZE"
+
+/**
+ *  \brief  Controls how a truncated WAVE file is handled.
+ *
+ *  A WAVE file is considered truncated if any of the chunks are incomplete or
+ *  the data chunk size is not a multiple of the block size. By default, SDL
+ *  decodes until the first incomplete block, as most applications seem to do.
+ *
+ *  This variable can be set to the following values:
+ *
+ *    "verystrict" - Raise an error if the file is truncated
+ *    "strict"     - Like "verystrict", but the size of the RIFF chunk is ignored
+ *    "dropframe"  - Decode until the first incomplete sample frame
+ *    "dropblock"  - Decode until the first incomplete block (default)
+ */
+#define SDL_HINT_WAVE_TRUNCATION   "SDL_WAVE_TRUNCATION"
+
+/**
+ *  \brief  Controls how the fact chunk affects the loading of a WAVE file.
+ *
+ *  The fact chunk stores information about the number of samples of a WAVE
+ *  file. The Standards Update from Microsoft notes that this value can be used
+ *  to 'determine the length of the data in seconds'. This is especially useful
+ *  for compressed formats (for which this is a mandatory chunk) if they produce
+ *  multiple sample frames per block and truncating the block is not allowed.
+ *  The fact chunk can exactly specify how many sample frames there should be
+ *  in this case.
+ *
+ *  Unfortunately, most application seem to ignore the fact chunk and so SDL
+ *  ignores it by default as well.
+ *
+ *  This variable can be set to the following values:
+ *
+ *    "truncate"    - Use the number of samples to truncate the wave data if
+ *                    the fact chunk is present and valid
+ *    "strict"      - Like "truncate", but raise an error if the fact chunk
+ *                    is invalid, not present for non-PCM formats, or if the
+ *                    data chunk doesn't have that many samples
+ *    "ignorezero"  - Like "truncate", but ignore fact chunk if the number of
+ *                    samples is zero
+ *    "ignore"      - Ignore fact chunk entirely (default)
+ */
+#define SDL_HINT_WAVE_FACT_CHUNK   "SDL_WAVE_FACT_CHUNK"
+
 /**
 /**
  *  \brief  An enumeration of hint priorities
  *  \brief  An enumeration of hint priorities
  */
  */

+ 2 - 2
sdl.mod/SDL/include/SDL_keycode.h

@@ -47,7 +47,7 @@ typedef Sint32 SDL_Keycode;
 #define SDLK_SCANCODE_MASK (1<<30)
 #define SDLK_SCANCODE_MASK (1<<30)
 #define SDL_SCANCODE_TO_KEYCODE(X)  (X | SDLK_SCANCODE_MASK)
 #define SDL_SCANCODE_TO_KEYCODE(X)  (X | SDLK_SCANCODE_MASK)
 
 
-enum
+typedef enum
 {
 {
     SDLK_UNKNOWN = 0,
     SDLK_UNKNOWN = 0,
 
 
@@ -317,7 +317,7 @@ enum
 
 
     SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND),
     SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND),
     SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD)
     SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD)
-};
+} SDL_KeyCode;
 
 
 /**
 /**
  * \brief Enumeration of valid key mods (possibly OR'd together).
  * \brief Enumeration of valid key mods (possibly OR'd together).

+ 2 - 2
sdl.mod/SDL/include/SDL_log.h

@@ -61,7 +61,7 @@ extern "C" {
  *  at the VERBOSE level and all other categories are enabled at the
  *  at the VERBOSE level and all other categories are enabled at the
  *  CRITICAL level.
  *  CRITICAL level.
  */
  */
-enum
+typedef enum
 {
 {
     SDL_LOG_CATEGORY_APPLICATION,
     SDL_LOG_CATEGORY_APPLICATION,
     SDL_LOG_CATEGORY_ERROR,
     SDL_LOG_CATEGORY_ERROR,
@@ -94,7 +94,7 @@ enum
        };
        };
      */
      */
     SDL_LOG_CATEGORY_CUSTOM
     SDL_LOG_CATEGORY_CUSTOM
-};
+} SDL_LogCategory;
 
 
 /**
 /**
  *  \brief The predefined log priorities
  *  \brief The predefined log priorities

+ 5 - 3
sdl.mod/SDL/include/SDL_messagebox.h

@@ -36,9 +36,11 @@ extern "C" {
  */
  */
 typedef enum
 typedef enum
 {
 {
-    SDL_MESSAGEBOX_ERROR        = 0x00000010,   /**< error dialog */
-    SDL_MESSAGEBOX_WARNING      = 0x00000020,   /**< warning dialog */
-    SDL_MESSAGEBOX_INFORMATION  = 0x00000040    /**< informational dialog */
+    SDL_MESSAGEBOX_ERROR                 = 0x00000010,   /**< error dialog */
+    SDL_MESSAGEBOX_WARNING               = 0x00000020,   /**< warning dialog */
+    SDL_MESSAGEBOX_INFORMATION           = 0x00000040,   /**< informational dialog */
+    SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT = 0x00000080,   /**< buttons placed left to right */
+    SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT = 0x00000100    /**< buttons placed right to left */
 } SDL_MessageBoxFlags;
 } SDL_MessageBoxFlags;
 
 
 /**
 /**

+ 91 - 0
sdl.mod/SDL/include/SDL_metal.h

@@ -0,0 +1,91 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2019 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_metal.h
+ *
+ *  Header file for functions to creating Metal layers and views on SDL windows.
+ */
+
+#ifndef SDL_metal_h_
+#define SDL_metal_h_
+
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS).
+ *
+ *  \note This can be cast directly to an NSView or UIView.
+ */
+typedef void *SDL_MetalView;
+
+/**
+ *  \name Metal support functions
+ */
+/* @{ */
+
+/**
+ *  \brief Create a CAMetalLayer-backed NSView/UIView and attach it to the
+ *        specified window.
+ *
+ *  On macOS, this does *not* associate a MTLDevice with the CAMetalLayer on its
+ *  own. It is up to user code to do that.
+ *
+ *  The returned handle can be casted directly to a NSView or UIView, and the
+ *  CAMetalLayer can be accessed from the view's 'layer' property.
+ *
+ *  \code
+ *  SDL_MetalView metalview = SDL_Metal_CreateView(window);
+ *  UIView *uiview = (__bridge UIView *)metalview;
+ *  CAMetalLayer *metallayer = (CAMetalLayer *)uiview.layer;
+ *  // [...]
+ *  SDL_Metal_DestroyView(metalview);
+ *  \endcode
+ *
+ *  \sa SDL_Metal_DestroyView
+ */
+extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window);
+
+/**
+ *  \brief Destroy an existing SDL_MetalView object.
+ *
+ *  This should be called before SDL_DestroyWindow, if SDL_Metal_CreateView was
+ *  called after SDL_CreateWindow.
+ *
+ *  \sa SDL_Metal_CreateView
+ */
+extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view);
+
+/* @} *//* Metal support functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_metal_h_ */

+ 3 - 0
sdl.mod/SDL/include/SDL_opengl_glext.h

@@ -40,6 +40,9 @@ extern "C" {
 #ifndef WIN32_LEAN_AND_MEAN
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
 #define WIN32_LEAN_AND_MEAN 1
 #endif
 #endif
+#ifndef NOMINMAX   /* don't define min() and max(). */
+#define NOMINMAX
+#endif
 #include <windows.h>
 #include <windows.h>
 #endif
 #endif
 
 

+ 10 - 10
sdl.mod/SDL/include/SDL_pixels.h

@@ -48,7 +48,7 @@ extern "C" {
 /* @} */
 /* @} */
 
 
 /** Pixel type. */
 /** Pixel type. */
-enum
+typedef enum
 {
 {
     SDL_PIXELTYPE_UNKNOWN,
     SDL_PIXELTYPE_UNKNOWN,
     SDL_PIXELTYPE_INDEX1,
     SDL_PIXELTYPE_INDEX1,
@@ -62,18 +62,18 @@ enum
     SDL_PIXELTYPE_ARRAYU32,
     SDL_PIXELTYPE_ARRAYU32,
     SDL_PIXELTYPE_ARRAYF16,
     SDL_PIXELTYPE_ARRAYF16,
     SDL_PIXELTYPE_ARRAYF32
     SDL_PIXELTYPE_ARRAYF32
-};
+} SDL_PixelType;
 
 
 /** Bitmap pixel order, high bit -> low bit. */
 /** Bitmap pixel order, high bit -> low bit. */
-enum
+typedef enum
 {
 {
     SDL_BITMAPORDER_NONE,
     SDL_BITMAPORDER_NONE,
     SDL_BITMAPORDER_4321,
     SDL_BITMAPORDER_4321,
     SDL_BITMAPORDER_1234
     SDL_BITMAPORDER_1234
-};
+} SDL_BitmapOrder;
 
 
 /** Packed component order, high bit -> low bit. */
 /** Packed component order, high bit -> low bit. */
-enum
+typedef enum
 {
 {
     SDL_PACKEDORDER_NONE,
     SDL_PACKEDORDER_NONE,
     SDL_PACKEDORDER_XRGB,
     SDL_PACKEDORDER_XRGB,
@@ -84,12 +84,12 @@ enum
     SDL_PACKEDORDER_BGRX,
     SDL_PACKEDORDER_BGRX,
     SDL_PACKEDORDER_ABGR,
     SDL_PACKEDORDER_ABGR,
     SDL_PACKEDORDER_BGRA
     SDL_PACKEDORDER_BGRA
-};
+} SDL_PackedOrder;
 
 
 /** Array component order, low byte -> high byte. */
 /** Array component order, low byte -> high byte. */
 /* !!! FIXME: in 2.1, make these not overlap differently with
 /* !!! FIXME: in 2.1, make these not overlap differently with
    !!! FIXME:  SDL_PACKEDORDER_*, so we can simplify SDL_ISPIXELFORMAT_ALPHA */
    !!! FIXME:  SDL_PACKEDORDER_*, so we can simplify SDL_ISPIXELFORMAT_ALPHA */
-enum
+typedef enum
 {
 {
     SDL_ARRAYORDER_NONE,
     SDL_ARRAYORDER_NONE,
     SDL_ARRAYORDER_RGB,
     SDL_ARRAYORDER_RGB,
@@ -98,10 +98,10 @@ enum
     SDL_ARRAYORDER_BGR,
     SDL_ARRAYORDER_BGR,
     SDL_ARRAYORDER_BGRA,
     SDL_ARRAYORDER_BGRA,
     SDL_ARRAYORDER_ABGR
     SDL_ARRAYORDER_ABGR
-};
+} SDL_ArrayOrder;
 
 
 /** Packed component layout. */
 /** Packed component layout. */
-enum
+typedef enum
 {
 {
     SDL_PACKEDLAYOUT_NONE,
     SDL_PACKEDLAYOUT_NONE,
     SDL_PACKEDLAYOUT_332,
     SDL_PACKEDLAYOUT_332,
@@ -112,7 +112,7 @@ enum
     SDL_PACKEDLAYOUT_8888,
     SDL_PACKEDLAYOUT_8888,
     SDL_PACKEDLAYOUT_2101010,
     SDL_PACKEDLAYOUT_2101010,
     SDL_PACKEDLAYOUT_1010102
     SDL_PACKEDLAYOUT_1010102
-};
+} SDL_PackedLayout;
 
 
 #define SDL_DEFINE_PIXELFOURCC(A, B, C, D) SDL_FOURCC(A, B, C, D)
 #define SDL_DEFINE_PIXELFOURCC(A, B, C, D) SDL_FOURCC(A, B, C, D)
 
 

+ 21 - 0
sdl.mod/SDL/include/SDL_render.h

@@ -430,10 +430,31 @@ extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture * texture,
                                             const SDL_Rect * rect,
                                             const SDL_Rect * rect,
                                             void **pixels, int *pitch);
                                             void **pixels, int *pitch);
 
 
+/**
+ *  \brief Lock a portion of the texture for write-only pixel access.
+ *         Expose it as a SDL surface.
+ *
+ *  \param texture   The texture to lock for access, which was created with
+ *                   ::SDL_TEXTUREACCESS_STREAMING.
+ *  \param rect      A pointer to the rectangle to lock for access. If the rect
+ *                   is NULL, the entire texture will be locked.
+ *  \param surface   This is filled in with a SDL surface representing the locked area
+ *                   Surface is freed internally after calling SDL_UnlockTexture or SDL_DestroyTexture.
+ *
+ *  \return 0 on success, or -1 if the texture is not valid or was not created with ::SDL_TEXTUREACCESS_STREAMING.
+ *
+ *  \sa SDL_UnlockTexture()
+ */
+extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture,
+                                            const SDL_Rect *rect,
+                                            SDL_Surface **surface);
+
 /**
 /**
  *  \brief Unlock a texture, uploading the changes to video memory, if needed.
  *  \brief Unlock a texture, uploading the changes to video memory, if needed.
+ *         If SDL_LockTextureToSurface() was called for locking, the SDL surface is freed.
  *
  *
  *  \sa SDL_LockTexture()
  *  \sa SDL_LockTexture()
+ *  \sa SDL_LockTextureToSurface()
  */
  */
 extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture * texture);
 extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture * texture);
 
 

+ 49 - 12
sdl.mod/SDL/include/SDL_rwops.h

@@ -176,19 +176,48 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area);
 #define RW_SEEK_END 2       /**< Seek relative to the end of data */
 #define RW_SEEK_END 2       /**< Seek relative to the end of data */
 
 
 /**
 /**
- *  \name Read/write macros
+ *  Return the size of the file in this rwops, or -1 if unknown
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context);
+
+/**
+ *  Seek to \c offset relative to \c whence, one of stdio's whence values:
+ *  RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END
  *
  *
- *  Macros to easily read and write from an SDL_RWops structure.
+ *  \return the final offset in the data stream, or -1 on error.
  */
  */
-/* @{ */
-#define SDL_RWsize(ctx)         (ctx)->size(ctx)
-#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence)
-#define SDL_RWtell(ctx)         (ctx)->seek(ctx, 0, RW_SEEK_CUR)
-#define SDL_RWread(ctx, ptr, size, n)   (ctx)->read(ctx, ptr, size, n)
-#define SDL_RWwrite(ctx, ptr, size, n)  (ctx)->write(ctx, ptr, size, n)
-#define SDL_RWclose(ctx)        (ctx)->close(ctx)
-/* @} *//* Read/write macros */
+extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context,
+                                          Sint64 offset, int whence);
+
+/**
+ *  Return the current offset in the data stream, or -1 on error.
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
 
 
+/**
+ *  Read up to \c maxnum objects each of size \c size from the data
+ *  stream to the area pointed at by \c ptr.
+ *
+ *  \return the number of objects read, or 0 at error or end of file.
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context,
+                                          void *ptr, size_t size, size_t maxnum);
+
+/**
+ *  Write exactly \c num objects each of size \c size from the area
+ *  pointed at by \c ptr to data stream.
+ *
+ *  \return the number of objects written, or 0 at error or end of file.
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context,
+                                           const void *ptr, size_t size, size_t num);
+
+/**
+ *  Close and free an allocated SDL_RWops structure.
+ *
+ *  \return 0 if successful or -1 on write error when flushing data.
+ */
+extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context);
 
 
 /**
 /**
  *  Load all the data from an SDL data stream.
  *  Load all the data from an SDL data stream.
@@ -209,9 +238,17 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize,
 /**
 /**
  *  Load an entire file.
  *  Load an entire file.
  *
  *
- *  Convenience macro.
+ *  The data is allocated with a zero byte at the end (null terminated)
+ *
+ *  If \c datasize is not NULL, it is filled with the size of the data read.
+ *
+ *  If \c freesrc is non-zero, the stream will be closed after being read.
+ *
+ *  The data should be freed with SDL_free().
+ *
+ *  \return the data, or NULL if there was an error.
  */
  */
-#define SDL_LoadFile(file, datasize)   SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1)
+extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize);
 
 
 /**
 /**
  *  \name Read endian functions
  *  \name Read endian functions

+ 4 - 1
sdl.mod/SDL/include/SDL_stdinc.h

@@ -415,11 +415,14 @@ extern DECLSPEC void *SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c,
 
 
 #define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
 #define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
 #define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
 #define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
+#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x)))
 
 
 /* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */
 /* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */
 SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
 SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
 {
 {
-#if defined(__GNUC__) && defined(i386)
+#ifdef __APPLE__
+    memset_pattern4(dst, &val, dwords * 4);
+#elif defined(__GNUC__) && defined(i386)
     int u0, u1, u2;
     int u0, u1, u2;
     __asm__ __volatile__ (
     __asm__ __volatile__ (
         "cld \n\t"
         "cld \n\t"

+ 3 - 0
sdl.mod/SDL/include/SDL_syswm.h

@@ -49,6 +49,9 @@ struct SDL_SysWMinfo;
 #ifndef WIN32_LEAN_AND_MEAN
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
 #endif
+#ifndef NOMINMAX   /* don't define min() and max(). */
+#define NOMINMAX
+#endif
 #include <windows.h>
 #include <windows.h>
 #endif
 #endif
 
 

+ 1 - 1
sdl.mod/SDL/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   0
 #define SDL_MINOR_VERSION   0
-#define SDL_PATCHLEVEL      9
+#define SDL_PATCHLEVEL      11
 
 
 /**
 /**
  *  \brief Macro to determine SDL version program was compiled against.
  *  \brief Macro to determine SDL version program was compiled against.

+ 0 - 1
sdl.mod/SDL/include/SDL_video.h

@@ -96,7 +96,6 @@ typedef struct SDL_Window SDL_Window;
  */
  */
 typedef enum
 typedef enum
 {
 {
-    /* !!! FIXME: change this to name = (1<<x). */
     SDL_WINDOW_FULLSCREEN = 0x00000001,         /**< fullscreen window */
     SDL_WINDOW_FULLSCREEN = 0x00000001,         /**< fullscreen window */
     SDL_WINDOW_OPENGL = 0x00000002,             /**< window usable with OpenGL context */
     SDL_WINDOW_OPENGL = 0x00000002,             /**< window usable with OpenGL context */
     SDL_WINDOW_SHOWN = 0x00000004,              /**< window is visible */
     SDL_WINDOW_SHOWN = 0x00000004,              /**< window is visible */

+ 3 - 3
sdl.mod/SDL/include/SDL_vulkan.h

@@ -98,8 +98,8 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */
  *        applications to link with libvulkan (and historically MoltenVK was
  *        applications to link with libvulkan (and historically MoltenVK was
  *        provided as a static library). If it is not found then, on macOS, SDL
  *        provided as a static library). If it is not found then, on macOS, SDL
  *        will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib,
  *        will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib,
- *        \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order.
- *        On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications
+ *        followed by \c libvulkan.dylib, in that order.
+ *        On iOS SDL will attempt to load \c libvulkan.dylib only. Applications
  *        using a dynamic framework or .dylib must ensure it is included in its
  *        using a dynamic framework or .dylib must ensure it is included in its
  *        application bundle.
  *        application bundle.
  *
  *
@@ -153,7 +153,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
  *  is smaller than the number of required extensions, \c SDL_FALSE will be
  *  is smaller than the number of required extensions, \c SDL_FALSE will be
  *  returned instead of \c SDL_TRUE, to indicate that not all the required
  *  returned instead of \c SDL_TRUE, to indicate that not all the required
  *  extensions were returned.
  *  extensions were returned.
- * 
+ *
  *  \note If \c window is not NULL, it will be checked against its creation
  *  \note If \c window is not NULL, it will be checked against its creation
  *        flags to ensure that the Vulkan flag is present. This parameter
  *        flags to ensure that the Vulkan flag is present. This parameter
  *        will be removed in a future major release.
  *        will be removed in a future major release.

+ 3 - 0
sdl.mod/SDL/include/begin_code.h

@@ -105,6 +105,9 @@
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #pragma warning(disable: 4103)
 #pragma warning(disable: 4103)
 #endif
 #endif
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpragma-pack"
+#endif
 #ifdef __BORLANDC__
 #ifdef __BORLANDC__
 #pragma nopackwarning
 #pragma nopackwarning
 #endif
 #endif

+ 36 - 0
sdl.mod/SDL/src/SDL.c

@@ -22,6 +22,14 @@
 
 
 #if defined(__WIN32__)
 #if defined(__WIN32__)
 #include "core/windows/SDL_windows.h"
 #include "core/windows/SDL_windows.h"
+#elif defined(__OS2__)
+#include <stdlib.h> /* For _exit() */
+#elif !defined(__WINRT__)
+#include <unistd.h> /* For _exit(), etc. */
+#endif
+
+#if defined(__EMSCRIPTEN__)
+#include <emscripten.h>
 #endif
 #endif
 
 
 /* Initialization code for SDL */
 /* Initialization code for SDL */
@@ -45,6 +53,34 @@ extern int SDL_HelperWindowDestroy(void);
 #endif
 #endif
 
 
 
 
+/* This is not declared in any header, although it is shared between some
+    parts of SDL, because we don't want anything calling it without an
+    extremely good reason. */
+extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
+SDL_NORETURN void SDL_ExitProcess(const int exitcode)
+{
+#ifdef __WIN32__
+    /* "if you do not know the state of all threads in your process, it is
+       better to call TerminateProcess than ExitProcess"
+       https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */
+    TerminateProcess(GetCurrentProcess(), exitcode);
+    /* MingW doesn't have TerminateProcess marked as noreturn, so add an
+       ExitProcess here that will never be reached but make MingW happy. */
+    ExitProcess(exitcode);
+#elif defined(__EMSCRIPTEN__)
+    emscripten_cancel_main_loop();  /* this should "kill" the app. */
+    emscripten_force_exit(exitcode);  /* this should "kill" the app. */
+    exit(exitcode);
+#elif defined(__HAIKU__)  /* Haiku has _Exit, but it's not marked noreturn. */
+    _exit(exitcode);
+#elif defined(HAVE__EXIT) /* Upper case _Exit() */
+    _Exit(exitcode);
+#else
+    _exit(exitcode);
+#endif
+}
+
+
 /* The initialized subsystems */
 /* The initialized subsystems */
 #ifdef SDL_MAIN_NEEDED
 #ifdef SDL_MAIN_NEEDED
 static SDL_bool SDL_MainIsReady = SDL_FALSE;
 static SDL_bool SDL_MainIsReady = SDL_FALSE;

+ 12 - 29
sdl.mod/SDL/src/SDL_assert.c

@@ -36,12 +36,9 @@
 #ifndef WS_OVERLAPPEDWINDOW
 #ifndef WS_OVERLAPPEDWINDOW
 #define WS_OVERLAPPEDWINDOW 0
 #define WS_OVERLAPPEDWINDOW 0
 #endif
 #endif
-#else  /* fprintf, _exit(), etc. */
+#else  /* fprintf, etc. */
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
-#if ! defined(__WINRT__)
-#include <unistd.h>
-#endif
 #endif
 #endif
 
 
 #if defined(__EMSCRIPTEN__)
 #if defined(__EMSCRIPTEN__)
@@ -120,35 +117,21 @@ static void SDL_GenerateAssertionReport(void)
 }
 }
 
 
 
 
+/* This is not declared in any header, although it is shared between some
+    parts of SDL, because we don't want anything calling it without an
+    extremely good reason. */
 #if defined(__WATCOMC__)
 #if defined(__WATCOMC__)
+extern void SDL_ExitProcess(int exitcode);
 #pragma aux SDL_ExitProcess aborts;
 #pragma aux SDL_ExitProcess aborts;
 #endif
 #endif
-static void SDL_ExitProcess(int exitcode)
-{
-#ifdef __WIN32__
-    /* "if you do not know the state of all threads in your process, it is
-       better to call TerminateProcess than ExitProcess"
-       https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */
-    TerminateProcess(GetCurrentProcess(), exitcode);
-
-#elif defined(__EMSCRIPTEN__)
-    emscripten_cancel_main_loop();  /* this should "kill" the app. */
-    emscripten_force_exit(exitcode);  /* this should "kill" the app. */
-    exit(exitcode);
-#else
-#ifdef HAVE__EXIT /* Upper case _Exit() */
-    _Exit(exitcode);
-#else
-    _exit(exitcode);
-#endif
-#endif
-}
+extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
 
 
 
 
 #if defined(__WATCOMC__)
 #if defined(__WATCOMC__)
+static void SDL_AbortAssertion (void);
 #pragma aux SDL_AbortAssertion aborts;
 #pragma aux SDL_AbortAssertion aborts;
 #endif
 #endif
-static void SDL_AbortAssertion(void)
+static SDL_NORETURN void SDL_AbortAssertion(void)
 {
 {
     SDL_Quit();
     SDL_Quit();
     SDL_ExitProcess(42);
     SDL_ExitProcess(42);
@@ -374,10 +357,6 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
 
 
     switch (state)
     switch (state)
     {
     {
-        case SDL_ASSERTION_ABORT:
-            SDL_AbortAssertion();
-            return SDL_ASSERTION_IGNORE;  /* shouldn't return, but oh well. */
-
         case SDL_ASSERTION_ALWAYS_IGNORE:
         case SDL_ASSERTION_ALWAYS_IGNORE:
             state = SDL_ASSERTION_IGNORE;
             state = SDL_ASSERTION_IGNORE;
             data->always_ignore = 1;
             data->always_ignore = 1;
@@ -387,6 +366,10 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
         case SDL_ASSERTION_RETRY:
         case SDL_ASSERTION_RETRY:
         case SDL_ASSERTION_BREAK:
         case SDL_ASSERTION_BREAK:
             break;  /* macro handles these. */
             break;  /* macro handles these. */
+
+        case SDL_ASSERTION_ABORT:
+            SDL_AbortAssertion();
+            /*break;  ...shouldn't return, but oh well. */
     }
     }
 
 
     assertion_running--;
     assertion_running--;

+ 0 - 10
sdl.mod/SDL/src/SDL_error.c

@@ -26,16 +26,6 @@
 #include "SDL_error.h"
 #include "SDL_error.h"
 #include "SDL_error_c.h"
 #include "SDL_error_c.h"
 
 
-
-/* Routine to get the thread-specific error variable */
-#if SDL_THREADS_DISABLED
-/* The default (non-thread-safe) global error variable */
-static SDL_error SDL_global_error;
-#define SDL_GetErrBuf() (&SDL_global_error)
-#else
-extern SDL_error *SDL_GetErrBuf(void);
-#endif /* SDL_THREADS_DISABLED */
-
 #define SDL_ERRBUFIZE   1024
 #define SDL_ERRBUFIZE   1024
 
 
 /* Private functions */
 /* Private functions */

+ 2 - 2
sdl.mod/SDL/src/SDL_log.c

@@ -400,8 +400,8 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
         __android_log_write(SDL_android_priority[priority], tag, message);
         __android_log_write(SDL_android_priority[priority], tag, message);
     }
     }
-#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
-    /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
+#elif defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))
+    /* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now.
     */
     */
     extern void SDL_NSLog(const char *text);
     extern void SDL_NSLog(const char *text);
     {
     {

+ 4 - 0
sdl.mod/SDL/src/atomic/SDL_atomic.c

@@ -289,6 +289,10 @@ SDL_AtomicGetPtr(void **a)
 #endif
 #endif
 }
 }
 
 
+#ifdef SDL_MEMORY_BARRIER_USES_FUNCTION
+#error This file should be built in arm mode so the mcr instruction is available for memory barriers
+#endif
+
 void
 void
 SDL_MemoryBarrierReleaseFunction(void)
 SDL_MemoryBarrierReleaseFunction(void)
 {
 {

+ 12 - 14
sdl.mod/SDL/src/audio/SDL_audio.c

@@ -248,12 +248,6 @@ SDL_AudioPlayDevice_Default(_THIS)
 {                               /* no-op. */
 {                               /* no-op. */
 }
 }
 
 
-static int
-SDL_AudioGetPendingBytes_Default(_THIS)
-{
-    return 0;
-}
-
 static Uint8 *
 static Uint8 *
 SDL_AudioGetDeviceBuf_Default(_THIS)
 SDL_AudioGetDeviceBuf_Default(_THIS)
 {
 {
@@ -361,7 +355,6 @@ finish_audio_entry_points_init(void)
     FILL_STUB(BeginLoopIteration);
     FILL_STUB(BeginLoopIteration);
     FILL_STUB(WaitDevice);
     FILL_STUB(WaitDevice);
     FILL_STUB(PlayDevice);
     FILL_STUB(PlayDevice);
-    FILL_STUB(GetPendingBytes);
     FILL_STUB(GetDeviceBuf);
     FILL_STUB(GetDeviceBuf);
     FILL_STUB(CaptureFromDevice);
     FILL_STUB(CaptureFromDevice);
     FILL_STUB(FlushCapture);
     FILL_STUB(FlushCapture);
@@ -654,11 +647,9 @@ SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
     }
     }
 
 
     /* Nothing to do unless we're set up for queueing. */
     /* Nothing to do unless we're set up for queueing. */
-    if (device->callbackspec.callback == SDL_BufferQueueDrainCallback) {
-        current_audio.impl.LockDevice(device);
-        retval = ((Uint32) SDL_CountDataQueue(device->buffer_queue)) + current_audio.impl.GetPendingBytes(device);
-        current_audio.impl.UnlockDevice(device);
-    } else if (device->callbackspec.callback == SDL_BufferQueueFillCallback) {
+    if (device->callbackspec.callback == SDL_BufferQueueDrainCallback ||
+        device->callbackspec.callback == SDL_BufferQueueFillCallback)
+    {
         current_audio.impl.LockDevice(device);
         current_audio.impl.LockDevice(device);
         retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
         retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
         current_audio.impl.UnlockDevice(device);
         current_audio.impl.UnlockDevice(device);
@@ -957,7 +948,7 @@ SDL_AudioInit(const char *driver_name)
     }
     }
 
 
     SDL_zero(current_audio);
     SDL_zero(current_audio);
-    SDL_zero(open_devices);
+    SDL_zeroa(open_devices);
 
 
     /* Select the proper audio driver */
     /* Select the proper audio driver */
     if (driver_name == NULL) {
     if (driver_name == NULL) {
@@ -1617,7 +1608,7 @@ SDL_AudioQuit(void)
     SDL_DestroyMutex(current_audio.detectionLock);
     SDL_DestroyMutex(current_audio.detectionLock);
 
 
     SDL_zero(current_audio);
     SDL_zero(current_audio);
-    SDL_zero(open_devices);
+    SDL_zeroa(open_devices);
 
 
 #ifdef HAVE_LIBSAMPLERATE_H
 #ifdef HAVE_LIBSAMPLERATE_H
     UnloadLibSampleRate();
     UnloadLibSampleRate();
@@ -1678,8 +1669,15 @@ SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
 {
 {
     switch (spec->format) {
     switch (spec->format) {
     case AUDIO_U8:
     case AUDIO_U8:
+
+    // !!! FIXME: 0x80 isn't perfect for U16, but we can't fit 0x8000 in a
+    // !!! FIXME:  byte for memset() use. This is actually 0.1953 percent off
+    //  from silence. Maybe just don't use U16.
+    case AUDIO_U16LSB:
+    case AUDIO_U16MSB:
         spec->silence = 0x80;
         spec->silence = 0x80;
         break;
         break;
+
     default:
     default:
         spec->silence = 0x00;
         spec->silence = 0x00;
         break;
         break;

+ 16 - 6
sdl.mod/SDL/src/audio/SDL_audiocvt.c

@@ -718,9 +718,15 @@ SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format
     /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
     /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
     float *dst = (float *) (cvt->buf + srclen);
     float *dst = (float *) (cvt->buf + srclen);
     const int dstlen = (cvt->len * cvt->len_mult) - srclen;
     const int dstlen = (cvt->len * cvt->len_mult) - srclen;
-    const int paddingsamples = (ResamplerPadding(inrate, outrate) * chans);
+    const int requestedpadding = ResamplerPadding(inrate, outrate);
+    int paddingsamples;
     float *padding;
     float *padding;
 
 
+    if (requestedpadding < SDL_MAX_SINT32 / chans) {
+        paddingsamples = requestedpadding * chans;
+    } else {
+        paddingsamples = 0;
+    }
     SDL_assert(format == AUDIO_F32SYS);
     SDL_assert(format == AUDIO_F32SYS);
 
 
     /* we keep no streaming state here, so pad with silence on both ends. */
     /* we keep no streaming state here, so pad with silence on both ends. */
@@ -889,10 +895,14 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
         return SDL_SetError("Invalid source channels");
         return SDL_SetError("Invalid source channels");
     } else if (!SDL_SupportedChannelCount(dst_channels)) {
     } else if (!SDL_SupportedChannelCount(dst_channels)) {
         return SDL_SetError("Invalid destination channels");
         return SDL_SetError("Invalid destination channels");
-    } else if (src_rate == 0) {
-        return SDL_SetError("Source rate is zero");
-    } else if (dst_rate == 0) {
-        return SDL_SetError("Destination rate is zero");
+    } else if (src_rate <= 0) {
+        return SDL_SetError("Source rate is equal to or less than zero");
+    } else if (dst_rate <= 0) {
+        return SDL_SetError("Destination rate is equal to or less than zero");
+    } else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
+        return SDL_SetError("Source rate is too high");
+    } else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
+        return SDL_SetError("Destination rate is too high");
     }
     }
 
 
 #if DEBUG_CONVERT
 #if DEBUG_CONVERT
@@ -905,7 +915,7 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
     cvt->dst_format = dst_fmt;
     cvt->dst_format = dst_fmt;
     cvt->needed = 0;
     cvt->needed = 0;
     cvt->filter_index = 0;
     cvt->filter_index = 0;
-    SDL_zero(cvt->filters);
+    SDL_zeroa(cvt->filters);
     cvt->len_mult = 1;
     cvt->len_mult = 1;
     cvt->len_ratio = 1.0;
     cvt->len_ratio = 1.0;
     cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
     cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);

+ 21 - 22
sdl.mod/SDL/src/audio/SDL_audiotypecvt.c

@@ -25,8 +25,7 @@
 #include "SDL_cpuinfo.h"
 #include "SDL_cpuinfo.h"
 #include "SDL_assert.h"
 #include "SDL_assert.h"
 
 
-/* !!! FIXME: disabled until we fix https://bugzilla.libsdl.org/show_bug.cgi?id=4186 */
-#if 0 /*def __ARM_NEON */
+#ifdef __ARM_NEON
 #define HAVE_NEON_INTRINSICS 1
 #define HAVE_NEON_INTRINSICS 1
 #endif
 #endif
 
 
@@ -483,7 +482,7 @@ SDL_Convert_U16_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
     if ((((size_t) src) & 15) == 0) {
     if ((((size_t) src) & 15) == 0) {
         /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
         /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
         const __m128 divby32768 = _mm_set1_ps(DIVBY32768);
         const __m128 divby32768 = _mm_set1_ps(DIVBY32768);
-        const __m128 minus1 = _mm_set1_ps(1.0f);
+        const __m128 minus1 = _mm_set1_ps(-1.0f);
         while (i >= 8) {   /* 8 * 16-bit */
         while (i >= 8) {   /* 8 * 16-bit */
             const __m128i ints = _mm_load_si128((__m128i const *) src);  /* get 8 sint16 into an XMM register. */
             const __m128i ints = _mm_load_si128((__m128i const *) src);  /* get 8 sint16 into an XMM register. */
             /* treat as int32, shift left to clear every other sint16, then back right with zero-extend. Now sint32. */
             /* treat as int32, shift left to clear every other sint16, then back right with zero-extend. Now sint32. */
@@ -526,9 +525,9 @@ SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
     }
     }
 
 
     SDL_assert(!i || ((((size_t) dst) & 15) == 0));
     SDL_assert(!i || ((((size_t) dst) & 15) == 0));
-    SDL_assert(!i || ((((size_t) src) & 15) == 0));
 
 
-    {
+    /* Make sure src is aligned too. */
+    if ((((size_t) src) & 15) == 0) {
         /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
         /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
         const __m128 divby8388607 = _mm_set1_ps(DIVBY8388607);
         const __m128 divby8388607 = _mm_set1_ps(DIVBY8388607);
         const __m128i *mmsrc = (const __m128i *) src;
         const __m128i *mmsrc = (const __m128i *) src;
@@ -615,7 +614,7 @@ static void SDLCALL
 SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
 SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
 {
 {
     const float *src = (const float *) cvt->buf;
     const float *src = (const float *) cvt->buf;
-    Uint8 *dst = (Uint8 *) cvt->buf;
+    Uint8 *dst = cvt->buf;
     int i;
     int i;
 
 
     LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U8 (using SSE2)");
     LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U8 (using SSE2)");
@@ -880,10 +879,10 @@ SDL_Convert_S8_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
             const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes));  /* convert top 8 bytes to 8 int16 */
             const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes));  /* convert top 8 bytes to 8 int16 */
             const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes));   /* convert bottom 8 bytes to 8 int16 */
             const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes));   /* convert bottom 8 bytes to 8 int16 */
             /* split int16 to two int32, then convert to float, then multiply to normalize, store. */
             /* split int16 to two int32, then convert to float, then multiply to normalize, store. */
-            vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16hi))), divby128));
-            vst1q_f32(dst+4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128));
-            vst1q_f32(dst+8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128));
-            vst1q_f32(dst+12, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128));
+            vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128));
+            vst1q_f32(dst+4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128));
+            vst1q_f32(dst+8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128));
+            vst1q_f32(dst+12, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16hi))), divby128));
             i -= 16; mmsrc -= 16; dst -= 16;
             i -= 16; mmsrc -= 16; dst -= 16;
         }
         }
 
 
@@ -926,16 +925,16 @@ SDL_Convert_U8_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
         /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
         /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
         const uint8_t *mmsrc = (const uint8_t *) src;
         const uint8_t *mmsrc = (const uint8_t *) src;
         const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
         const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
-        const float32x4_t one = vdupq_n_f32(1.0f);
+        const float32x4_t negone = vdupq_n_f32(-1.0f);
         while (i >= 16) {   /* 16 * 8-bit */
         while (i >= 16) {   /* 16 * 8-bit */
             const uint8x16_t bytes = vld1q_u8(mmsrc);  /* get 16 uint8 into a NEON register. */
             const uint8x16_t bytes = vld1q_u8(mmsrc);  /* get 16 uint8 into a NEON register. */
             const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes));  /* convert top 8 bytes to 8 uint16 */
             const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes));  /* convert top 8 bytes to 8 uint16 */
             const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes));   /* convert bottom 8 bytes to 8 uint16 */
             const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes));   /* convert bottom 8 bytes to 8 uint16 */
             /* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */
             /* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */
-            vst1q_f32(dst, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128, one));
-            vst1q_f32(dst+4, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128, one));
-            vst1q_f32(dst+8, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128, one));
-            vst1q_f32(dst+12, vmlsq_f32(vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128, one));
+            vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128));
+            vst1q_f32(dst+4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128));
+            vst1q_f32(dst+8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128));
+            vst1q_f32(dst+12, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128));
             i -= 16; mmsrc -= 16; dst -= 16;
             i -= 16; mmsrc -= 16; dst -= 16;
         }
         }
 
 
@@ -1021,12 +1020,12 @@ SDL_Convert_U16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
     if ((((size_t) src) & 15) == 0) {
     if ((((size_t) src) & 15) == 0) {
         /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
         /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
         const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
         const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
-        const float32x4_t one = vdupq_n_f32(1.0f);
+        const float32x4_t negone = vdupq_n_f32(-1.0f);
         while (i >= 8) {   /* 8 * 16-bit */
         while (i >= 8) {   /* 8 * 16-bit */
             const uint16x8_t uints = vld1q_u16((uint16_t const *) src);  /* get 8 uint16 into a NEON register. */
             const uint16x8_t uints = vld1q_u16((uint16_t const *) src);  /* get 8 uint16 into a NEON register. */
             /* split uint16 to two int32, then convert to float, then multiply to normalize, subtract for sign, store. */
             /* split uint16 to two int32, then convert to float, then multiply to normalize, subtract for sign, store. */
-            vst1q_f32(dst, vmlsq_f32(one, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uints))), divby32768));
-            vst1q_f32(dst+4, vmlsq_f32(one, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uints))), divby32768));
+            vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uints))), divby32768));
+            vst1q_f32(dst+4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uints))), divby32768));
             i -= 8; src -= 8; dst -= 8;
             i -= 8; src -= 8; dst -= 8;
         }
         }
     }
     }
@@ -1060,9 +1059,9 @@ SDL_Convert_S32_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
     }
     }
 
 
     SDL_assert(!i || ((((size_t) dst) & 15) == 0));
     SDL_assert(!i || ((((size_t) dst) & 15) == 0));
-    SDL_assert(!i || ((((size_t) src) & 15) == 0));
 
 
-    {
+    /* Make sure src is aligned too. */
+    if ((((size_t) src) & 15) == 0) {
         /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
         /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
         const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607);
         const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607);
         const int32_t *mmsrc = (const int32_t *) src;
         const int32_t *mmsrc = (const int32_t *) src;
@@ -1341,7 +1340,7 @@ SDL_Convert_F32_to_S32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
         if (sample >= 1.0f) {
         if (sample >= 1.0f) {
             *dst = 2147483647;
             *dst = 2147483647;
         } else if (sample <= -1.0f) {
         } else if (sample <= -1.0f) {
-            *dst = -2147483648;
+            *dst = (-2147483647) - 1;
         } else {
         } else {
             *dst = ((Sint32)(sample * 8388607.0f)) << 8;
             *dst = ((Sint32)(sample * 8388607.0f)) << 8;
         }
         }
@@ -1369,7 +1368,7 @@ SDL_Convert_F32_to_S32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
         if (sample >= 1.0f) {
         if (sample >= 1.0f) {
             *dst = 2147483647;
             *dst = 2147483647;
         } else if (sample <= -1.0f) {
         } else if (sample <= -1.0f) {
-            *dst = -2147483648;
+            *dst = (-2147483647) - 1;
         } else {
         } else {
             *dst = ((Sint32)(sample * 8388607.0f)) << 8;
             *dst = ((Sint32)(sample * 8388607.0f)) << 8;
         }
         }

+ 0 - 1
sdl.mod/SDL/src/audio/SDL_sysaudio.h

@@ -71,7 +71,6 @@ typedef struct SDL_AudioDriverImpl
     void (*BeginLoopIteration)(_THIS);  /* Called by audio thread at top of loop */
     void (*BeginLoopIteration)(_THIS);  /* Called by audio thread at top of loop */
     void (*WaitDevice) (_THIS);
     void (*WaitDevice) (_THIS);
     void (*PlayDevice) (_THIS);
     void (*PlayDevice) (_THIS);
-    int (*GetPendingBytes) (_THIS);
     Uint8 *(*GetDeviceBuf) (_THIS);
     Uint8 *(*GetDeviceBuf) (_THIS);
     int (*CaptureFromDevice) (_THIS, void *buffer, int buflen);
     int (*CaptureFromDevice) (_THIS, void *buffer, int buflen);
     void (*FlushCapture) (_THIS);
     void (*FlushCapture) (_THIS);

+ 2024 - 565
sdl.mod/SDL/src/audio/SDL_wave.c

@@ -20,675 +20,2134 @@
 */
 */
 #include "../SDL_internal.h"
 #include "../SDL_internal.h"
 
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+#ifndef INT_MAX
+/* Make a lucky guess. */
+#define INT_MAX SDL_MAX_SINT32
+#endif
+#endif
+
 /* Microsoft WAVE file loading routines */
 /* Microsoft WAVE file loading routines */
 
 
-#include "SDL_audio.h"
-#include "SDL_wave.h"
+#include "SDL_log.h"
+#include "SDL_hints.h"
+#include "SDL_audio.h"
+#include "SDL_wave.h"
+
+/* Reads the value stored at the location of the f1 pointer, multiplies it
+ * with the second argument and then stores the result to f1.
+ * Returns 0 on success, or -1 if the multiplication overflows, in which case f1
+ * does not get modified.
+ */
+static int
+SafeMult(size_t *f1, size_t f2)
+{
+    if (*f1 > 0 && SIZE_MAX / *f1 <= f2) {
+        return -1;
+    }
+    *f1 *= f2;
+    return 0;
+}
+
+typedef struct ADPCM_DecoderState
+{
+    Uint32 channels;        /* Number of channels. */
+    size_t blocksize;       /* Size of an ADPCM block in bytes. */
+    size_t blockheadersize; /* Size of an ADPCM block header in bytes. */
+    size_t samplesperblock; /* Number of samples per channel in an ADPCM block. */
+    size_t framesize;       /* Size of a sample frame (16-bit PCM) in bytes. */
+    Sint64 framestotal;     /* Total number of sample frames. */
+    Sint64 framesleft;      /* Number of sample frames still to be decoded. */
+    void *ddata;            /* Decoder data from initialization. */
+    void *cstate;           /* Decoding state for each channel. */
+
+    /* ADPCM data. */
+    struct {
+        Uint8 *data;
+        size_t size;
+        size_t pos;
+    } input;
+
+    /* Current ADPCM block in the ADPCM data above. */
+    struct {
+        Uint8 *data;
+        size_t size;
+        size_t pos;
+    } block;
+
+    /* Decoded 16-bit PCM data. */
+    struct {
+        Sint16 *data;
+        size_t size;
+        size_t pos;
+    } output;
+} ADPCM_DecoderState;
+
+typedef struct MS_ADPCM_CoeffData
+{
+    Uint16 coeffcount;
+    Sint16 *coeff;
+    Sint16 aligndummy; /* Has to be last member. */
+} MS_ADPCM_CoeffData;
+
+typedef struct MS_ADPCM_ChannelState
+{
+    Uint16 delta;
+    Sint16 coeff1;
+    Sint16 coeff2;
+} MS_ADPCM_ChannelState;
+
+#ifdef SDL_WAVE_DEBUG_LOG_FORMAT
+static void
+WaveDebugLogFormat(WaveFile *file)
+{
+    WaveFormat *format = &file->format;
+    const char *fmtstr = "WAVE file: %s, %u Hz, %s, %u bits, %u %s/s";
+    const char *waveformat, *wavechannel, *wavebpsunit = "B";
+    Uint32 wavebps = format->byterate;
+    char channelstr[64];
+
+    SDL_zeroa(channelstr);
+
+    switch (format->encoding) {
+    case PCM_CODE:
+        waveformat = "PCM";
+        break;
+    case IEEE_FLOAT_CODE:
+        waveformat = "IEEE Float";
+        break;
+    case ALAW_CODE:
+        waveformat = "A-law";
+        break;
+    case MULAW_CODE:
+        waveformat = "\xc2\xb5-law";
+        break;
+    case MS_ADPCM_CODE:
+        waveformat = "MS ADPCM";
+        break;
+    case IMA_ADPCM_CODE:
+        waveformat = "IMA ADPCM";
+        break;
+    default:
+        waveformat = "Unknown";
+        break;
+    }
+
+#define SDL_WAVE_DEBUG_CHANNELCFG(STR, CODE) case CODE: wavechannel = STR; break;
+#define SDL_WAVE_DEBUG_CHANNELSTR(STR, CODE) if (format->channelmask & CODE) { \
+    SDL_strlcat(channelstr, channelstr[0] ? "-" STR : STR, sizeof(channelstr));}
+
+    if (format->formattag == EXTENSIBLE_CODE && format->channelmask > 0) {
+        switch (format->channelmask) {
+            SDL_WAVE_DEBUG_CHANNELCFG("1.0 Mono",         0x4)
+            SDL_WAVE_DEBUG_CHANNELCFG("1.1 Mono",         0xc)
+            SDL_WAVE_DEBUG_CHANNELCFG("2.0 Stereo",       0x3)
+            SDL_WAVE_DEBUG_CHANNELCFG("2.1 Stereo",       0xb)
+            SDL_WAVE_DEBUG_CHANNELCFG("3.0 Stereo",       0x7)
+            SDL_WAVE_DEBUG_CHANNELCFG("3.1 Stereo",       0xf)
+            SDL_WAVE_DEBUG_CHANNELCFG("3.0 Surround",     0x103)
+            SDL_WAVE_DEBUG_CHANNELCFG("3.1 Surround",     0x10b)
+            SDL_WAVE_DEBUG_CHANNELCFG("4.0 Quad",         0x33)
+            SDL_WAVE_DEBUG_CHANNELCFG("4.1 Quad",         0x3b)
+            SDL_WAVE_DEBUG_CHANNELCFG("4.0 Surround",     0x107)
+            SDL_WAVE_DEBUG_CHANNELCFG("4.1 Surround",     0x10f)
+            SDL_WAVE_DEBUG_CHANNELCFG("5.0",              0x37)
+            SDL_WAVE_DEBUG_CHANNELCFG("5.1",              0x3f)
+            SDL_WAVE_DEBUG_CHANNELCFG("5.0 Side",         0x607)
+            SDL_WAVE_DEBUG_CHANNELCFG("5.1 Side",         0x60f)
+            SDL_WAVE_DEBUG_CHANNELCFG("6.0",              0x137)
+            SDL_WAVE_DEBUG_CHANNELCFG("6.1",              0x13f)
+            SDL_WAVE_DEBUG_CHANNELCFG("6.0 Side",         0x707)
+            SDL_WAVE_DEBUG_CHANNELCFG("6.1 Side",         0x70f)
+            SDL_WAVE_DEBUG_CHANNELCFG("7.0",              0xf7)
+            SDL_WAVE_DEBUG_CHANNELCFG("7.1",              0xff)
+            SDL_WAVE_DEBUG_CHANNELCFG("7.0 Side",         0x6c7)
+            SDL_WAVE_DEBUG_CHANNELCFG("7.1 Side",         0x6cf)
+            SDL_WAVE_DEBUG_CHANNELCFG("7.0 Surround",     0x637)
+            SDL_WAVE_DEBUG_CHANNELCFG("7.1 Surround",     0x63f)
+            SDL_WAVE_DEBUG_CHANNELCFG("9.0 Surround",     0x5637)
+            SDL_WAVE_DEBUG_CHANNELCFG("9.1 Surround",     0x563f)
+            SDL_WAVE_DEBUG_CHANNELCFG("11.0 Surround",    0x56f7)
+            SDL_WAVE_DEBUG_CHANNELCFG("11.1 Surround",    0x56ff)
+        default:
+            SDL_WAVE_DEBUG_CHANNELSTR("FL",  0x1)
+            SDL_WAVE_DEBUG_CHANNELSTR("FR",  0x2)
+            SDL_WAVE_DEBUG_CHANNELSTR("FC",  0x4)
+            SDL_WAVE_DEBUG_CHANNELSTR("LF",  0x8)
+            SDL_WAVE_DEBUG_CHANNELSTR("BL",  0x10)
+            SDL_WAVE_DEBUG_CHANNELSTR("BR",  0x20)
+            SDL_WAVE_DEBUG_CHANNELSTR("FLC", 0x40)
+            SDL_WAVE_DEBUG_CHANNELSTR("FRC", 0x80)
+            SDL_WAVE_DEBUG_CHANNELSTR("BC",  0x100)
+            SDL_WAVE_DEBUG_CHANNELSTR("SL",  0x200)
+            SDL_WAVE_DEBUG_CHANNELSTR("SR",  0x400)
+            SDL_WAVE_DEBUG_CHANNELSTR("TC",  0x800)
+            SDL_WAVE_DEBUG_CHANNELSTR("TFL", 0x1000)
+            SDL_WAVE_DEBUG_CHANNELSTR("TFC", 0x2000)
+            SDL_WAVE_DEBUG_CHANNELSTR("TFR", 0x4000)
+            SDL_WAVE_DEBUG_CHANNELSTR("TBL", 0x8000)
+            SDL_WAVE_DEBUG_CHANNELSTR("TBC", 0x10000)
+            SDL_WAVE_DEBUG_CHANNELSTR("TBR", 0x20000)
+            break;
+        }
+    } else {
+        switch (format->channels) {
+        default:
+            if (SDL_snprintf(channelstr, sizeof(channelstr), "%u channels", format->channels) >= 0) {
+                wavechannel = channelstr;
+                break;
+            }
+        case 0:
+            wavechannel = "Unknown";
+            break;
+        case 1:
+            wavechannel = "Mono";
+            break;
+        case 2:
+            wavechannel = "Setero";
+            break;
+        }
+    }
+
+#undef SDL_WAVE_DEBUG_CHANNELCFG
+#undef SDL_WAVE_DEBUG_CHANNELSTR
+
+    if (wavebps >= 1024) {
+        wavebpsunit = "KiB";
+        wavebps = wavebps / 1024 + (wavebps & 0x3ff ? 1 : 0);
+    }
+
+    SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, fmtstr, waveformat, format->frequency, wavechannel, format->bitspersample, wavebps, wavebpsunit);
+}
+#endif
+
+#ifdef SDL_WAVE_DEBUG_DUMP_FORMAT
+static void
+WaveDebugDumpFormat(WaveFile *file, Uint32 rifflen, Uint32 fmtlen, Uint32 datalen)
+{
+    WaveFormat *format = &file->format;
+    const char *fmtstr1 = "WAVE chunk dump:\n"
+        "-------------------------------------------\n"
+        "RIFF                            %11u\n"
+        "-------------------------------------------\n"
+        "    fmt                         %11u\n"
+        "        wFormatTag                   0x%04x\n"
+        "        nChannels               %11u\n"
+        "        nSamplesPerSec          %11u\n"
+        "        nAvgBytesPerSec         %11u\n"
+        "        nBlockAlign             %11u\n";
+    const char *fmtstr2 = "        wBitsPerSample          %11u\n";
+    const char *fmtstr3 = "        cbSize                  %11u\n";
+    const char *fmtstr4a = "        wValidBitsPerSample     %11u\n";
+    const char *fmtstr4b = "        wSamplesPerBlock        %11u\n";
+    const char *fmtstr5 = "        dwChannelMask            0x%08x\n"
+        "        SubFormat\n"
+        "        %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x\n";
+    const char *fmtstr6 = "-------------------------------------------\n"
+        " fact\n"
+        "  dwSampleLength                %11u\n";
+    const char *fmtstr7 = "-------------------------------------------\n"
+        " data                           %11u\n"
+        "-------------------------------------------\n";
+    char *dumpstr;
+    size_t dumppos = 0;
+    const size_t bufsize = 1024;
+    int res;
+
+    dumpstr = SDL_malloc(bufsize);
+    if (dumpstr == NULL) {
+        return;
+    }
+    dumpstr[0] = 0;
+
+    res = SDL_snprintf(dumpstr, bufsize, fmtstr1, rifflen, fmtlen, format->formattag, format->channels, format->frequency, format->byterate, format->blockalign);
+    dumppos += res > 0 ? res : 0;
+    if (fmtlen >= 16) {
+        res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr2, format->bitspersample);
+        dumppos += res > 0 ? res : 0;
+    }
+    if (fmtlen >= 18) {
+        res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr3, format->extsize);
+        dumppos += res > 0 ? res : 0;
+    }
+    if (format->formattag == EXTENSIBLE_CODE && fmtlen >= 40 && format->extsize >= 22) {
+        const Uint8 *g = format->subformat;
+        const Uint32 g1 = g[0] | ((Uint32)g[1] << 8) | ((Uint32)g[2] << 16) | ((Uint32)g[3] << 24);
+        const Uint32 g2 = g[4] | ((Uint32)g[5] << 8);
+        const Uint32 g3 = g[6] | ((Uint32)g[7] << 8);
+
+        switch (format->encoding) {
+        default:
+            res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr4a, format->validsamplebits);
+            dumppos += res > 0 ? res : 0;
+            break;
+        case MS_ADPCM_CODE:
+        case IMA_ADPCM_CODE:
+            res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr4b, format->samplesperblock);
+            dumppos += res > 0 ? res : 0;
+            break;
+        }
+        res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr5, format->channelmask, g1, g2, g3, g[8], g[9], g[10], g[11], g[12], g[13], g[14], g[15]);
+        dumppos += res > 0 ? res : 0;
+    } else {
+        switch (format->encoding) {
+        case MS_ADPCM_CODE:
+        case IMA_ADPCM_CODE:
+            if (fmtlen >= 20 && format->extsize >= 2) {
+                res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr4b, format->samplesperblock);
+                dumppos += res > 0 ? res : 0;
+            }
+            break;
+        }
+    }
+    if (file->fact.status >= 1) {
+        res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr6, file->fact.samplelength);
+        dumppos += res > 0 ? res : 0;
+    }
+    res = SDL_snprintf(dumpstr + dumppos, bufsize - dumppos, fmtstr7, datalen);
+    dumppos += res > 0 ? res : 0;
+
+    SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "%s", dumpstr);
+
+    free(dumpstr);
+}
+#endif
+
+static Sint64
+WaveAdjustToFactValue(WaveFile *file, Sint64 sampleframes)
+{
+    if (file->fact.status == 2) {
+        if (file->facthint == FactStrict && sampleframes < file->fact.samplelength) {
+            return SDL_SetError("Invalid number of sample frames in WAVE fact chunk (too many)");
+        } else if (sampleframes > file->fact.samplelength) {
+            return file->fact.samplelength;
+        }
+    }
+
+    return sampleframes;
+}
+
+static int
+MS_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength)
+{
+    WaveFormat *format = &file->format;
+    const size_t blockheadersize = (size_t)file->format.channels * 7;
+    const size_t availableblocks = datalength / file->format.blockalign;
+    const size_t blockframebitsize = (size_t)file->format.bitspersample * file->format.channels;
+    const size_t trailingdata = datalength % file->format.blockalign;
+
+    if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
+        /* The size of the data chunk must be a multiple of the block size. */
+        if (datalength < blockheadersize || trailingdata > 0) {
+            return SDL_SetError("Truncated MS ADPCM block");
+        }
+    }
+
+    /* Calculate number of sample frames that will be decoded. */
+    file->sampleframes = (Sint64)availableblocks * format->samplesperblock;
+    if (trailingdata > 0) {
+        /* The last block is truncated. Check if we can get any samples out of it. */
+        if (file->trunchint == TruncDropFrame) {
+            /* Drop incomplete sample frame. */
+            if (trailingdata >= blockheadersize) {
+                size_t trailingsamples = 2 + (trailingdata - blockheadersize) * 8 / blockframebitsize;
+                if (trailingsamples > format->samplesperblock) {
+                    trailingsamples = format->samplesperblock;
+                }
+                file->sampleframes += trailingsamples;
+            }
+        }
+    }
+
+    file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes);
+    if (file->sampleframes < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+MS_ADPCM_Init(WaveFile *file, size_t datalength)
+{
+    WaveFormat *format = &file->format;
+    WaveChunk *chunk = &file->chunk;
+    const size_t blockheadersize = (size_t)format->channels * 7;
+    const size_t blockdatasize = (size_t)format->blockalign - blockheadersize;
+    const size_t blockframebitsize = (size_t)format->bitspersample * format->channels;
+    const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize;
+    const Sint16 presetcoeffs[14] = {256, 0, 512, -256, 0, 0, 192, 64, 240, 0, 460, -208, 392, -232};
+    size_t i, coeffcount;
+    MS_ADPCM_CoeffData *coeffdata;
+
+    /* Sanity checks. */
+
+    /* While it's clear how IMA ADPCM handles more than two channels, the nibble
+     * order of MS ADPCM makes it awkward. The Standards Update does not talk
+     * about supporting more than stereo anyway.
+     */
+    if (format->channels > 2) {
+        return SDL_SetError("Invalid number of channels");
+    }
+
+    if (format->bitspersample != 4) {
+        return SDL_SetError("Invalid MS ADPCM bits per sample of %u", (unsigned int)format->bitspersample);
+    }
+
+    /* The block size must be big enough to contain the block header. */
+    if (format->blockalign < blockheadersize) {
+        return SDL_SetError("Invalid MS ADPCM block size (nBlockAlign)");
+    }
+
+    if (format->formattag == EXTENSIBLE_CODE) {
+        /* Does have a GUID (like all format tags), but there's no specification
+         * for how the data is packed into the extensible header. Making
+         * assumptions here could lead to new formats nobody wants to support.
+         */
+        return SDL_SetError("MS ADPCM with the extensible header is not supported");
+    }
+
+    /* There are wSamplesPerBlock, wNumCoef, and at least 7 coefficient pairs in
+     * the extended part of the header.
+     */
+    if (chunk->size < 22) {
+        return SDL_SetError("Could not read MS ADPCM format header");
+    }
+
+    format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8);
+    /* Number of coefficient pairs. A pair has two 16-bit integers. */
+    coeffcount = chunk->data[20] | ((size_t)chunk->data[21] << 8);
+    /* bPredictor, the integer offset into the coefficients array, is only
+     * 8 bits. It can only address the first 256 coefficients. Let's limit
+     * the count number here.
+     */
+    if (coeffcount > 256) {
+        coeffcount = 256;
+    }
+
+    if (chunk->size < 22 + coeffcount * 4) {
+        return SDL_SetError("Could not read custom coefficients in MS ADPCM format header");
+    } else if (format->extsize < 4 + coeffcount * 4) {
+        return SDL_SetError("Invalid MS ADPCM format header (too small)");
+    } else if (coeffcount < 7) {
+        return SDL_SetError("Missing required coefficients in MS ADPCM format header");
+    }
+
+    coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4);
+    file->decoderdata = coeffdata; /* Freed in cleanup. */
+    if (coeffdata == NULL) {
+        return SDL_OutOfMemory();
+    }
+    coeffdata->coeff = &coeffdata->aligndummy;
+    coeffdata->coeffcount = (Uint16)coeffcount;
+
+    /* Copy the 16-bit pairs. */
+    for (i = 0; i < coeffcount * 2; i++) {
+        Sint32 c = chunk->data[22 + i * 2] | ((Sint32)chunk->data[23 + i * 2] << 8);
+        if (c >= 0x8000) {
+            c -= 0x10000;
+        }
+        if (i < 14 && c != presetcoeffs[i]) {
+            return SDL_SetError("Wrong preset coefficients in MS ADPCM format header");
+        }
+        coeffdata->coeff[i] = (Sint16)c;
+    }
+
+    /* Technically, wSamplesPerBlock is required, but we have all the
+     * information in the other fields to calculate it, if it's zero.
+     */
+    if (format->samplesperblock == 0) {
+        /* Let's be nice to the encoders that didn't know how to fill this.
+         * The Standards Update calculates it this way:
+         *
+         *   x = Block size (in bits) minus header size (in bits)
+         *   y = Bit depth multiplied by channel count
+         *   z = Number of samples per channel in block header
+         *   wSamplesPerBlock = x / y + z
+         */
+        format->samplesperblock = (Uint32)blockdatasamples + 2;
+    }
+
+    /* nBlockAlign can be in conflict with wSamplesPerBlock. For example, if
+     * the number of samples doesn't fit into the block. The Standards Update
+     * also describes wSamplesPerBlock with a formula that makes it necessary to
+     * always fill the block with the maximum amount of samples, but this is not
+     * enforced here as there are no compatibility issues.
+     * A truncated block header with just one sample is not supported.
+     */
+    if (format->samplesperblock == 1 || blockdatasamples < format->samplesperblock - 2) {
+        return SDL_SetError("Invalid number of samples per MS ADPCM block (wSamplesPerBlock)");
+    }
+
+    if (MS_ADPCM_CalculateSampleFrames(file, datalength) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static Sint16
+MS_ADPCM_ProcessNibble(MS_ADPCM_ChannelState *cstate, Sint32 sample1, Sint32 sample2, Uint8 nybble)
+{
+    const Sint32 max_audioval = 32767;
+    const Sint32 min_audioval = -32768;
+    const Uint16 max_deltaval = 65535;
+    const Uint16 adaptive[] = {
+        230, 230, 230, 230, 307, 409, 512, 614,
+        768, 614, 512, 409, 307, 230, 230, 230
+    };
+    Sint32 new_sample;
+    Sint32 errordelta;
+    Uint32 delta = cstate->delta;
+
+    new_sample = (sample1 * cstate->coeff1 + sample2 * cstate->coeff2) / 256;
+    /* The nibble is a signed 4-bit error delta. */
+    errordelta = (Sint32)nybble - (nybble >= 0x08 ? 0x10 : 0);
+    new_sample += (Sint32)delta * errordelta;
+    if (new_sample < min_audioval) {
+        new_sample = min_audioval;
+    } else if (new_sample > max_audioval) {
+        new_sample = max_audioval;
+    }
+    delta = (delta * adaptive[nybble]) / 256;
+    if (delta < 16) {
+        delta = 16;
+    } else if (delta > max_deltaval) {
+        /* This issue is not described in the Standards Update and therefore
+         * undefined. It seems sensible to prevent overflows with a limit.
+         */
+        delta = max_deltaval;
+    }
+
+    cstate->delta = (Uint16)delta;
+    return (Sint16)new_sample;
+}
+
+static int
+MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state)
+{
+    Uint8 coeffindex;
+    const Uint32 channels = state->channels;
+    Sint32 sample;
+    Uint32 c;
+    MS_ADPCM_ChannelState *cstate = (MS_ADPCM_ChannelState *)state->cstate;
+    MS_ADPCM_CoeffData *ddata = (MS_ADPCM_CoeffData *)state->ddata;
+
+    for (c = 0; c < channels; c++) {
+        size_t o = c;
+
+        /* Load the coefficient pair into the channel state. */
+        coeffindex = state->block.data[o];
+        if (coeffindex > ddata->coeffcount) {
+            return SDL_SetError("Invalid MS ADPCM coefficient index in block header");
+        }
+        cstate[c].coeff1 = ddata->coeff[coeffindex * 2];
+        cstate[c].coeff2 = ddata->coeff[coeffindex * 2 + 1];
+
+        /* Initial delta value. */
+        o = channels + c * 2;
+        cstate[c].delta = state->block.data[o] | ((Uint16)state->block.data[o + 1] << 8);
+
+        /* Load the samples from the header. Interestingly, the sample later in
+         * the output stream comes first.
+         */
+        o = channels * 3 + c * 2;
+        sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
+        if (sample >= 0x8000) {
+            sample -= 0x10000;
+        }
+        state->output.data[state->output.pos + channels] = (Sint16)sample;
+
+        o = channels * 5 + c * 2;
+        sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
+        if (sample >= 0x8000) {
+            sample -= 0x10000;
+        }
+        state->output.data[state->output.pos] = (Sint16)sample;
+
+        state->output.pos++;
+    }
+
+    state->block.pos += state->blockheadersize;
+
+    /* Skip second sample frame that came from the header. */
+    state->output.pos += state->channels;
+
+    /* Header provided two sample frames. */
+    state->framesleft -= 2;
+
+    return 0;
+}
+
+/* Decodes the data of the MS ADPCM block. Decoding will stop if a block is too
+ * short, returning with none or partially decoded data. The partial data
+ * will always contain full sample frames (same sample count for each channel).
+ * Incomplete sample frames are discarded.
+ */
+static int
+MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state)
+{
+    Uint16 nybble = 0;
+    Sint16 sample1, sample2;
+    const Uint32 channels = state->channels;
+    Uint32 c;
+    MS_ADPCM_ChannelState *cstate = (MS_ADPCM_ChannelState *)state->cstate;
+
+    size_t blockpos = state->block.pos;
+    size_t blocksize = state->block.size;
+
+    size_t outpos = state->output.pos;
+
+    Sint64 blockframesleft = state->samplesperblock - 2;
+    if (blockframesleft > state->framesleft) {
+        blockframesleft = state->framesleft;
+    }
+
+    while (blockframesleft > 0) {
+        for (c = 0; c < channels; c++) {
+            if (nybble & 0x4000) {
+                nybble <<= 4;
+            } else if (blockpos < blocksize) {
+                nybble = state->block.data[blockpos++] | 0x4000;
+            } else {
+                /* Out of input data. Drop the incomplete frame and return. */
+                state->output.pos = outpos - c;
+                return -1;
+            }
+
+            /* Load previous samples which may come from the block header. */
+            sample1 = state->output.data[outpos - channels];
+            sample2 = state->output.data[outpos - channels * 2];
+
+            sample1 = MS_ADPCM_ProcessNibble(cstate + c, sample1, sample2, (nybble >> 4) & 0x0f);
+            state->output.data[outpos++] = sample1;
+        }
+
+        state->framesleft--;
+        blockframesleft--;
+    }
+
+    state->output.pos = outpos;
+
+    return 0;
+}
+
+static int
+MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
+{
+    int result;
+    size_t bytesleft, outputsize;
+    WaveChunk *chunk = &file->chunk;
+    ADPCM_DecoderState state;
+    MS_ADPCM_ChannelState cstate[2];
+
+    SDL_zero(state);
+    SDL_zeroa(cstate);
+
+    if (chunk->size != chunk->length) {
+        /* Could not read everything. Recalculate number of sample frames. */
+        if (MS_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) {
+            return -1;
+        }
+    }
+
+    /* Nothing to decode, nothing to return. */
+    if (file->sampleframes == 0) {
+        *audio_buf = NULL;
+        *audio_len = 0;
+        return 0;
+    }
+
+    state.blocksize = file->format.blockalign;
+    state.channels = file->format.channels;
+    state.blockheadersize = (size_t)state.channels * 7;
+    state.samplesperblock = file->format.samplesperblock;
+    state.framesize = state.channels * sizeof(Sint16);
+    state.ddata = file->decoderdata;
+    state.framestotal = file->sampleframes;
+    state.framesleft = state.framestotal;
+
+    state.input.data = chunk->data;
+    state.input.size = chunk->size;
+    state.input.pos = 0;
+
+    /* The output size in bytes. May get modified if data is truncated. */
+    outputsize = (size_t)state.framestotal;
+    if (SafeMult(&outputsize, state.framesize)) {
+        return SDL_OutOfMemory();
+    } else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
+        return SDL_SetError("WAVE file too big");
+    }
+
+    state.output.pos = 0;
+    state.output.size = outputsize / sizeof(Sint16);
+    state.output.data = (Sint16 *)SDL_malloc(outputsize);
+    if (state.output.data == NULL) {
+        return SDL_OutOfMemory();
+    }
+
+    state.cstate = cstate;
+
+    /* Decode block by block. A truncated block will stop the decoding. */
+    bytesleft = state.input.size - state.input.pos;
+    while (state.framesleft > 0 && bytesleft >= state.blockheadersize) {
+        state.block.data = state.input.data + state.input.pos;
+        state.block.size = bytesleft < state.blocksize ? bytesleft : state.blocksize;
+        state.block.pos = 0;
+
+        if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) {
+            /* Somehow didn't allocate enough space for the output. */
+            SDL_free(state.output.data);
+            return SDL_SetError("Unexpected overflow in MS ADPCM decoder");
+        }
+
+        /* Initialize decoder with the values from the block header. */
+        result = MS_ADPCM_DecodeBlockHeader(&state);
+        if (result == -1) {
+            SDL_free(state.output.data);
+            return -1;
+        }
+
+        /* Decode the block data. It stores the samples directly in the output. */
+        result = MS_ADPCM_DecodeBlockData(&state);
+        if (result == -1) {
+            /* Unexpected end. Stop decoding and return partial data if necessary. */
+            if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
+                SDL_free(state.output.data);
+                return SDL_SetError("Truncated data chunk");
+            } else if (file->trunchint != TruncDropFrame) {
+                state.output.pos -= state.output.pos % (state.samplesperblock * state.channels);
+            }
+            outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */
+            break;
+        }
+
+        state.input.pos += state.block.size;
+        bytesleft = state.input.size - state.input.pos;
+    }
+
+    *audio_buf = (Uint8 *)state.output.data;
+    *audio_len = (Uint32)outputsize;
+
+    return 0;
+}
+
+static int
+IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength)
+{
+    WaveFormat *format = &file->format;
+    const size_t blockheadersize = (size_t)format->channels * 4;
+    const size_t subblockframesize = (size_t)format->channels * 4;
+    const size_t availableblocks = datalength / format->blockalign;
+    const size_t trailingdata = datalength % format->blockalign;
+
+    if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
+        /* The size of the data chunk must be a multiple of the block size. */
+        if (datalength < blockheadersize || trailingdata > 0) {
+            return SDL_SetError("Truncated IMA ADPCM block");
+        }
+    }
+
+    /* Calculate number of sample frames that will be decoded. */
+    file->sampleframes = (Uint64)availableblocks * format->samplesperblock;
+    if (trailingdata > 0) {
+        /* The last block is truncated. Check if we can get any samples out of it. */
+        if (file->trunchint == TruncDropFrame && trailingdata > blockheadersize - 2) {
+            /* The sample frame in the header of the truncated block is present.
+             * Drop incomplete sample frames.
+             */
+            size_t trailingsamples = 1;
+
+            if (trailingdata > blockheadersize) {
+                /* More data following after the header. */
+                const size_t trailingblockdata = trailingdata - blockheadersize;
+                const size_t trailingsubblockdata = trailingblockdata % subblockframesize;
+                trailingsamples += (trailingblockdata / subblockframesize) * 8;
+                /* Due to the interleaved sub-blocks, the last 4 bytes determine
+                 * how many samples of the truncated sub-block are lost.
+                 */
+                if (trailingsubblockdata > subblockframesize - 4) {
+                    trailingsamples += (trailingsubblockdata % 4) * 2;
+                }
+            }
+
+            if (trailingsamples > format->samplesperblock) {
+                trailingsamples = format->samplesperblock;
+            }
+            file->sampleframes += trailingsamples;
+        }
+    }
+
+    file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes);
+    if (file->sampleframes < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+IMA_ADPCM_Init(WaveFile *file, size_t datalength)
+{
+    WaveFormat *format = &file->format;
+    WaveChunk *chunk = &file->chunk;
+    const size_t blockheadersize = (size_t)format->channels * 4;
+    const size_t blockdatasize = (size_t)format->blockalign - blockheadersize;
+    const size_t blockframebitsize = (size_t)format->bitspersample * format->channels;
+    const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize;
+
+    /* Sanity checks. */
+
+    /* IMA ADPCM can also have 3-bit samples, but it's not supported by SDL at this time. */
+    if (format->bitspersample == 3) {
+        return SDL_SetError("3-bit IMA ADPCM currently not supported");
+    } else if (format->bitspersample != 4) {
+        return SDL_SetError("Invalid IMA ADPCM bits per sample of %u", (unsigned int)format->bitspersample);
+    }
+
+    /* The block size is required to be a multiple of 4 and it must be able to
+     * hold a block header.
+     */
+    if (format->blockalign < blockheadersize || format->blockalign % 4) {
+        return SDL_SetError("Invalid IMA ADPCM block size (nBlockAlign)");
+    }
+
+    if (format->formattag == EXTENSIBLE_CODE) {
+        /* There's no specification for this, but it's basically the same
+         * format because the extensible header has wSampePerBlocks too.
+         */
+    } else  {
+        /* The Standards Update says there 'should' be 2 bytes for wSamplesPerBlock. */
+        if (chunk->size >= 20 && format->extsize >= 2) {
+            format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8);
+        }
+    }
+
+    if (format->samplesperblock == 0) {
+        /* Field zero? No problem. We just assume the encoder packed the block.
+         * The specification calculates it this way:
+         *
+         *   x = Block size (in bits) minus header size (in bits)
+         *   y = Bit depth multiplied by channel count
+         *   z = Number of samples per channel in header
+         *   wSamplesPerBlock = x / y + z
+         */
+        format->samplesperblock = (Uint32)blockdatasamples + 1;
+    }
+
+    /* nBlockAlign can be in conflict with wSamplesPerBlock. For example, if
+     * the number of samples doesn't fit into the block. The Standards Update
+     * also describes wSamplesPerBlock with a formula that makes it necessary
+     * to always fill the block with the maximum amount of samples, but this is
+     * not enforced here as there are no compatibility issues.
+     */
+    if (blockdatasamples < format->samplesperblock - 1) {
+        return SDL_SetError("Invalid number of samples per IMA ADPCM block (wSamplesPerBlock)");
+    }
+
+    if (IMA_ADPCM_CalculateSampleFrames(file, datalength) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static Sint16
+IMA_ADPCM_ProcessNibble(Sint8 *cindex, Sint16 lastsample, Uint8 nybble)
+{
+    const Sint32 max_audioval = 32767;
+    const Sint32 min_audioval = -32768;
+    const Sint8 index_table_4b[16] = {
+        -1, -1, -1, -1,
+        2, 4, 6, 8,
+        -1, -1, -1, -1,
+        2, 4, 6, 8
+    };
+    const Uint16 step_table[89] = {
+        7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
+        34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
+        143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
+        449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
+        1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
+        3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
+        9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
+        22385, 24623, 27086, 29794, 32767
+    };
+    Uint32 step;
+    Sint32 sample, delta;
+    Sint8 index = *cindex;
+
+    /* Clamp index into valid range. */
+    if (index > 88) {
+        index = 88;
+    } else if (index < 0) {
+        index = 0;
+    }
+
+    /* explicit cast to avoid gcc warning about using 'char' as array index */
+    step = step_table[(size_t)index];
+
+    /* Update index value */
+    *cindex = index + index_table_4b[nybble];
+
+    /* This calculation uses shifts and additions because multiplications were
+     * much slower back then. Sadly, this can't just be replaced with an actual
+     * multiplication now as the old algorithm drops some bits. The closest
+     * approximation I could find is something like this:
+     * (nybble & 0x8 ? -1 : 1) * ((nybble & 0x7) * step / 4 + step / 8)
+     */
+    delta = step >> 3;
+    if (nybble & 0x04)
+        delta += step;
+    if (nybble & 0x02)
+        delta += step >> 1;
+    if (nybble & 0x01)
+        delta += step >> 2;
+    if (nybble & 0x08)
+        delta = -delta;
+
+    sample = lastsample + delta;
+
+    /* Clamp output sample */
+    if (sample > max_audioval) {
+        sample = max_audioval;
+    } else if (sample < min_audioval) {
+        sample = min_audioval;
+    }
+
+    return (Sint16)sample;
+}
+
+static int
+IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state)
+{
+    Sint16 step;
+    Uint32 c;
+    Uint8 *cstate = state->cstate;
+
+    for (c = 0; c < state->channels; c++) {
+        size_t o = state->block.pos + c * 4;
+
+        /* Extract the sample from the header. */
+        Sint32 sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
+        if (sample >= 0x8000) {
+            sample -= 0x10000;
+        }
+        state->output.data[state->output.pos++] = (Sint16)sample;
+
+        /* Channel step index. */
+        step = (Sint16)state->block.data[o + 2];
+        cstate[c] = (Sint8)(step > 0x80 ? step - 0x100 : step);
+
+        /* Reserved byte in block header, should be 0. */
+        if (state->block.data[o + 3] != 0) {
+            /* Uh oh, corrupt data?  Buggy code? */ ;
+        }
+    }
+
+    state->block.pos += state->blockheadersize;
+
+    /* Header provided one sample frame. */
+    state->framesleft--;
+
+    return 0;
+}
+
+/* Decodes the data of the IMA ADPCM block. Decoding will stop if a block is too
+ * short, returning with none or partially decoded data. The partial data always
+ * contains full sample frames (same sample count for each channel).
+ * Incomplete sample frames are discarded.
+ */
+static int
+IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state)
+{
+    size_t i;
+    int retval = 0;
+    const Uint32 channels = state->channels;
+    const size_t subblockframesize = channels * 4;
+    Uint64 bytesrequired;
+    Uint32 c;
+
+    size_t blockpos = state->block.pos;
+    size_t blocksize = state->block.size;
+    size_t blockleft = blocksize - blockpos;
+
+    size_t outpos = state->output.pos;
+
+    Sint64 blockframesleft = state->samplesperblock - 1;
+    if (blockframesleft > state->framesleft) {
+        blockframesleft = state->framesleft;
+    }
+
+    bytesrequired = (blockframesleft + 7) / 8 * subblockframesize;
+    if (blockleft < bytesrequired) {
+        /* Data truncated. Calculate how many samples we can get out if it. */
+        const size_t guaranteedframes = blockleft / subblockframesize;
+        const size_t remainingbytes = blockleft % subblockframesize;
+        blockframesleft = guaranteedframes;
+        if (remainingbytes > subblockframesize - 4) {
+            blockframesleft += (remainingbytes % 4) * 2;
+        }
+        /* Signal the truncation. */
+        retval = -1;
+    }
+
+    /* Each channel has their nibbles packed into 32-bit blocks. These blocks
+     * are interleaved and make up the data part of the ADPCM block. This loop
+     * decodes the samples as they come from the input data and puts them at
+     * the appropriate places in the output data.
+     */
+    while (blockframesleft > 0) {
+        const size_t subblocksamples = blockframesleft < 8 ? (size_t)blockframesleft : 8;
+
+        for (c = 0; c < channels; c++) {
+            Uint8 nybble = 0;
+            /* Load previous sample which may come from the block header. */
+            Sint16 sample = state->output.data[outpos + c - channels];
+
+            for (i = 0; i < subblocksamples; i++) {
+                if (i & 1) {
+                    nybble >>= 4;
+                } else {
+                    nybble = state->block.data[blockpos++];
+                }
+
+                sample = IMA_ADPCM_ProcessNibble((Sint8 *)state->cstate + c, sample, nybble & 0x0f);
+                state->output.data[outpos + c + i * channels] = sample;
+            }
+        }
+
+        outpos += channels * subblocksamples;
+        state->framesleft -= subblocksamples;
+        blockframesleft -= subblocksamples;
+    }
+
+    state->block.pos = blockpos;
+    state->output.pos = outpos;
+
+    return retval;
+}
+
+static int
+IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
+{
+    int result;
+    size_t bytesleft, outputsize;
+    WaveChunk *chunk = &file->chunk;
+    ADPCM_DecoderState state;
+    Sint8 *cstate;
+
+    if (chunk->size != chunk->length) {
+        /* Could not read everything. Recalculate number of sample frames. */
+        if (IMA_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) {
+            return -1;
+        }
+    }
+
+    /* Nothing to decode, nothing to return. */
+    if (file->sampleframes == 0) {
+        *audio_buf = NULL;
+        *audio_len = 0;
+        return 0;
+    }
+
+    SDL_zero(state);
+    state.channels = file->format.channels;
+    state.blocksize = file->format.blockalign;
+    state.blockheadersize = (size_t)state.channels * 4;
+    state.samplesperblock = file->format.samplesperblock;
+    state.framesize = state.channels * sizeof(Sint16);
+    state.framestotal = file->sampleframes;
+    state.framesleft = state.framestotal;
+
+    state.input.data = chunk->data;
+    state.input.size = chunk->size;
+    state.input.pos = 0;
+
+    /* The output size in bytes. May get modified if data is truncated. */
+    outputsize = (size_t)state.framestotal;
+    if (SafeMult(&outputsize, state.framesize)) {
+        return SDL_OutOfMemory();
+    } else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
+        return SDL_SetError("WAVE file too big");
+    }
+
+    state.output.pos = 0;
+    state.output.size = outputsize / sizeof(Sint16);
+    state.output.data = (Sint16 *)SDL_malloc(outputsize);
+    if (state.output.data == NULL) {
+        return SDL_OutOfMemory();
+    }
+
+    cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8));
+    if (cstate == NULL) {
+        SDL_free(state.output.data);
+        return SDL_OutOfMemory();
+    }
+    state.cstate = cstate;
+
+    /* Decode block by block. A truncated block will stop the decoding. */
+    bytesleft = state.input.size - state.input.pos;
+    while (state.framesleft > 0 && bytesleft >= state.blockheadersize) {
+        state.block.data = state.input.data + state.input.pos;
+        state.block.size = bytesleft < state.blocksize ? bytesleft : state.blocksize;
+        state.block.pos = 0;
+
+        if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) {
+            /* Somehow didn't allocate enough space for the output. */
+            SDL_free(state.output.data);
+            SDL_free(cstate);
+            return SDL_SetError("Unexpected overflow in IMA ADPCM decoder");
+        }
+
+        /* Initialize decoder with the values from the block header. */
+        result = IMA_ADPCM_DecodeBlockHeader(&state);
+        if (result == 0) {
+            /* Decode the block data. It stores the samples directly in the output. */
+            result = IMA_ADPCM_DecodeBlockData(&state);
+        }
+
+        if (result == -1) {
+            /* Unexpected end. Stop decoding and return partial data if necessary. */
+            if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
+                SDL_free(state.output.data);
+                SDL_free(cstate);
+                return SDL_SetError("Truncated data chunk");
+            } else if (file->trunchint != TruncDropFrame) {
+                state.output.pos -= state.output.pos % (state.samplesperblock * state.channels);
+            }
+            outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */
+            break;
+        }
+
+        state.input.pos += state.block.size;
+        bytesleft = state.input.size - state.input.pos;
+    }
+
+    *audio_buf = (Uint8 *)state.output.data;
+    *audio_len = (Uint32)outputsize;
+
+    SDL_free(cstate);
+
+    return 0;
+}
+
+static int
+LAW_Init(WaveFile *file, size_t datalength)
+{
+    WaveFormat *format = &file->format;
+
+    /* Standards Update requires this to be 8. */
+    if (format->bitspersample != 8) {
+        return SDL_SetError("Invalid companded bits per sample of %u", (unsigned int)format->bitspersample);
+    }
+
+    /* Not going to bother with weird padding. */
+    if (format->blockalign != format->channels) {
+        return SDL_SetError("Unsupported block alignment");
+    }
+
+    if ((file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict)) {
+        if (format->blockalign > 1 && datalength % format->blockalign) {
+            return SDL_SetError("Truncated data chunk in WAVE file");
+        }
+    }
+
+    file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign);
+    if (file->sampleframes < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
+{
+#ifdef SDL_WAVE_LAW_LUT
+    const Sint16 alaw_lut[256] = {
+        -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752,
+        -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016,
+        -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008,
+        -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344,
+        -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88,
+        -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376,
+        -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688,
+        -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504,
+        5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752,
+        2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016,
+        20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008,
+        10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344,
+        328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88,
+        72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376,
+        1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688,
+        656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848
+    };
+    const Sint16 mulaw_lut[256] = {
+        -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996,
+        -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932,
+        -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900,
+        -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884,
+        -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876,
+        -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372,
+        -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120,
+        -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124,
+        31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996,
+        15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932,
+        7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900,
+        3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884,
+        1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876,
+        844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372,
+        356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120,
+        112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0
+    };
+#endif
+
+    WaveFormat *format = &file->format;
+    WaveChunk *chunk = &file->chunk;
+    size_t i, sample_count, expanded_len;
+    Uint8 *src;
+    Sint16 *dst;
+
+    if (chunk->length != chunk->size) {
+        file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign);
+        if (file->sampleframes < 0) {
+            return -1;
+        }
+    }
+
+    /* Nothing to decode, nothing to return. */
+    if (file->sampleframes == 0) {
+        *audio_buf = NULL;
+        *audio_len = 0;
+        return 0;
+    }
+
+    sample_count = (size_t)file->sampleframes;
+    if (SafeMult(&sample_count, format->channels)) {
+        return SDL_OutOfMemory();
+    }
+
+    expanded_len = sample_count;
+    if (SafeMult(&expanded_len, sizeof(Sint16))) {
+        return SDL_OutOfMemory();
+    } else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
+        return SDL_SetError("WAVE file too big");
+    }
+
+    /* 1 to avoid allocating zero bytes, to keep static analysis happy. */
+    src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
+    if (src == NULL) {
+        return SDL_OutOfMemory();
+    }
+    chunk->data = NULL;
+    chunk->size = 0;
+
+    dst = (Sint16 *)src;
+
+    /* Work backwards, since we're expanding in-place. SDL_AudioSpec.format will
+     * inform the caller about the byte order.
+     */
+    i = sample_count;
+    switch (file->format.encoding) {
+#ifdef SDL_WAVE_LAW_LUT
+    case ALAW_CODE:
+        while (i--) {
+            dst[i] = alaw_lut[src[i]];
+        }
+        break;
+    case MULAW_CODE:
+        while (i--) {
+            dst[i] = mulaw_lut[src[i]];
+        }
+        break;
+#else
+    case ALAW_CODE:
+        while (i--) {
+            Uint8 nibble = src[i];
+            Uint8 exponent = (nibble & 0x7f) ^ 0x55;
+            Sint16 mantissa = exponent & 0xf;
+
+            exponent >>= 4;
+            if (exponent > 0) {
+                mantissa |= 0x10;
+            }
+            mantissa = (mantissa << 4) | 0x8;
+            if (exponent > 1) {
+                mantissa <<= exponent - 1;
+            }
+
+            dst[i] = nibble & 0x80 ? mantissa : -mantissa;
+        }
+        break;
+    case MULAW_CODE:
+        while (i--) {
+            Uint8 nibble = ~src[i];
+            Sint16 mantissa = nibble & 0xf;
+            Uint8 exponent = (nibble >> 4) & 0x7;
+            Sint16 step = 4 << (exponent + 1);
+
+            mantissa = (0x80 << exponent) + step * mantissa + step / 2 - 132;
+
+            dst[i] = nibble & 0x80 ? -mantissa : mantissa;
+        }
+        break;
+#endif
+    default:
+        SDL_free(src);
+        return SDL_SetError("Unknown companded encoding");
+    }
+
+    *audio_buf = src;
+    *audio_len = (Uint32)expanded_len;
+
+    return 0;
+}
+
+static int
+PCM_Init(WaveFile *file, size_t datalength)
+{
+    WaveFormat *format = &file->format;
+
+    if (format->encoding == PCM_CODE) {
+        switch (format->bitspersample) {
+        case 8:
+        case 16:
+        case 24:
+        case 32:
+            /* These are supported. */
+            break;
+        default:
+            return SDL_SetError("%u-bit PCM format not supported", (unsigned int)format->bitspersample);
+        }
+    } else if (format->encoding == IEEE_FLOAT_CODE) {
+        if (format->bitspersample != 32) {
+            return SDL_SetError("%u-bit IEEE floating-point format not supported", (unsigned int)format->bitspersample);
+        }
+    }
+
+    /* It wouldn't be that hard to support more exotic block sizes, but
+     * the most common formats should do for now.
+     */
+    if (format->blockalign * 8 != format->channels * format->bitspersample) {
+        return SDL_SetError("Unsupported block alignment");
+    }
+
+    if ((file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict)) {
+        if (format->blockalign > 1 && datalength % format->blockalign) {
+            return SDL_SetError("Truncated data chunk in WAVE file");
+        }
+    }
+
+    file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign);
+    if (file->sampleframes < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
+{
+    WaveFormat *format = &file->format;
+    WaveChunk *chunk = &file->chunk;
+    size_t i, expanded_len, sample_count;
+    Uint8 *ptr;
+
+    sample_count = (size_t)file->sampleframes;
+    if (SafeMult(&sample_count, format->channels)) {
+        return SDL_OutOfMemory();
+    }
+
+    expanded_len = sample_count;
+    if (SafeMult(&expanded_len, sizeof(Sint32))) {
+        return SDL_OutOfMemory();
+    } else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
+        return SDL_SetError("WAVE file too big");
+    }
+
+    /* 1 to avoid allocating zero bytes, to keep static analysis happy. */
+    ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
+    if (ptr == NULL) {
+        return SDL_OutOfMemory();
+    }
+
+    /* This pointer is now invalid. */
+    chunk->data = NULL;
+    chunk->size = 0;
+
+    *audio_buf = ptr;
+    *audio_len = (Uint32)expanded_len;
+
+    /* work from end to start, since we're expanding in-place. */
+    for (i = sample_count; i > 0; i--) {
+        const size_t o = i - 1;
+        uint8_t b[4];
+
+        b[0] = 0;
+        b[1] = ptr[o * 3];
+        b[2] = ptr[o * 3 + 1];
+        b[3] = ptr[o * 3 + 2];
+
+        ptr[o * 4 + 0] = b[0];
+        ptr[o * 4 + 1] = b[1];
+        ptr[o * 4 + 2] = b[2];
+        ptr[o * 4 + 3] = b[3];
+    }
+
+    return 0;
+}
+
+static int
+PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
+{
+    WaveFormat *format = &file->format;
+    WaveChunk *chunk = &file->chunk;
+    size_t outputsize;
+
+    if (chunk->length != chunk->size) {
+        file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign);
+        if (file->sampleframes < 0) {
+            return -1;
+        }
+    }
+
+    /* Nothing to decode, nothing to return. */
+    if (file->sampleframes == 0) {
+        *audio_buf = NULL;
+        *audio_len = 0;
+        return 0;
+    }
+
+    /* 24-bit samples get shifted to 32 bits. */
+    if (format->encoding == PCM_CODE && format->bitspersample == 24) {
+        return PCM_ConvertSint24ToSint32(file, audio_buf, audio_len);
+    }
+
+    outputsize = (size_t)file->sampleframes;
+    if (SafeMult(&outputsize, format->blockalign)) {
+        return SDL_OutOfMemory();
+    } else if (outputsize > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
+        return SDL_SetError("WAVE file too big");
+    }
+
+    *audio_buf = chunk->data;
+    *audio_len = (Uint32)outputsize;
+
+    /* This pointer is going to be returned to the caller. Prevent free in cleanup. */
+    chunk->data = NULL;
+    chunk->size = 0;
+
+    return 0;
+}
+
+static WaveRiffSizeHint
+WaveGetRiffSizeHint()
+{
+    const char *hint = SDL_GetHint(SDL_HINT_WAVE_RIFF_CHUNK_SIZE);
+
+    if (hint != NULL) {
+        if (SDL_strcmp(hint, "force") == 0) {
+            return RiffSizeForce;
+        } else if (SDL_strcmp(hint, "ignore") == 0) {
+            return RiffSizeIgnore;
+        } else if (SDL_strcmp(hint, "ignorezero") == 0) {
+            return RiffSizeIgnoreZero;
+        } else if (SDL_strcmp(hint, "maximum") == 0) {
+            return RiffSizeMaximum;
+        }
+    }
 
 
+    return RiffSizeNoHint;
+}
+
+static WaveTruncationHint
+WaveGetTruncationHint()
+{
+    const char *hint = SDL_GetHint(SDL_HINT_WAVE_TRUNCATION);
+
+    if (hint != NULL) {
+        if (SDL_strcmp(hint, "verystrict") == 0) {
+            return TruncVeryStrict;
+        } else if (SDL_strcmp(hint, "strict") == 0) {
+            return TruncStrict;
+        } else if (SDL_strcmp(hint, "dropframe") == 0) {
+            return TruncDropFrame;
+        } else if (SDL_strcmp(hint, "dropblock") == 0) {
+            return TruncDropBlock;
+        }
+    }
 
 
-static int ReadChunk(SDL_RWops * src, Chunk * chunk);
+    return TruncNoHint;
+}
 
 
-struct MS_ADPCM_decodestate
+static WaveFactChunkHint
+WaveGetFactChunkHint()
 {
 {
-    Uint8 hPredictor;
-    Uint16 iDelta;
-    Sint16 iSamp1;
-    Sint16 iSamp2;
-};
-static struct MS_ADPCM_decoder
+    const char *hint = SDL_GetHint(SDL_HINT_WAVE_FACT_CHUNK);
+
+    if (hint != NULL) {
+        if (SDL_strcmp(hint, "truncate") == 0) {
+            return FactTruncate;
+        } else if (SDL_strcmp(hint, "strict") == 0) {
+            return FactStrict;
+        } else if (SDL_strcmp(hint, "ignorezero") == 0) {
+            return FactIgnoreZero;
+        } else if (SDL_strcmp(hint, "ignore") == 0) {
+            return FactIgnore;
+        }
+    }
+
+    return FactNoHint;
+}
+
+static void
+WaveFreeChunkData(WaveChunk *chunk)
 {
 {
-    WaveFMT wavefmt;
-    Uint16 wSamplesPerBlock;
-    Uint16 wNumCoef;
-    Sint16 aCoeff[7][2];
-    /* * * */
-    struct MS_ADPCM_decodestate state[2];
-} MS_ADPCM_state;
+    if (chunk->data != NULL) {
+        SDL_free(chunk->data);
+        chunk->data = NULL;
+    }
+    chunk->size = 0;
+}
 
 
 static int
 static int
-InitMS_ADPCM(WaveFMT * format)
-{
-    Uint8 *rogue_feel;
-    int i;
-
-    /* Set the rogue pointer to the MS_ADPCM specific data */
-    MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
-    MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
-    MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
-    MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
-    MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
-    MS_ADPCM_state.wavefmt.bitspersample =
-        SDL_SwapLE16(format->bitspersample);
-    rogue_feel = (Uint8 *) format + sizeof(*format);
-    if (sizeof(*format) == 16) {
-        /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
-        rogue_feel += sizeof(Uint16);
-    }
-    MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
-    rogue_feel += sizeof(Uint16);
-    MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
-    rogue_feel += sizeof(Uint16);
-    if (MS_ADPCM_state.wNumCoef != 7) {
-        SDL_SetError("Unknown set of MS_ADPCM coefficients");
-        return (-1);
-    }
-    for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
-        MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
-        rogue_feel += sizeof(Uint16);
-        MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
-        rogue_feel += sizeof(Uint16);
-    }
-    return (0);
-}
-
-static Sint32
-MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state,
-                Uint8 nybble, Sint16 * coeff)
-{
-    const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
-    const Sint32 min_audioval = -(1 << (16 - 1));
-    const Sint32 adaptive[] = {
-        230, 230, 230, 230, 307, 409, 512, 614,
-        768, 614, 512, 409, 307, 230, 230, 230
-    };
-    Sint32 new_sample, delta;
+WaveNextChunk(SDL_RWops *src, WaveChunk *chunk)
+{
+    Uint32 chunkheader[2];
+    Sint64 nextposition = chunk->position + chunk->length;
 
 
-    new_sample = ((state->iSamp1 * coeff[0]) +
-                  (state->iSamp2 * coeff[1])) / 256;
-    if (nybble & 0x08) {
-        new_sample += state->iDelta * (nybble - 0x10);
-    } else {
-        new_sample += state->iDelta * nybble;
+    /* Data is no longer valid after this function returns. */
+    WaveFreeChunkData(chunk);
+
+    /* Error on overflows. */
+    if (SDL_MAX_SINT64 - chunk->length < chunk->position || SDL_MAX_SINT64 - 8 < nextposition) {
+        return -1;
     }
     }
-    if (new_sample < min_audioval) {
-        new_sample = min_audioval;
-    } else if (new_sample > max_audioval) {
-        new_sample = max_audioval;
+
+    /* RIFF chunks have a 2-byte alignment. Skip padding byte. */
+    if (chunk->length & 1) {
+        nextposition++;
     }
     }
-    delta = ((Sint32) state->iDelta * adaptive[nybble]) / 256;
-    if (delta < 16) {
-        delta = 16;
+
+    if (SDL_RWseek(src, nextposition, RW_SEEK_SET) != nextposition) {
+        /* Not sure how we ended up here. Just abort. */
+        return -2;
+    } else if (SDL_RWread(src, chunkheader, 4, 2) != 2) {
+        return -1;
     }
     }
-    state->iDelta = (Uint16) delta;
-    state->iSamp2 = state->iSamp1;
-    state->iSamp1 = (Sint16) new_sample;
-    return (new_sample);
+
+    chunk->fourcc = SDL_SwapLE32(chunkheader[0]);
+    chunk->length = SDL_SwapLE32(chunkheader[1]);
+    chunk->position = nextposition + 8;
+
+    return 0;
 }
 }
 
 
 static int
 static int
-MS_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
-{
-    struct MS_ADPCM_decodestate *state[2];
-    Uint8 *freeable, *encoded, *decoded;
-    Sint32 encoded_len, samplesleft;
-    Sint8 nybble;
-    Uint8 stereo;
-    Sint16 *coeff[2];
-    Sint32 new_sample;
+WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t length)
+{
+    WaveFreeChunkData(chunk);
 
 
-    /* Allocate the proper sized output buffer */
-    encoded_len = *audio_len;
-    encoded = *audio_buf;
-    freeable = *audio_buf;
-    *audio_len = (encoded_len / MS_ADPCM_state.wavefmt.blockalign) *
-        MS_ADPCM_state.wSamplesPerBlock *
-        MS_ADPCM_state.wavefmt.channels * sizeof(Sint16);
-    *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
-    if (*audio_buf == NULL) {
-        return SDL_OutOfMemory();
+    if (length > chunk->length) {
+        length = chunk->length;
+    }
+
+    if (length > 0) {
+        chunk->data = SDL_malloc(length);
+        if (chunk->data == NULL) {
+            return SDL_OutOfMemory();
+        }
+
+        if (SDL_RWseek(src, chunk->position, RW_SEEK_SET) != chunk->position) {
+            /* Not sure how we ended up here. Just abort. */
+            return -2;
+        }
+
+        chunk->size = SDL_RWread(src, chunk->data, 1, length);
+        if (chunk->size != length) {
+            /* Expected to be handled by the caller. */
+        }
     }
     }
-    decoded = *audio_buf;
-
-    /* Get ready... Go! */
-    stereo = (MS_ADPCM_state.wavefmt.channels == 2);
-    state[0] = &MS_ADPCM_state.state[0];
-    state[1] = &MS_ADPCM_state.state[stereo];
-    while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
-        /* Grab the initial information for this block */
-        state[0]->hPredictor = *encoded++;
-        if (stereo) {
-            state[1]->hPredictor = *encoded++;
-        }
-        state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
-        encoded += sizeof(Sint16);
-        if (stereo) {
-            state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
-            encoded += sizeof(Sint16);
-        }
-        state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
-        encoded += sizeof(Sint16);
-        if (stereo) {
-            state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
-            encoded += sizeof(Sint16);
-        }
-        state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
-        encoded += sizeof(Sint16);
-        if (stereo) {
-            state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
-            encoded += sizeof(Sint16);
-        }
-        coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
-        coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
-
-        /* Store the two initial samples we start with */
-        decoded[0] = state[0]->iSamp2 & 0xFF;
-        decoded[1] = state[0]->iSamp2 >> 8;
-        decoded += 2;
-        if (stereo) {
-            decoded[0] = state[1]->iSamp2 & 0xFF;
-            decoded[1] = state[1]->iSamp2 >> 8;
-            decoded += 2;
-        }
-        decoded[0] = state[0]->iSamp1 & 0xFF;
-        decoded[1] = state[0]->iSamp1 >> 8;
-        decoded += 2;
-        if (stereo) {
-            decoded[0] = state[1]->iSamp1 & 0xFF;
-            decoded[1] = state[1]->iSamp1 >> 8;
-            decoded += 2;
-        }
-
-        /* Decode and store the other samples in this block */
-        samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
-            MS_ADPCM_state.wavefmt.channels;
-        while (samplesleft > 0) {
-            nybble = (*encoded) >> 4;
-            new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
-            decoded[0] = new_sample & 0xFF;
-            new_sample >>= 8;
-            decoded[1] = new_sample & 0xFF;
-            decoded += 2;
-
-            nybble = (*encoded) & 0x0F;
-            new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
-            decoded[0] = new_sample & 0xFF;
-            new_sample >>= 8;
-            decoded[1] = new_sample & 0xFF;
-            decoded += 2;
-
-            ++encoded;
-            samplesleft -= 2;
-        }
-        encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
-    }
-    SDL_free(freeable);
-    return (0);
-}
-
-struct IMA_ADPCM_decodestate
+
+    return 0;
+}
+
+static int
+WaveReadChunkData(SDL_RWops *src, WaveChunk *chunk)
 {
 {
-    Sint32 sample;
-    Sint8 index;
+    return WaveReadPartialChunkData(src, chunk, chunk->length);
+}
+
+typedef struct WaveExtensibleGUID {
+    Uint16 encoding;
+    Uint8 guid[16];
+} WaveExtensibleGUID;
+
+/* Some of the GUIDs that are used by WAVEFORMATEXTENSIBLE. */
+#define WAVE_FORMATTAG_GUID(tag) {(tag) & 0xff, (tag) >> 8, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113}
+static WaveExtensibleGUID extensible_guids[] = {
+    {PCM_CODE,        WAVE_FORMATTAG_GUID(PCM_CODE)},
+    {MS_ADPCM_CODE,   WAVE_FORMATTAG_GUID(MS_ADPCM_CODE)},
+    {IEEE_FLOAT_CODE, WAVE_FORMATTAG_GUID(IEEE_FLOAT_CODE)},
+    {ALAW_CODE,       WAVE_FORMATTAG_GUID(ALAW_CODE)},
+    {MULAW_CODE,      WAVE_FORMATTAG_GUID(MULAW_CODE)},
+    {IMA_ADPCM_CODE,  WAVE_FORMATTAG_GUID(IMA_ADPCM_CODE)}
 };
 };
-static struct IMA_ADPCM_decoder
+
+static Uint16
+WaveGetFormatGUIDEncoding(WaveFormat *format)
 {
 {
-    WaveFMT wavefmt;
-    Uint16 wSamplesPerBlock;
-    /* * * */
-    struct IMA_ADPCM_decodestate state[2];
-} IMA_ADPCM_state;
+    size_t i;
+    for (i = 0; i < SDL_arraysize(extensible_guids); i++) {
+        if (SDL_memcmp(format->subformat, extensible_guids[i].guid, 16) == 0) {
+            return extensible_guids[i].encoding;
+        }
+    }
+    return UNKNOWN_CODE;
+}
 
 
 static int
 static int
-InitIMA_ADPCM(WaveFMT * format)
+WaveReadFormat(WaveFile *file)
 {
 {
-    Uint8 *rogue_feel;
+    WaveChunk *chunk = &file->chunk;
+    WaveFormat *format = &file->format;
+    SDL_RWops *fmtsrc;
+    size_t fmtlen = chunk->size;
 
 
-    /* Set the rogue pointer to the IMA_ADPCM specific data */
-    IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
-    IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
-    IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
-    IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
-    IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
-    IMA_ADPCM_state.wavefmt.bitspersample =
-        SDL_SwapLE16(format->bitspersample);
-    rogue_feel = (Uint8 *) format + sizeof(*format);
-    if (sizeof(*format) == 16) {
-        /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
-        rogue_feel += sizeof(Uint16);
+    if (fmtlen > SDL_MAX_SINT32) {
+        /* Limit given by SDL_RWFromConstMem. */
+        return SDL_SetError("Data of WAVE fmt chunk too big");
+    }
+    fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size);
+    if (fmtsrc == NULL) {
+        return SDL_OutOfMemory();
     }
     }
-    IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
-    return (0);
-}
 
 
-static Sint32
-IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
-{
-    const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
-    const Sint32 min_audioval = -(1 << (16 - 1));
-    const int index_table[16] = {
-        -1, -1, -1, -1,
-        2, 4, 6, 8,
-        -1, -1, -1, -1,
-        2, 4, 6, 8
-    };
-    const Sint32 step_table[89] = {
-        7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
-        34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
-        143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
-        449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
-        1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
-        3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
-        9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
-        22385, 24623, 27086, 29794, 32767
-    };
-    Sint32 delta, step;
+    format->formattag = SDL_ReadLE16(fmtsrc);
+    format->encoding = format->formattag;
+    format->channels = SDL_ReadLE16(fmtsrc);
+    format->frequency = SDL_ReadLE32(fmtsrc);
+    format->byterate = SDL_ReadLE32(fmtsrc);
+    format->blockalign = SDL_ReadLE16(fmtsrc);
 
 
-    /* Compute difference and new sample value */
-    if (state->index > 88) {
-        state->index = 88;
-    } else if (state->index < 0) {
-        state->index = 0;
+    /* This is PCM specific in the first version of the specification. */
+    if (fmtlen >= 16) {
+        format->bitspersample = SDL_ReadLE16(fmtsrc);
+    } else if (format->encoding == PCM_CODE) {
+        SDL_RWclose(fmtsrc);
+        return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
     }
     }
-    /* explicit cast to avoid gcc warning about using 'char' as array index */
-    step = step_table[(int)state->index];
-    delta = step >> 3;
-    if (nybble & 0x04)
-        delta += step;
-    if (nybble & 0x02)
-        delta += (step >> 1);
-    if (nybble & 0x01)
-        delta += (step >> 2);
-    if (nybble & 0x08)
-        delta = -delta;
-    state->sample += delta;
 
 
-    /* Update index value */
-    state->index += index_table[nybble];
+    /* The earlier versions also don't have this field. */
+    if (fmtlen >= 18) {
+        format->extsize = SDL_ReadLE16(fmtsrc);
+    }
 
 
-    /* Clamp output sample */
-    if (state->sample > max_audioval) {
-        state->sample = max_audioval;
-    } else if (state->sample < min_audioval) {
-        state->sample = min_audioval;
+    if (format->formattag == EXTENSIBLE_CODE) {
+        /* note that this ignores channel masks, smaller valid bit counts
+         * inside a larger container, and most subtypes. This is just enough
+         * to get things that didn't really _need_ WAVE_FORMAT_EXTENSIBLE
+         * to be useful working when they use this format flag.
+         */
+
+        /* Extensible header must be at least 22 bytes. */
+        if (fmtlen < 40 || format->extsize < 22) {
+            SDL_RWclose(fmtsrc);
+            return SDL_SetError("Extensible WAVE header too small");
+        }
+
+        format->validsamplebits = SDL_ReadLE16(fmtsrc);
+        format->samplesperblock = format->validsamplebits;
+        format->channelmask = SDL_ReadLE32(fmtsrc);
+        SDL_RWread(fmtsrc, format->subformat, 1, 16);
+        format->encoding = WaveGetFormatGUIDEncoding(format);
     }
     }
-    return (state->sample);
+
+    SDL_RWclose(fmtsrc);
+
+    return 0;
 }
 }
 
 
-/* Fill the decode buffer with a channel block of data (8 samples) */
-static void
-Fill_IMA_ADPCM_block(Uint8 * decoded, Uint8 * encoded,
-                     int channel, int numchannels,
-                     struct IMA_ADPCM_decodestate *state)
+static int
+WaveCheckFormat(WaveFile *file, size_t datalength)
 {
 {
-    int i;
-    Sint8 nybble;
-    Sint32 new_sample;
+    WaveFormat *format = &file->format;
 
 
-    decoded += (channel * 2);
-    for (i = 0; i < 4; ++i) {
-        nybble = (*encoded) & 0x0F;
-        new_sample = IMA_ADPCM_nibble(state, nybble);
-        decoded[0] = new_sample & 0xFF;
-        new_sample >>= 8;
-        decoded[1] = new_sample & 0xFF;
-        decoded += 2 * numchannels;
+    /* Check for some obvious issues. */
 
 
-        nybble = (*encoded) >> 4;
-        new_sample = IMA_ADPCM_nibble(state, nybble);
-        decoded[0] = new_sample & 0xFF;
-        new_sample >>= 8;
-        decoded[1] = new_sample & 0xFF;
-        decoded += 2 * numchannels;
+    if (format->channels == 0) {
+        return SDL_SetError("Invalid number of channels");
+    } else if (format->channels > 255) {
+        /* Limit given by SDL_AudioSpec.channels. */
+        return SDL_SetError("Number of channels exceeds limit of 255");
+    }
 
 
-        ++encoded;
+    if (format->frequency == 0) {
+        return SDL_SetError("Invalid sample rate");
+    } else if (format->frequency > INT_MAX) {
+        /* Limit given by SDL_AudioSpec.freq. */
+        return SDL_SetError("Sample rate exceeds limit of %d", INT_MAX);
     }
     }
-}
 
 
-static int
-IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
-{
-    struct IMA_ADPCM_decodestate *state;
-    Uint8 *freeable, *encoded, *decoded;
-    Sint32 encoded_len, samplesleft;
-    unsigned int c, channels;
-
-    /* Check to make sure we have enough variables in the state array */
-    channels = IMA_ADPCM_state.wavefmt.channels;
-    if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
-        SDL_SetError("IMA ADPCM decoder can only handle %u channels",
-                     (unsigned int)SDL_arraysize(IMA_ADPCM_state.state));
-        return (-1);
-    }
-    state = IMA_ADPCM_state.state;
-
-    /* Allocate the proper sized output buffer */
-    encoded_len = *audio_len;
-    encoded = *audio_buf;
-    freeable = *audio_buf;
-    *audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
-        IMA_ADPCM_state.wSamplesPerBlock *
-        IMA_ADPCM_state.wavefmt.channels * sizeof(Sint16);
-    *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
-    if (*audio_buf == NULL) {
-        return SDL_OutOfMemory();
+    /* Reject invalid fact chunks in strict mode. */
+    if (file->facthint == FactStrict && file->fact.status == -1) {
+        return SDL_SetError("Invalid fact chunk in WAVE file");
     }
     }
-    decoded = *audio_buf;
-
-    /* Get ready... Go! */
-    while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
-        /* Grab the initial information for this block */
-        for (c = 0; c < channels; ++c) {
-            /* Fill the state information for this block */
-            state[c].sample = ((encoded[1] << 8) | encoded[0]);
-            encoded += 2;
-            if (state[c].sample & 0x8000) {
-                state[c].sample -= 0x10000;
-            }
-            state[c].index = *encoded++;
-            /* Reserved byte in buffer header, should be 0 */
-            if (*encoded++ != 0) {
-                /* Uh oh, corrupt data?  Buggy code? */ ;
-            }
 
 
-            /* Store the initial sample we start with */
-            decoded[0] = (Uint8) (state[c].sample & 0xFF);
-            decoded[1] = (Uint8) (state[c].sample >> 8);
-            decoded += 2;
+    /* Check for issues common to all encodings. Some unsupported formats set
+     * the bits per sample to zero. These fall through to the 'unsupported
+     * format' error.
+     */
+    switch (format->encoding) {
+    case IEEE_FLOAT_CODE:
+    case ALAW_CODE:
+    case MULAW_CODE:
+    case MS_ADPCM_CODE:
+    case IMA_ADPCM_CODE:
+        /* These formats require a fact chunk. */
+        if (file->facthint == FactStrict && file->fact.status <= 0) {
+            return SDL_SetError("Missing fact chunk in WAVE file");
+        }
+        /* fallthrough */
+    case PCM_CODE:
+        /* All supported formats require a non-zero bit depth. */
+        if (file->chunk.size < 16) {
+            return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
+        } else if (format->bitspersample == 0) {
+            return SDL_SetError("Invalid bits per sample");
+        }
+
+        /* All supported formats must have a proper block size. */
+        if (format->blockalign == 0) {
+            return SDL_SetError("Invalid block alignment");
         }
         }
 
 
-        /* Decode and store the other samples in this block */
-        samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
-        while (samplesleft > 0) {
-            for (c = 0; c < channels; ++c) {
-                Fill_IMA_ADPCM_block(decoded, encoded,
-                                     c, channels, &state[c]);
-                encoded += 4;
-                samplesleft -= 8;
+        /* If the fact chunk is valid and the appropriate hint is set, the
+         * decoders will use the number of sample frames from the fact chunk.
+         */
+        if (file->fact.status == 1) {
+            WaveFactChunkHint hint = file->facthint;
+            Uint32 samples = file->fact.samplelength;
+            if (hint == FactTruncate || hint == FactStrict || (hint == FactIgnoreZero && samples > 0)) {
+                file->fact.status = 2;
             }
             }
-            decoded += (channels * 8 * 2);
         }
         }
-        encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
     }
     }
-    SDL_free(freeable);
-    return (0);
-}
 
 
+    /* Check the format for encoding specific issues and initialize decoders. */
+    switch (format->encoding) {
+    case PCM_CODE:
+    case IEEE_FLOAT_CODE:
+        if (PCM_Init(file, datalength) < 0) {
+            return -1;
+        }
+        break;
+    case ALAW_CODE:
+    case MULAW_CODE:
+        if (LAW_Init(file, datalength) < 0) {
+            return -1;
+        }
+        break;
+    case MS_ADPCM_CODE:
+        if (MS_ADPCM_Init(file, datalength) < 0) {
+            return -1;
+        }
+        break;
+    case IMA_ADPCM_CODE:
+        if (IMA_ADPCM_Init(file, datalength) < 0) {
+            return -1;
+        }
+        break;
+    case MPEG_CODE:
+    case MPEGLAYER3_CODE:
+        return SDL_SetError("MPEG formats not supported");
+    default:
+        if (format->formattag == EXTENSIBLE_CODE) {
+            const char *errstr = "Unknown WAVE format GUID: %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x";
+            const Uint8 *g = format->subformat;
+            const Uint32 g1 = g[0] | ((Uint32)g[1] << 8) | ((Uint32)g[2] << 16) | ((Uint32)g[3] << 24);
+            const Uint32 g2 = g[4] | ((Uint32)g[5] << 8);
+            const Uint32 g3 = g[6] | ((Uint32)g[7] << 8);
+            return SDL_SetError(errstr, g1, g2, g3, g[8], g[9], g[10], g[11], g[12], g[13], g[14], g[15]);
+        }
+        return SDL_SetError("Unknown WAVE format tag: 0x%04x", (unsigned int)format->encoding);
+    }
+
+    return 0;
+}
 
 
 static int
 static int
-ConvertSint24ToSint32(Uint8 ** audio_buf, Uint32 * audio_len)
-{
-    const double DIVBY8388608 = 0.00000011920928955078125;
-    const Uint32 original_len = *audio_len;
-    const Uint32 samples = original_len / 3;
-    const Uint32 expanded_len = samples * sizeof (Uint32);
-    Uint8 *ptr = (Uint8 *) SDL_realloc(*audio_buf, expanded_len);
-    const Uint8 *src;
-    Uint32 *dst;
-    Uint32 i;
-
-    if (!ptr) {
-        return SDL_OutOfMemory();
+WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+{
+    int result;
+    Uint32 chunkcount = 0;
+    Uint32 chunkcountlimit = 10000;
+    char *envchunkcountlimit;
+    Sint64 RIFFstart, RIFFend, lastchunkpos;
+    SDL_bool RIFFlengthknown = SDL_FALSE;
+    WaveFormat *format = &file->format;
+    WaveChunk *chunk = &file->chunk;
+    WaveChunk RIFFchunk;
+    WaveChunk fmtchunk;
+    WaveChunk datachunk;
+
+    SDL_zero(RIFFchunk);
+    SDL_zero(fmtchunk);
+    SDL_zero(datachunk);
+
+    envchunkcountlimit = SDL_getenv("SDL_WAVE_CHUNK_LIMIT");
+    if (envchunkcountlimit != NULL) {
+        unsigned int count;
+        if (SDL_sscanf(envchunkcountlimit, "%u", &count) == 1) {
+            chunkcountlimit = count <= SDL_MAX_UINT32 ? count : SDL_MAX_UINT32;
+        }
     }
     }
 
 
-    *audio_buf = ptr;
-    *audio_len = expanded_len;
+    RIFFstart = SDL_RWtell(src);
+    if (RIFFstart < 0) {
+        return SDL_SetError("Could not seek in file");
+    }
 
 
-    /* work from end to start, since we're expanding in-place. */
-    src = (ptr + original_len) - 3;
-    dst = ((Uint32 *) (ptr + expanded_len)) - 1;
-    for (i = 0; i < samples; i++) {
-        /* There's probably a faster way to do all this. */
-        const Sint32 converted = ((Sint32) ( (((Uint32) src[2]) << 24) |
-                                             (((Uint32) src[1]) << 16) |
-                                             (((Uint32) src[0]) << 8) )) >> 8;
-        const double scaled = (((double) converted) * DIVBY8388608);
-        src -= 3;
-        *(dst--) = (Sint32) (scaled * 2147483647.0);
+    RIFFchunk.position = RIFFstart;
+    if (WaveNextChunk(src, &RIFFchunk) < 0) {
+        return SDL_SetError("Could not read RIFF header");
     }
     }
 
 
-    return 0;
-}
+    /* Check main WAVE file identifiers. */
+    if (RIFFchunk.fourcc == RIFF) {
+        Uint32 formtype;
+        /* Read the form type. "WAVE" expected. */
+        if (SDL_RWread(src, &formtype, sizeof(Uint32), 1) != 1) {
+            return SDL_SetError("Could not read RIFF form type");
+        } else if (SDL_SwapLE32(formtype) != WAVE) {
+            return SDL_SetError("RIFF form type is not WAVE (not a Waveform file)");
+        }
+    } else if (RIFFchunk.fourcc == WAVE) {
+        /* RIFF chunk missing or skipped. Length unknown. */
+        RIFFchunk.position = 0;
+        RIFFchunk.length = 0;
+    } else {
+        return SDL_SetError("Could not find RIFF or WAVE identifiers (not a Waveform file)");
+    }
 
 
+    /* The 4-byte form type is immediately followed by the first chunk.*/
+    chunk->position = RIFFchunk.position + 4;
 
 
-/* GUIDs that are used by WAVE_FORMAT_EXTENSIBLE */
-static const Uint8 extensible_pcm_guid[16] = { 1, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 };
-static const Uint8 extensible_ieee_guid[16] = { 3, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 };
+    /* Use the RIFF chunk size to limit the search for the chunks. This is not
+     * always reliable and the hint can be used to tune the behavior. By
+     * default, it will never search past 4 GiB.
+     */
+    switch (file->riffhint) {
+    case RiffSizeIgnore:
+        RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
+        break;
+    default:
+    case RiffSizeIgnoreZero:
+        if (RIFFchunk.length == 0) {
+            RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
+            break;
+        }
+        /* fallthrough */
+    case RiffSizeForce:
+        RIFFend = RIFFchunk.position + RIFFchunk.length;
+        RIFFlengthknown = SDL_TRUE;
+        break;
+    case RiffSizeMaximum:
+        RIFFend = SDL_MAX_SINT64;
+        break;
+    }
 
 
-SDL_AudioSpec *
-SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
-               SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len)
-{
-    int was_error;
-    Chunk chunk;
-    int lenread;
-    int IEEE_float_encoded, MS_ADPCM_encoded, IMA_ADPCM_encoded;
-    int samplesize;
+    /* Step through all chunks and save information on the fmt, data, and fact
+     * chunks. Ignore the chunks we don't know as per specification. This
+     * currently also ignores cue, list, and slnt chunks.
+     */
+    while ((Uint64)RIFFend > (Uint64)chunk->position + chunk->length + (chunk->length & 1)) {
+        /* Abort after too many chunks or else corrupt files may waste time. */
+        if (chunkcount++ >= chunkcountlimit) {
+            return SDL_SetError("Chunk count in WAVE file exceeds limit of %u", chunkcountlimit);
+        }
+
+        result = WaveNextChunk(src, chunk);
+        if (result == -1) {
+            /* Unexpected EOF. Corrupt file or I/O issues. */
+            if (file->trunchint == TruncVeryStrict) {
+                return SDL_SetError("Unexpected end of WAVE file");
+            }
+            /* Let the checks after this loop sort this issue out. */
+            break;
+        } else if (result == -2) {
+            return SDL_SetError("Could not seek to WAVE chunk header");
+        }
 
 
-    /* WAV magic header */
-    Uint32 RIFFchunk;
-    Uint32 wavelen = 0;
-    Uint32 WAVEmagic;
-    Uint32 headerDiff = 0;
+        if (chunk->fourcc == FMT) {
+            if (fmtchunk.fourcc == FMT) {
+                /* Multiple fmt chunks. Ignore or error? */
+            } else {
+                /* The fmt chunk must occur before the data chunk. */
+                if (datachunk.fourcc == DATA) {
+                    return SDL_SetError("fmt chunk after data chunk in WAVE file");
+                }
+                fmtchunk = *chunk;
+            }
+        } else if (chunk->fourcc == DATA) {
+            /* Only use the first data chunk. Handling the wavl list madness
+             * may require a different approach.
+             */
+            if (datachunk.fourcc != DATA) {
+                datachunk = *chunk;
+            }
+        } else if (chunk->fourcc == FACT) {
+            /* The fact chunk data must be at least 4 bytes for the
+             * dwSampleLength field. Ignore all fact chunks after the first one.
+             */
+            if (file->fact.status == 0) {
+                if (chunk->length < 4) {
+                    file->fact.status = -1;
+                } else {
+                    /* Let's use src directly, it's just too convenient. */
+                    Sint64 position = SDL_RWseek(src, chunk->position, RW_SEEK_SET);
+                    Uint32 samplelength;
+                    if (position == chunk->position && SDL_RWread(src, &samplelength, sizeof(Uint32), 1) == 1) {
+                        file->fact.status = 1;
+                        file->fact.samplelength = SDL_SwapLE32(samplelength);
+                    } else {
+                        file->fact.status = -1;
+                    }
+                }
+            }
+        }
 
 
-    /* FMT chunk */
-    WaveFMT *format = NULL;
-    WaveExtensibleFMT *ext = NULL;
+        /* Go through all chunks in verystrict mode or stop the search early if
+         * all required chunks were found.
+         */
+        if (file->trunchint == TruncVeryStrict) {
+            if ((Uint64)RIFFend < (Uint64)chunk->position + chunk->length) {
+                return SDL_SetError("RIFF size truncates chunk");
+            }
+        } else if (fmtchunk.fourcc == FMT && datachunk.fourcc == DATA) {
+            if (file->fact.status == 1 || file->facthint == FactIgnore || file->facthint == FactNoHint) {
+                break;
+            }
+        }
+    }
 
 
-    SDL_zero(chunk);
+    /* Save the position after the last chunk. This position will be used if the
+     * RIFF length is unknown.
+     */
+    lastchunkpos = chunk->position + chunk->length;
 
 
-    /* Make sure we are passed a valid data source */
-    was_error = 0;
-    if (src == NULL) {
-        was_error = 1;
-        goto done;
+    /* The fmt chunk is mandatory. */
+    if (fmtchunk.fourcc != FMT) {
+        return SDL_SetError("Missing fmt chunk in WAVE file");
+    }
+    /* A data chunk must be present. */
+    if (datachunk.fourcc != DATA) {
+        return SDL_SetError("Missing data chunk in WAVE file");
+    }
+    /* Check if the last chunk has all of its data in verystrict mode. */
+    if (file->trunchint == TruncVeryStrict) {
+        /* data chunk is handled later. */
+        if (chunk->fourcc != DATA && chunk->length > 0) {
+            Uint8 tmp;
+            Uint64 position = (Uint64)chunk->position + chunk->length - 1;
+            if (position > SDL_MAX_SINT64 || SDL_RWseek(src, (Sint64)position, RW_SEEK_SET) != (Sint64)position) {
+                return SDL_SetError("Could not seek to WAVE chunk data");
+            } else if (SDL_RWread(src, &tmp, 1, 1) != 1) {
+                return SDL_SetError("RIFF size truncates chunk");
+            }
+        }
     }
     }
 
 
-    /* Check the magic header */
-    RIFFchunk = SDL_ReadLE32(src);
-    wavelen = SDL_ReadLE32(src);
-    if (wavelen == WAVE) {      /* The RIFFchunk has already been read */
-        WAVEmagic = wavelen;
-        wavelen = RIFFchunk;
-        RIFFchunk = RIFF;
-    } else {
-        WAVEmagic = SDL_ReadLE32(src);
-    }
-    if ((RIFFchunk != RIFF) || (WAVEmagic != WAVE)) {
-        SDL_SetError("Unrecognized file type (not WAVE)");
-        was_error = 1;
-        goto done;
-    }
-    headerDiff += sizeof(Uint32);       /* for WAVE */
-
-    /* Read the audio data format chunk */
-    chunk.data = NULL;
-    do {
-        SDL_free(chunk.data);
-        chunk.data = NULL;
-        lenread = ReadChunk(src, &chunk);
-        if (lenread < 0) {
-            was_error = 1;
-            goto done;
-        }
-        /* 2 Uint32's for chunk header+len, plus the lenread */
-        headerDiff += lenread + 2 * sizeof(Uint32);
-    } while ((chunk.magic == FACT) || (chunk.magic == LIST) || (chunk.magic == BEXT) || (chunk.magic == JUNK));
-
-    /* Decode the audio data format */
-    format = (WaveFMT *) chunk.data;
-    if (chunk.magic != FMT) {
-        SDL_SetError("Complex WAVE files not supported");
-        was_error = 1;
-        goto done;
-    }
-    IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
-    switch (SDL_SwapLE16(format->encoding)) {
+    /* Process fmt chunk. */
+    *chunk = fmtchunk;
+
+    /* No need to read more than 1046 bytes of the fmt chunk data with the
+     * formats that are currently supported. (1046 because of MS ADPCM coefficients)
+     */
+    if (WaveReadPartialChunkData(src, chunk, 1046) < 0) {
+        return SDL_SetError("Could not read data of WAVE fmt chunk");
+    }
+
+    /* The fmt chunk data must be at least 14 bytes to include all common fields.
+     * It usually is 16 and larger depending on the header and encoding.
+     */
+    if (chunk->length < 14) {
+        return SDL_SetError("Invalid WAVE fmt chunk length (too small)");
+    } else if (chunk->size < 14) {
+        return SDL_SetError("Could not read data of WAVE fmt chunk");
+    } else if (WaveReadFormat(file) < 0) {
+        return -1;
+    } else if (WaveCheckFormat(file, (size_t)datachunk.length) < 0) {
+        return -1;
+    }
+
+#ifdef SDL_WAVE_DEBUG_LOG_FORMAT
+    WaveDebugLogFormat(file);
+#endif
+#ifdef SDL_WAVE_DEBUG_DUMP_FORMAT
+    WaveDebugDumpFormat(file, RIFFchunk.length, fmtchunk.length, datachunk.length);
+#endif
+
+    WaveFreeChunkData(chunk);
+
+    /* Process data chunk. */
+    *chunk = datachunk;
+
+    if (chunk->length > 0) {
+        result = WaveReadChunkData(src, chunk);
+        if (result == -1) {
+            return -1;
+        } else if (result == -2) {
+            return SDL_SetError("Could not seek data of WAVE data chunk");
+        }
+    }
+
+    if (chunk->length != chunk->size) {
+        /* I/O issues or corrupt file. */
+        if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
+            return SDL_SetError("Could not read data of WAVE data chunk");
+        }
+        /* The decoders handle this truncation. */
+    }
+
+    /* Decode or convert the data if necessary. */
+    switch (format->encoding) {
     case PCM_CODE:
     case PCM_CODE:
-        /* We can understand this */
-        break;
     case IEEE_FLOAT_CODE:
     case IEEE_FLOAT_CODE:
-        IEEE_float_encoded = 1;
-        /* We can understand this */
+        if (PCM_Decode(file, audio_buf, audio_len) < 0) {
+            return -1;
+        }
         break;
         break;
-    case MS_ADPCM_CODE:
-        /* Try to understand this */
-        if (InitMS_ADPCM(format) < 0) {
-            was_error = 1;
-            goto done;
+    case ALAW_CODE:
+    case MULAW_CODE:
+        if (LAW_Decode(file, audio_buf, audio_len) < 0) {
+            return -1;
         }
         }
-        MS_ADPCM_encoded = 1;
         break;
         break;
-    case IMA_ADPCM_CODE:
-        /* Try to understand this */
-        if (InitIMA_ADPCM(format) < 0) {
-            was_error = 1;
-            goto done;
+    case MS_ADPCM_CODE:
+        if (MS_ADPCM_Decode(file, audio_buf, audio_len) < 0) {
+            return -1;
         }
         }
-        IMA_ADPCM_encoded = 1;
         break;
         break;
-    case EXTENSIBLE_CODE:
-        /* note that this ignores channel masks, smaller valid bit counts
-           inside a larger container, and most subtypes. This is just enough
-           to get things that didn't really _need_ WAVE_FORMAT_EXTENSIBLE
-           to be useful working when they use this format flag. */
-        ext = (WaveExtensibleFMT *) format;
-        if (SDL_SwapLE16(ext->size) < 22) {
-            SDL_SetError("bogus extended .wav header");
-            was_error = 1;
-            goto done;
-        }
-        if (SDL_memcmp(ext->subformat, extensible_pcm_guid, 16) == 0) {
-            break;  /* cool. */
-        } else if (SDL_memcmp(ext->subformat, extensible_ieee_guid, 16) == 0) {
-            IEEE_float_encoded = 1;
-            break;
+    case IMA_ADPCM_CODE:
+        if (IMA_ADPCM_Decode(file, audio_buf, audio_len) < 0) {
+            return -1;
         }
         }
         break;
         break;
-    case MP3_CODE:
-        SDL_SetError("MPEG Layer 3 data not supported");
-        was_error = 1;
-        goto done;
-    default:
-        SDL_SetError("Unknown WAVE data format: 0x%.4x",
-                     SDL_SwapLE16(format->encoding));
-        was_error = 1;
-        goto done;
     }
     }
+
+    /* Setting up the SDL_AudioSpec. All unsupported formats were filtered out
+     * by checks earlier in this function.
+     */
     SDL_zerop(spec);
     SDL_zerop(spec);
-    spec->freq = SDL_SwapLE32(format->frequency);
+    spec->freq = format->frequency;
+    spec->channels = (Uint8)format->channels;
+    spec->samples = 4096;       /* Good default buffer size */
 
 
-    if (IEEE_float_encoded) {
-        if ((SDL_SwapLE16(format->bitspersample)) != 32) {
-            was_error = 1;
-        } else {
-            spec->format = AUDIO_F32;
-        }
-    } else {
-        switch (SDL_SwapLE16(format->bitspersample)) {
-        case 4:
-            if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
-                spec->format = AUDIO_S16;
-            } else {
-                was_error = 1;
-            }
-            break;
+    switch (format->encoding) {
+    case MS_ADPCM_CODE:
+    case IMA_ADPCM_CODE:
+    case ALAW_CODE:
+    case MULAW_CODE:
+        /* These can be easily stored in the byte order of the system. */
+        spec->format = AUDIO_S16SYS;
+        break;
+    case IEEE_FLOAT_CODE:
+        spec->format = AUDIO_F32LSB;
+        break;
+    case PCM_CODE:
+        switch (format->bitspersample) {
         case 8:
         case 8:
             spec->format = AUDIO_U8;
             spec->format = AUDIO_U8;
             break;
             break;
         case 16:
         case 16:
-            spec->format = AUDIO_S16;
-            break;
-        case 24:  /* convert this. */
-            spec->format = AUDIO_S32;
+            spec->format = AUDIO_S16LSB;
             break;
             break;
+        case 24: /* Has been shifted to 32 bits. */
         case 32:
         case 32:
-            spec->format = AUDIO_S32;
+            spec->format = AUDIO_S32LSB;
             break;
             break;
         default:
         default:
-            was_error = 1;
-            break;
+            /* Just in case something unexpected happened in the checks. */
+            return SDL_SetError("Unexpected %u-bit PCM data format", (unsigned int)format->bitspersample);
         }
         }
+        break;
     }
     }
 
 
-    if (was_error) {
-        SDL_SetError("Unknown %d-bit PCM data format",
-                     SDL_SwapLE16(format->bitspersample));
-        goto done;
+    /* Report the end position back to the cleanup code. */
+    if (RIFFlengthknown) {
+        chunk->position = RIFFend;
+    } else {
+        chunk->position = lastchunkpos;
     }
     }
-    spec->channels = (Uint8) SDL_SwapLE16(format->channels);
-    spec->samples = 4096;       /* Good default buffer size */
 
 
-    /* Read the audio data chunk */
-    *audio_buf = NULL;
-    do {
-        SDL_free(*audio_buf);
-        *audio_buf = NULL;
-        lenread = ReadChunk(src, &chunk);
-        if (lenread < 0) {
-            was_error = 1;
-            goto done;
-        }
-        *audio_len = lenread;
-        *audio_buf = chunk.data;
-        if (chunk.magic != DATA)
-            headerDiff += lenread + 2 * sizeof(Uint32);
-    } while (chunk.magic != DATA);
-    headerDiff += 2 * sizeof(Uint32);   /* for the data chunk and len */
+    return 0;
+}
 
 
-    if (MS_ADPCM_encoded) {
-        if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
-            was_error = 1;
-            goto done;
-        }
-    }
-    if (IMA_ADPCM_encoded) {
-        if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
-            was_error = 1;
-            goto done;
-        }
-    }
+SDL_AudioSpec *
+SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+{
+    int result;
+    WaveFile file;
 
 
-    if (SDL_SwapLE16(format->bitspersample) == 24) {
-        if (ConvertSint24ToSint32(audio_buf, audio_len) < 0) {
-            was_error = 1;
-            goto done;
-        }
+    SDL_zero(file);
+
+    /* Make sure we are passed a valid data source */
+    if (src == NULL) {
+        /* Error may come from RWops. */
+        return NULL;
+    } else if (spec == NULL) {
+        SDL_InvalidParamError("spec");
+        return NULL;
+    } else if (audio_buf == NULL) {
+        SDL_InvalidParamError("audio_buf");
+        return NULL;
+    } else if (audio_len == NULL) {
+        SDL_InvalidParamError("audio_len");
+        return NULL;
     }
     }
 
 
-    /* Don't return a buffer that isn't a multiple of samplesize */
-    samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
-    *audio_len &= ~(samplesize - 1);
+    *audio_buf = NULL;
+    *audio_len = 0;
 
 
-  done:
-    SDL_free(format);
-    if (src) {
-        if (freesrc) {
-            SDL_RWclose(src);
-        } else {
-            /* seek to the end of the file (given by the RIFF chunk) */
-            SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
-        }
-    }
-    if (was_error) {
+    file.riffhint = WaveGetRiffSizeHint();
+    file.trunchint = WaveGetTruncationHint();
+    file.facthint = WaveGetFactChunkHint();
+
+    result = WaveLoad(src, &file, spec, audio_buf, audio_len);
+    if (result < 0) {
+        SDL_free(*audio_buf);
         spec = NULL;
         spec = NULL;
+        audio_buf = NULL;
+        audio_len = 0;
+    }
+
+    /* Cleanup */
+    if (freesrc) {
+        SDL_RWclose(src);
+    } else {
+        SDL_RWseek(src, file.chunk.position, RW_SEEK_SET);
     }
     }
-    return (spec);
+    WaveFreeChunkData(&file.chunk);
+    SDL_free(file.decoderdata);
+
+    return spec;
 }
 }
 
 
 /* Since the WAV memory is allocated in the shared library, it must also
 /* Since the WAV memory is allocated in the shared library, it must also
    be freed here.  (Necessary under Win32, VC++)
    be freed here.  (Necessary under Win32, VC++)
  */
  */
 void
 void
-SDL_FreeWAV(Uint8 * audio_buf)
+SDL_FreeWAV(Uint8 *audio_buf)
 {
 {
     SDL_free(audio_buf);
     SDL_free(audio_buf);
 }
 }
 
 
-static int
-ReadChunk(SDL_RWops * src, Chunk * chunk)
-{
-    chunk->magic = SDL_ReadLE32(src);
-    chunk->length = SDL_ReadLE32(src);
-    chunk->data = (Uint8 *) SDL_malloc(chunk->length);
-    if (chunk->data == NULL) {
-        return SDL_OutOfMemory();
-    }
-    if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
-        SDL_free(chunk->data);
-        chunk->data = NULL;
-        return SDL_Error(SDL_EFREAD);
-    }
-    return (chunk->length);
-}
-
 /* vi: set ts=4 sw=4 expandtab: */
 /* vi: set ts=4 sw=4 expandtab: */

+ 103 - 31
sdl.mod/SDL/src/audio/SDL_wave.h

@@ -20,11 +20,12 @@
 */
 */
 #include "../SDL_internal.h"
 #include "../SDL_internal.h"
 
 
-/* WAVE files are little-endian */
+/* RIFF WAVE files are little-endian */
 
 
 /*******************************************/
 /*******************************************/
 /* Define values for Microsoft WAVE format */
 /* Define values for Microsoft WAVE format */
 /*******************************************/
 /*******************************************/
+/* FOURCC */
 #define RIFF            0x46464952      /* "RIFF" */
 #define RIFF            0x46464952      /* "RIFF" */
 #define WAVE            0x45564157      /* "WAVE" */
 #define WAVE            0x45564157      /* "WAVE" */
 #define FACT            0x74636166      /* "fact" */
 #define FACT            0x74636166      /* "fact" */
@@ -33,45 +34,116 @@
 #define JUNK            0x4B4E554A      /* "JUNK" */
 #define JUNK            0x4B4E554A      /* "JUNK" */
 #define FMT             0x20746D66      /* "fmt " */
 #define FMT             0x20746D66      /* "fmt " */
 #define DATA            0x61746164      /* "data" */
 #define DATA            0x61746164      /* "data" */
+/* Format tags */
+#define UNKNOWN_CODE    0x0000
 #define PCM_CODE        0x0001
 #define PCM_CODE        0x0001
 #define MS_ADPCM_CODE   0x0002
 #define MS_ADPCM_CODE   0x0002
 #define IEEE_FLOAT_CODE 0x0003
 #define IEEE_FLOAT_CODE 0x0003
+#define ALAW_CODE       0x0006
+#define MULAW_CODE      0x0007
 #define IMA_ADPCM_CODE  0x0011
 #define IMA_ADPCM_CODE  0x0011
-#define MP3_CODE        0x0055
+#define MPEG_CODE       0x0050
+#define MPEGLAYER3_CODE 0x0055
 #define EXTENSIBLE_CODE 0xFFFE
 #define EXTENSIBLE_CODE 0xFFFE
-#define WAVE_MONO       1
-#define WAVE_STEREO     2
 
 
-/* Normally, these three chunks come consecutively in a WAVE file */
-typedef struct WaveFMT
+/* Stores the WAVE format information. */
+typedef struct WaveFormat
 {
 {
-/* Not saved in the chunk we read:
-    Uint32  FMTchunk;
-    Uint32  fmtlen;
-*/
-    Uint16 encoding;
-    Uint16 channels;            /* 1 = mono, 2 = stereo */
-    Uint32 frequency;           /* One of 11025, 22050, or 44100 Hz */
-    Uint32 byterate;            /* Average bytes per second */
-    Uint16 blockalign;          /* Bytes per sample block */
-    Uint16 bitspersample;       /* One of 8, 12, 16, or 4 for ADPCM */
-} WaveFMT;
-
-/* The general chunk found in the WAVE file */
-typedef struct Chunk
+    Uint16 formattag;       /* Raw value of the first field in the fmt chunk data. */
+    Uint16 encoding;        /* Actual encoding, possibly from the extensible header. */
+    Uint16 channels;        /* Number of channels. */
+    Uint32 frequency;       /* Sampling rate in Hz. */
+    Uint32 byterate;        /* Average bytes per second. */
+    Uint16 blockalign;      /* Bytes per block. */
+    Uint16 bitspersample;   /* Currently supported are 8, 16, 24, 32, and 4 for ADPCM. */
+
+    /* Extra information size. Number of extra bytes starting at byte 18 in the
+     * fmt chunk data. This is at least 22 for the extensible header.
+     */
+    Uint16 extsize;
+
+    /* Extensible WAVE header fields */
+    Uint16 validsamplebits;
+    Uint32 samplesperblock; /* For compressed formats. Can be zero. Actually 16 bits in the header. */
+    Uint32 channelmask;
+    Uint8 subformat[16];    /* A format GUID. */
+} WaveFormat;
+
+/* Stores information on the fact chunk. */
+typedef struct WaveFact {
+    /* Represents the state of the fact chunk in the WAVE file.
+     * Set to -1 if the fact chunk is invalid.
+     * Set to 0 if the fact chunk is not present
+     * Set to 1 if the fact chunk is present and valid.
+     * Set to 2 if samplelength is going to be used as the number of sample frames.
+     */
+    Sint32 status;
+
+    /* Version 1 of the RIFF specification calls the field in the fact chunk
+     * dwFileSize. The Standards Update then calls it dwSampleLength and specifies
+     * that it is 'the length of the data in samples'. WAVE files from Windows
+     * with this chunk have it set to the samples per channel (sample frames).
+     * This is useful to truncate compressed audio to a specific sample count
+     * because a compressed block is usually decoded to a fixed number of
+     * sample frames.
+     */
+    Uint32 samplelength; /* Raw sample length value from the fact chunk. */
+} WaveFact;
+
+/* Generic struct for the chunks in the WAVE file. */
+typedef struct WaveChunk
 {
 {
-    Uint32 magic;
-    Uint32 length;
-    Uint8 *data;
-} Chunk;
+    Uint32 fourcc;   /* FOURCC of the chunk. */
+    Uint32 length;   /* Size of the chunk data. */
+    Sint64 position; /* Position of the data in the stream. */
+    Uint8 *data;     /* When allocated, this points to the chunk data. length is used for the malloc size. */
+    size_t size;     /* Number of bytes in data that could be read from the stream. Can be smaller than length. */
+} WaveChunk;
 
 
-typedef struct WaveExtensibleFMT
+/* Controls how the size of the RIFF chunk affects the loading of a WAVE file. */
+typedef enum WaveRiffSizeHint {
+    RiffSizeNoHint,
+    RiffSizeForce,
+    RiffSizeIgnoreZero,
+    RiffSizeIgnore,
+    RiffSizeMaximum
+} WaveRiffSizeHint;
+
+/* Controls how a truncated WAVE file is handled. */
+typedef enum WaveTruncationHint {
+    TruncNoHint,
+    TruncVeryStrict,
+    TruncStrict,
+    TruncDropFrame,
+    TruncDropBlock
+} WaveTruncationHint;
+
+/* Controls how the fact chunk affects the loading of a WAVE file. */
+typedef enum WaveFactChunkHint {
+    FactNoHint,
+    FactTruncate,
+    FactStrict,
+    FactIgnoreZero,
+    FactIgnore
+} WaveFactChunkHint;
+
+typedef struct WaveFile
 {
 {
-    WaveFMT format;
-    Uint16 size;
-    Uint16 validbits;
-    Uint32 channelmask;
-    Uint8 subformat[16];  /* a GUID. */
-} WaveExtensibleFMT;
+    WaveChunk chunk;
+    WaveFormat format;
+    WaveFact fact;
+
+    /* Number of sample frames that will be decoded. Calculated either with the
+     * size of the data chunk or, if the appropriate hint is enabled, with the
+     * sample length value from the fact chunk.
+     */
+    Sint64 sampleframes;
+
+    void *decoderdata;   /* Some decoders require extra data for a state. */
+
+    WaveRiffSizeHint riffhint;
+    WaveTruncationHint trunchint;
+    WaveFactChunkHint facthint;
+} WaveFile;
 
 
 /* vi: set ts=4 sw=4 expandtab: */
 /* vi: set ts=4 sw=4 expandtab: */

+ 21 - 13
sdl.mod/SDL/src/audio/alsa/SDL_alsa_audio.c

@@ -72,7 +72,9 @@ static int (*ALSA_snd_pcm_hw_params_set_period_size_near)
   (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
   (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
 static int (*ALSA_snd_pcm_hw_params_get_period_size)
 static int (*ALSA_snd_pcm_hw_params_get_period_size)
   (const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
   (const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
-static int (*ALSA_snd_pcm_hw_params_set_periods_near)
+static int (*ALSA_snd_pcm_hw_params_set_periods_min)
+  (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
+static int (*ALSA_snd_pcm_hw_params_set_periods_first)
   (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
   (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
 static int (*ALSA_snd_pcm_hw_params_get_periods)
 static int (*ALSA_snd_pcm_hw_params_get_periods)
   (const snd_pcm_hw_params_t *, unsigned int *, int *);
   (const snd_pcm_hw_params_t *, unsigned int *, int *);
@@ -148,7 +150,8 @@ load_alsa_syms(void)
     SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
     SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
     SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
     SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
     SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
     SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
-    SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_min);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_first);
     SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
     SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
     SDL_ALSA_SYM(snd_pcm_hw_params_set_buffer_size_near);
     SDL_ALSA_SYM(snd_pcm_hw_params_set_buffer_size_near);
     SDL_ALSA_SYM(snd_pcm_hw_params_get_buffer_size);
     SDL_ALSA_SYM(snd_pcm_hw_params_get_buffer_size);
@@ -337,7 +340,6 @@ swizzle_alsa_channels(_THIS, void *buffer, Uint32 bufferlen)
 static void
 static void
 no_swizzle(_THIS, void *buffer, Uint32 bufferlen)
 no_swizzle(_THIS, void *buffer, Uint32 bufferlen)
 {
 {
-    return;
 }
 }
 #endif /* SND_CHMAP_API_VERSION */
 #endif /* SND_CHMAP_API_VERSION */
 
 
@@ -346,7 +348,7 @@ static void
 ALSA_PlayDevice(_THIS)
 ALSA_PlayDevice(_THIS)
 {
 {
     const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
     const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
-    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
+    const int frame_size = ((SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
                                 this->spec.channels;
                                 this->spec.channels;
     snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
     snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
 
 
@@ -395,7 +397,7 @@ static int
 ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen)
 ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen)
 {
 {
     Uint8 *sample_buf = (Uint8 *) buffer;
     Uint8 *sample_buf = (Uint8 *) buffer;
-    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
+    const int frame_size = ((SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
                                 this->spec.channels;
                                 this->spec.channels;
     const int total_frames = buflen / frame_size;
     const int total_frames = buflen / frame_size;
     snd_pcm_uframes_t frames_left = total_frames;
     snd_pcm_uframes_t frames_left = total_frames;
@@ -462,14 +464,14 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
 {
 {
     int status;
     int status;
     snd_pcm_hw_params_t *hwparams;
     snd_pcm_hw_params_t *hwparams;
-    snd_pcm_uframes_t bufsize;
     snd_pcm_uframes_t persize;
     snd_pcm_uframes_t persize;
+    unsigned int periods;
 
 
     /* Copy the hardware parameters for this setup */
     /* Copy the hardware parameters for this setup */
     snd_pcm_hw_params_alloca(&hwparams);
     snd_pcm_hw_params_alloca(&hwparams);
     ALSA_snd_pcm_hw_params_copy(hwparams, params);
     ALSA_snd_pcm_hw_params_copy(hwparams, params);
 
 
-    /* Prioritize matching the period size to the requested buffer size */
+    /* Attempt to match the period size to the requested buffer size */
     persize = this->spec.samples;
     persize = this->spec.samples;
     status = ALSA_snd_pcm_hw_params_set_period_size_near(
     status = ALSA_snd_pcm_hw_params_set_period_size_near(
                 this->hidden->pcm_handle, hwparams, &persize, NULL);
                 this->hidden->pcm_handle, hwparams, &persize, NULL);
@@ -477,10 +479,16 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
         return(-1);
         return(-1);
     }
     }
 
 
-    /* Next try to restrict the parameters to having only two periods */
-    bufsize = this->spec.samples * 2;
-    status = ALSA_snd_pcm_hw_params_set_buffer_size_near(
-                    this->hidden->pcm_handle, hwparams, &bufsize);
+    /* Need to at least double buffer */
+    periods = 2;
+    status = ALSA_snd_pcm_hw_params_set_periods_min(
+                this->hidden->pcm_handle, hwparams, &periods, NULL);
+    if ( status < 0 ) {
+        return(-1);
+    }
+
+    status = ALSA_snd_pcm_hw_params_set_periods_first(
+                this->hidden->pcm_handle, hwparams, &periods, NULL);
     if ( status < 0 ) {
     if ( status < 0 ) {
         return(-1);
         return(-1);
     }
     }
@@ -495,9 +503,9 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
 
 
     /* This is useful for debugging */
     /* This is useful for debugging */
     if ( SDL_getenv("SDL_AUDIO_ALSA_DEBUG") ) {
     if ( SDL_getenv("SDL_AUDIO_ALSA_DEBUG") ) {
-        unsigned int periods = 0;
+        snd_pcm_uframes_t bufsize;
 
 
-        ALSA_snd_pcm_hw_params_get_periods(hwparams, &periods, NULL);
+        ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
 
 
         fprintf(stderr,
         fprintf(stderr,
             "ALSA: period size = %ld, periods = %u, buffer size = %lu\n",
             "ALSA: period size = %ld, periods = %u, buffer size = %lu\n",

+ 34 - 4
sdl.mod/SDL/src/audio/coreaudio/SDL_coreaudio.m

@@ -376,7 +376,7 @@ static BOOL update_audio_session(_THIS, SDL_bool open)
             /* An interruption end notification is not guaranteed to be sent if
             /* An interruption end notification is not guaranteed to be sent if
              we were previously interrupted... resuming if needed when the app
              we were previously interrupted... resuming if needed when the app
              becomes active seems to be the way to go. */
              becomes active seems to be the way to go. */
-			// Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications.  johna
+            // Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications.  johna
             [center addObserver:listener
             [center addObserver:listener
                        selector:@selector(applicationBecameActive:)
                        selector:@selector(applicationBecameActive:)
                            name:UIApplicationDidBecomeActiveNotification
                            name:UIApplicationDidBecomeActiveNotification
@@ -417,6 +417,34 @@ outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffe
     if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
     if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
         /* Supply silence if audio is not enabled or paused */
         /* Supply silence if audio is not enabled or paused */
         SDL_memset(inBuffer->mAudioData, this->spec.silence, inBuffer->mAudioDataBytesCapacity);
         SDL_memset(inBuffer->mAudioData, this->spec.silence, inBuffer->mAudioDataBytesCapacity);
+    } else if (this->stream ) {
+        UInt32 remaining = inBuffer->mAudioDataBytesCapacity;
+        Uint8 *ptr = (Uint8 *) inBuffer->mAudioData;
+
+        while (remaining > 0) {
+            if ( SDL_AudioStreamAvailable(this->stream) == 0 ) {
+                /* Generate the data */
+                SDL_LockMutex(this->mixer_lock);
+                (*this->callbackspec.callback)(this->callbackspec.userdata,
+                                               this->hidden->buffer, this->hidden->bufferSize);
+                SDL_UnlockMutex(this->mixer_lock);
+                this->hidden->bufferOffset = 0;
+                SDL_AudioStreamPut(this->stream, this->hidden->buffer, this->hidden->bufferSize);
+            }
+            if ( SDL_AudioStreamAvailable(this->stream) > 0 ) {
+                int got;
+                UInt32 len = SDL_AudioStreamAvailable(this->stream);
+                if ( len > remaining )
+                    len = remaining;
+                got = SDL_AudioStreamGet(this->stream, ptr, len);
+                SDL_assert((got < 0) || (got == len));
+                if (got != len) {
+                    SDL_memset(ptr, this->spec.silence, len);
+                }
+                ptr = ptr + len;
+                remaining -= len;
+            }
+        }
     } else {
     } else {
         UInt32 remaining = inBuffer->mAudioDataBytesCapacity;
         UInt32 remaining = inBuffer->mAudioDataBytesCapacity;
         Uint8 *ptr = (Uint8 *) inBuffer->mAudioData;
         Uint8 *ptr = (Uint8 *) inBuffer->mAudioData;
@@ -791,13 +819,11 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     while ((!valid_datatype) && (test_format)) {
     while ((!valid_datatype) && (test_format)) {
         this->spec.format = test_format;
         this->spec.format = test_format;
-        /* Just a list of valid SDL formats, so people don't pass junk here. */
+        /* CoreAudio handles most of SDL's formats natively, but not U16, apparently. */
         switch (test_format) {
         switch (test_format) {
         case AUDIO_U8:
         case AUDIO_U8:
         case AUDIO_S8:
         case AUDIO_S8:
-        case AUDIO_U16LSB:
         case AUDIO_S16LSB:
         case AUDIO_S16LSB:
-        case AUDIO_U16MSB:
         case AUDIO_S16MSB:
         case AUDIO_S16MSB:
         case AUDIO_S32LSB:
         case AUDIO_S32LSB:
         case AUDIO_S32MSB:
         case AUDIO_S32MSB:
@@ -813,6 +839,10 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
             else if (SDL_AUDIO_ISSIGNED(this->spec.format))
             else if (SDL_AUDIO_ISSIGNED(this->spec.format))
                 strdesc->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
                 strdesc->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
             break;
             break;
+
+        default:
+            test_format = SDL_NextAudioFormat();
+            break;
         }
         }
     }
     }
 
 

+ 47 - 126
sdl.mod/SDL/src/audio/netbsd/SDL_netbsdaudio.c

@@ -43,12 +43,7 @@
 #include "../SDL_audiodev_c.h"
 #include "../SDL_audiodev_c.h"
 #include "SDL_netbsdaudio.h"
 #include "SDL_netbsdaudio.h"
 
 
-/* Use timer for synchronization */
-/* #define USE_TIMER_SYNC */
-
 /* #define DEBUG_AUDIO */
 /* #define DEBUG_AUDIO */
-/* #define DEBUG_AUDIO_STREAM */
-
 
 
 static void
 static void
 NETBSDAUDIO_DetectDevices(void)
 NETBSDAUDIO_DetectDevices(void)
@@ -63,14 +58,14 @@ NETBSDAUDIO_Status(_THIS)
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
     /* *INDENT-OFF* */
     /* *INDENT-OFF* */
     audio_info_t info;
     audio_info_t info;
-    const audio_prinfo *prinfo;
+    const struct audio_prinfo *prinfo;
 
 
     if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
     if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
         fprintf(stderr, "AUDIO_GETINFO failed.\n");
         fprintf(stderr, "AUDIO_GETINFO failed.\n");
         return;
         return;
     }
     }
 
 
-    prinfo = this->iscapture ? &info.play : &info.record;
+    prinfo = this->iscapture ? &info.record : &info.play;
 
 
     fprintf(stderr, "\n"
     fprintf(stderr, "\n"
             "[%s info]\n"
             "[%s info]\n"
@@ -115,90 +110,37 @@ NETBSDAUDIO_Status(_THIS)
             (info.mode == AUMODE_PLAY) ? "PLAY"
             (info.mode == AUMODE_PLAY) ? "PLAY"
             : (info.mode = AUMODE_RECORD) ? "RECORD"
             : (info.mode = AUMODE_RECORD) ? "RECORD"
             : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
             : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
+
+    fprintf(stderr, "\n"
+            "[audio spec]\n"
+            "format		:   0x%x\n"
+            "size		:   %u\n"
+            "",
+            this->spec.format,
+            this->spec.size);
     /* *INDENT-ON* */
     /* *INDENT-ON* */
 #endif /* DEBUG_AUDIO */
 #endif /* DEBUG_AUDIO */
 }
 }
 
 
 
 
-/* This function waits until it is possible to write a full sound buffer */
-static void
-NETBSDAUDIO_WaitDevice(_THIS)
-{
-#ifndef USE_BLOCKING_WRITES     /* Not necessary when using blocking writes */
-    /* See if we need to use timed audio synchronization */
-    if (this->hidden->frame_ticks) {
-        /* Use timer for general audio synchronization */
-        Sint32 ticks;
-
-        ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
-        if (ticks > 0) {
-            SDL_Delay(ticks);
-        }
-    } else {
-        /* Use SDL_IOReady() for audio synchronization */
-#ifdef DEBUG_AUDIO
-        fprintf(stderr, "Waiting for audio to get ready\n");
-#endif
-        if (SDL_IOReady(this->hidden->audio_fd, SDL_TRUE, 10 * 1000)
-            <= 0) {
-            const char *message =
-                "Audio timeout - buggy audio driver? (disabled)";
-            /* In general we should never print to the screen,
-               but in this case we have no other way of letting
-               the user know what happened.
-             */
-            fprintf(stderr, "SDL: %s\n", message);
-            SDL_OpenedAudioDeviceDisconnected(this);
-            /* Don't try to close - may hang */
-            this->hidden->audio_fd = -1;
-#ifdef DEBUG_AUDIO
-            fprintf(stderr, "Done disabling audio\n");
-#endif
-        }
-#ifdef DEBUG_AUDIO
-        fprintf(stderr, "Ready!\n");
-#endif
-    }
-#endif /* !USE_BLOCKING_WRITES */
-}
-
 static void
 static void
 NETBSDAUDIO_PlayDevice(_THIS)
 NETBSDAUDIO_PlayDevice(_THIS)
 {
 {
-    int written, p = 0;
-
-    /* Write the audio data, checking for EAGAIN on broken audio drivers */
-    do {
-        written = write(this->hidden->audio_fd,
-                        &this->hidden->mixbuf[p], this->hidden->mixlen - p);
-
-        if (written > 0)
-            p += written;
-        if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
-            /* Non recoverable error has occurred. It should be reported!!! */
-            perror("audio");
-            break;
-        }
-
-#ifdef DEBUG_AUDIO
-        fprintf(stderr, "Wrote %d bytes of audio data\n", written);
-#endif
-
-        if (p < this->hidden->mixlen
-            || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
-            SDL_Delay(1);       /* Let a little CPU time go by */
-        }
-    } while (p < this->hidden->mixlen);
-
-    /* If timer synchronization is enabled, set the next write frame */
-    if (this->hidden->frame_ticks) {
-        this->hidden->next_frame += this->hidden->frame_ticks;
-    }
+    struct SDL_PrivateAudioData *h = this->hidden;
+    int written;
 
 
-    /* If we couldn't write, assume fatal error for now */
-    if (written < 0) {
+    /* Write the audio data */
+    written = write(h->audio_fd, h->mixbuf, h->mixlen);
+    if (written == -1) {
+        /* Non recoverable error has occurred. It should be reported!!! */
         SDL_OpenedAudioDeviceDisconnected(this);
         SDL_OpenedAudioDeviceDisconnected(this);
+        perror("audio");
+        return;
     }
     }
+
+#ifdef DEBUG_AUDIO
+    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
+#endif
 }
 }
 
 
 static Uint8 *
 static Uint8 *
@@ -212,28 +154,19 @@ static int
 NETBSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
 NETBSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
 {
 {
     Uint8 *buffer = (Uint8 *) _buffer;
     Uint8 *buffer = (Uint8 *) _buffer;
-    int br, p = 0;
-
-    /* Capture the audio data, checking for EAGAIN on broken audio drivers */
-    do {
-        br = read(this->hidden->audio_fd, buffer + p, buflen - p);
-        if (br > 0)
-            p += br;
-        if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
-            /* Non recoverable error has occurred. It should be reported!!! */
-            perror("audio");
-            return p ? p : -1;
-        }
+    int br;
+
+    br = read(this->hidden->audio_fd, buffer, buflen);
+    if (br == -1) {
+        /* Non recoverable error has occurred. It should be reported!!! */
+        perror("audio");
+        return -1;
+    }
 
 
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
-        fprintf(stderr, "Captured %d bytes of audio data\n", br);
+    fprintf(stderr, "Captured %d bytes of audio data\n", br);
 #endif
 #endif
-
-        if (p < buflen
-            || ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) {
-            SDL_Delay(1);       /* Let a little CPU time go by */
-        }
-    } while (p < buflen);
+    return 0;
 }
 }
 
 
 static void
 static void
@@ -271,10 +204,9 @@ NETBSDAUDIO_CloseDevice(_THIS)
 static int
 static int
 NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
-    const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
     SDL_AudioFormat format = 0;
     SDL_AudioFormat format = 0;
     audio_info_t info;
     audio_info_t info;
-    audio_prinfo *prinfo = iscapture ? &info.play : &info.record;
+    struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play;
 
 
     /* We don't care what the devname is...we'll try to open anything. */
     /* We don't care what the devname is...we'll try to open anything. */
     /*  ...but default to first name in the list... */
     /*  ...but default to first name in the list... */
@@ -294,25 +226,16 @@ NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_zerop(this->hidden);
     SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
-    this->hidden->audio_fd = open(devname, flags, 0);
+    this->hidden->audio_fd = open(devname, iscapture ? O_RDONLY : O_WRONLY);
     if (this->hidden->audio_fd < 0) {
     if (this->hidden->audio_fd < 0) {
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
     }
     }
 
 
     AUDIO_INITINFO(&info);
     AUDIO_INITINFO(&info);
 
 
-    /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(&this->spec);
-
-    /* Set to play mode */
-    info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
-    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
-        return SDL_SetError("Couldn't put device into play mode");
-    }
+    prinfo->encoding = AUDIO_ENCODING_NONE;
 
 
-    AUDIO_INITINFO(&info);
-    for (format = SDL_FirstAudioFormat(this->spec.format);
-         format; format = SDL_NextAudioFormat()) {
+    for (format = SDL_FirstAudioFormat(this->spec.format); format;) {
         switch (format) {
         switch (format) {
         case AUDIO_U8:
         case AUDIO_U8:
             prinfo->encoding = AUDIO_ENCODING_ULINEAR;
             prinfo->encoding = AUDIO_ENCODING_ULINEAR;
@@ -338,34 +261,33 @@ NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
             prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
             prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
             prinfo->precision = 16;
             prinfo->precision = 16;
             break;
             break;
-        default:
-            continue;
         }
         }
-
-        if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
+        if (prinfo->encoding != AUDIO_ENCODING_NONE) {
             break;
             break;
         }
         }
+        format = SDL_NextAudioFormat();
     }
     }
 
 
-    if (!format) {
+    if (prinfo->encoding == AUDIO_ENCODING_NONE) {
         return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
         return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
     }
     }
 
 
     this->spec.format = format;
     this->spec.format = format;
 
 
-    AUDIO_INITINFO(&info);
-    prinfo->channels = this->spec.channels;
-    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
-        this->spec.channels = 1;
-    }
-    AUDIO_INITINFO(&info);
-    prinfo->sample_rate = this->spec.freq;
+    /* Calculate spec parameters based on our chosen format */
+    SDL_CalculateAudioSpec(&this->spec);
+
+    info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
     info.blocksize = this->spec.size;
     info.blocksize = this->spec.size;
     info.hiwat = 5;
     info.hiwat = 5;
     info.lowat = 3;
     info.lowat = 3;
+    prinfo->sample_rate = this->spec.freq;
+    prinfo->channels = this->spec.channels;
     (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
     (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
+
     (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
     (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
     this->spec.freq = prinfo->sample_rate;
     this->spec.freq = prinfo->sample_rate;
+    this->spec.channels = prinfo->channels;
 
 
     if (!iscapture) {
     if (!iscapture) {
         /* Allocate mixing buffer */
         /* Allocate mixing buffer */
@@ -390,7 +312,6 @@ NETBSDAUDIO_Init(SDL_AudioDriverImpl * impl)
     impl->DetectDevices = NETBSDAUDIO_DetectDevices;
     impl->DetectDevices = NETBSDAUDIO_DetectDevices;
     impl->OpenDevice = NETBSDAUDIO_OpenDevice;
     impl->OpenDevice = NETBSDAUDIO_OpenDevice;
     impl->PlayDevice = NETBSDAUDIO_PlayDevice;
     impl->PlayDevice = NETBSDAUDIO_PlayDevice;
-    impl->WaitDevice = NETBSDAUDIO_WaitDevice;
     impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf;
     impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf;
     impl->CloseDevice = NETBSDAUDIO_CloseDevice;
     impl->CloseDevice = NETBSDAUDIO_CloseDevice;
     impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice;
     impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice;

+ 40 - 14
sdl.mod/SDL/src/audio/openslES/SDL_openslES.c

@@ -22,6 +22,10 @@
 
 
 #if SDL_AUDIO_DRIVER_OPENSLES
 #if SDL_AUDIO_DRIVER_OPENSLES
 
 
+/* For more discussion of low latency audio on Android, see this:
+   https://googlesamples.github.io/android-audio-high-performance/guides/opensl_es.html
+*/
+
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_openslES.h"
 #include "SDL_openslES.h"
@@ -32,9 +36,8 @@
 
 
 #include <android/log.h>
 #include <android/log.h>
 
 
-#define LOG_TAG "SDL_openslES"
-
 #if 0
 #if 0
+#define LOG_TAG "SDL_openslES"
 #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
 #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
 #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
 #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
 //#define LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
 //#define LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
@@ -99,7 +102,7 @@ static void openslES_DetectDevices( int iscapture )
 }
 }
 #endif
 #endif
 
 
-static void openslES_DestroyEngine();
+static void openslES_DestroyEngine(void);
 
 
 static int
 static int
 openslES_CreateEngine()
 openslES_CreateEngine()
@@ -290,19 +293,42 @@ openslES_CreatePCMPlayer(_THIS)
 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
 */
 */
+#define SL_ANDROID_SPEAKER_STEREO (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT)
+#define SL_ANDROID_SPEAKER_QUAD (SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT)
+#define SL_ANDROID_SPEAKER_5DOT1 (SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER  | SL_SPEAKER_LOW_FREQUENCY)
+#define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT)
 
 
-    if (this->spec.channels == 1) {
-        format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
-    } else if (this->spec.channels == 2) {
+    switch (this->spec.channels)
+    {
+    case 1:
+        format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT;
+        break;
+    case 2:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO;
+        break;
+    case 3:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER;
+        break;
+    case 4:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD;
+        break;
+    case 5:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
+        break;
+    case 6:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1;
+        break;
+    case 7:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
+        break;
+    case 8:
+        format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1;
+        break;
+    default:
+        /* Unknown number of channels, fall back to stereo */
+        this->spec.channels = 2;
         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
-    } else if (this->spec.channels == 3) {
-        format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
-    } else if (this->spec.channels == 4) {
-        format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
-              SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT;
-    } else {
-        format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
-              SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_FRONT_CENTER;
+        break;
     }
     }
 
 
     SLDataSource audioSrc = { &loc_bufq, &format_pcm };
     SLDataSource audioSrc = { &loc_bufq, &format_pcm };

+ 4 - 4
sdl.mod/SDL/src/audio/qsa/SDL_qsa_audio.c

@@ -619,8 +619,8 @@ QSA_Deinitialize(void)
 {
 {
     /* Clear devices array on shutdown */
     /* Clear devices array on shutdown */
     /* !!! FIXME: we zero these on init...any reason to do it here? */
     /* !!! FIXME: we zero these on init...any reason to do it here? */
-    SDL_zero(qsa_playback_device);
-    SDL_zero(qsa_capture_device);
+    SDL_zeroa(qsa_playback_device);
+    SDL_zeroa(qsa_capture_device);
     qsa_playback_devices = 0;
     qsa_playback_devices = 0;
     qsa_capture_devices = 0;
     qsa_capture_devices = 0;
 }
 }
@@ -629,8 +629,8 @@ static int
 QSA_Init(SDL_AudioDriverImpl * impl)
 QSA_Init(SDL_AudioDriverImpl * impl)
 {
 {
     /* Clear devices array */
     /* Clear devices array */
-    SDL_zero(qsa_playback_device);
-    SDL_zero(qsa_capture_device);
+    SDL_zeroa(qsa_playback_device);
+    SDL_zeroa(qsa_capture_device);
     qsa_playback_devices = 0;
     qsa_playback_devices = 0;
     qsa_capture_devices = 0;
     qsa_capture_devices = 0;
 
 

+ 3 - 19
sdl.mod/SDL/src/audio/wasapi/SDL_wasapi.c

@@ -161,21 +161,6 @@ WASAPI_DetectDevices(void)
     WASAPI_EnumerateEndpoints();
     WASAPI_EnumerateEndpoints();
 }
 }
 
 
-static int
-WASAPI_GetPendingBytes(_THIS)
-{
-    UINT32 frames = 0;
-
-    /* it's okay to fail here; we'll deal with failures in the audio thread. */
-    /* FIXME: need a lock around checking this->hidden->client */
-    if (this->hidden->client != NULL) {  /* definitely activated? */
-        if (FAILED(IAudioClient_GetCurrentPadding(this->hidden->client, &frames))) {
-            return 0;  /* oh well. */
-        }
-    }
-    return ((int) frames) * this->hidden->framesize;
-}
-
 static SDL_INLINE SDL_bool
 static SDL_INLINE SDL_bool
 WasapiFailed(_THIS, const HRESULT err)
 WasapiFailed(_THIS, const HRESULT err)
 {
 {
@@ -327,8 +312,8 @@ static void
 WASAPI_WaitDevice(_THIS)
 WASAPI_WaitDevice(_THIS)
 {
 {
     while (RecoverWasapiIfLost(this) && this->hidden->client && this->hidden->event) {
     while (RecoverWasapiIfLost(this) && this->hidden->client && this->hidden->event) {
-        /*SDL_Log("WAITDEVICE");*/
-        if (WaitForSingleObjectEx(this->hidden->event, INFINITE, FALSE) == WAIT_OBJECT_0) {
+        DWORD waitResult = WaitForSingleObjectEx(this->hidden->event, 200, FALSE);
+        if (waitResult == WAIT_OBJECT_0) {
             const UINT32 maxpadding = this->spec.samples;
             const UINT32 maxpadding = this->spec.samples;
             UINT32 padding = 0;
             UINT32 padding = 0;
             if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) {
             if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) {
@@ -337,7 +322,7 @@ WASAPI_WaitDevice(_THIS)
                     break;
                     break;
                 }
                 }
             }
             }
-        } else {
+        } else if (waitResult != WAIT_TIMEOUT) {
             /*SDL_Log("WASAPI FAILED EVENT!");*/
             /*SDL_Log("WASAPI FAILED EVENT!");*/
             IAudioClient_Stop(this->hidden->client);
             IAudioClient_Stop(this->hidden->client);
             SDL_OpenedAudioDeviceDisconnected(this);
             SDL_OpenedAudioDeviceDisconnected(this);
@@ -765,7 +750,6 @@ WASAPI_Init(SDL_AudioDriverImpl * impl)
     impl->OpenDevice = WASAPI_OpenDevice;
     impl->OpenDevice = WASAPI_OpenDevice;
     impl->PlayDevice = WASAPI_PlayDevice;
     impl->PlayDevice = WASAPI_PlayDevice;
     impl->WaitDevice = WASAPI_WaitDevice;
     impl->WaitDevice = WASAPI_WaitDevice;
-    impl->GetPendingBytes = WASAPI_GetPendingBytes;
     impl->GetDeviceBuf = WASAPI_GetDeviceBuf;
     impl->GetDeviceBuf = WASAPI_GetDeviceBuf;
     impl->CaptureFromDevice = WASAPI_CaptureFromDevice;
     impl->CaptureFromDevice = WASAPI_CaptureFromDevice;
     impl->FlushCapture = WASAPI_FlushCapture;
     impl->FlushCapture = WASAPI_FlushCapture;

+ 1 - 1
sdl.mod/SDL/src/audio/winmm/SDL_winmm.c

@@ -387,7 +387,7 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
 
 
-    SDL_zero(this->hidden->wavebuf);
+    SDL_zeroa(this->hidden->wavebuf);
     for (i = 0; i < NUM_BUFFERS; ++i) {
     for (i = 0; i < NUM_BUFFERS; ++i) {
         this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
         this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
         this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
         this->hidden->wavebuf[i].dwFlags = WHDR_DONE;

+ 78 - 20
sdl.mod/SDL/src/core/android/SDL_android.c

@@ -24,6 +24,7 @@
 #include "SDL_hints.h"
 #include "SDL_hints.h"
 #include "SDL_log.h"
 #include "SDL_log.h"
 #include "SDL_main.h"
 #include "SDL_main.h"
+#include "SDL_timer.h"
 
 
 #ifdef __ANDROID__
 #ifdef __ANDROID__
 
 
@@ -240,6 +241,8 @@ static jmethodID midSetSurfaceViewFormat;
 static jmethodID midSetActivityTitle;
 static jmethodID midSetActivityTitle;
 static jmethodID midSetWindowStyle;
 static jmethodID midSetWindowStyle;
 static jmethodID midSetOrientation;
 static jmethodID midSetOrientation;
+static jmethodID midMinimizeWindow;
+static jmethodID midShouldMinimizeOnFocusLoss;
 static jmethodID midGetContext;
 static jmethodID midGetContext;
 static jmethodID midIsTablet;
 static jmethodID midIsTablet;
 static jmethodID midIsAndroidTV;
 static jmethodID midIsAndroidTV;
@@ -490,6 +493,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
                                 "setWindowStyle","(Z)V");
                                 "setWindowStyle","(Z)V");
     midSetOrientation = (*env)->GetStaticMethodID(env, mActivityClass,
     midSetOrientation = (*env)->GetStaticMethodID(env, mActivityClass,
                                 "setOrientation","(IIZLjava/lang/String;)V");
                                 "setOrientation","(IIZLjava/lang/String;)V");
+    midMinimizeWindow = (*env)->GetStaticMethodID(env, mActivityClass,
+                                "minimizeWindow","()V");
+    midShouldMinimizeOnFocusLoss = (*env)->GetStaticMethodID(env, mActivityClass,
+                                "shouldMinimizeOnFocusLoss","()Z");
     midGetContext = (*env)->GetStaticMethodID(env, mActivityClass,
     midGetContext = (*env)->GetStaticMethodID(env, mActivityClass,
                                 "getContext","()Landroid/content/Context;");
                                 "getContext","()Landroid/content/Context;");
     midIsTablet = (*env)->GetStaticMethodID(env, mActivityClass,
     midIsTablet = (*env)->GetStaticMethodID(env, mActivityClass,
@@ -532,7 +539,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
 
 
 
 
     if (!midGetNativeSurface || !midSetSurfaceViewFormat ||
     if (!midGetNativeSurface || !midSetSurfaceViewFormat ||
-       !midSetActivityTitle || !midSetWindowStyle || !midSetOrientation || !midGetContext || !midIsTablet || !midIsAndroidTV || !midInitTouch ||
+       !midSetActivityTitle || !midSetWindowStyle || !midSetOrientation || !midMinimizeWindow || !midShouldMinimizeOnFocusLoss || !midGetContext || !midIsTablet || !midIsAndroidTV || !midInitTouch ||
        !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
        !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
        !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
        !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
        !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables || !midGetDisplayDPI ||
        !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables || !midGetDisplayDPI ||
@@ -622,6 +629,17 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls,
 
 
     library_file = (*env)->GetStringUTFChars(env, library, NULL);
     library_file = (*env)->GetStringUTFChars(env, library, NULL);
     library_handle = dlopen(library_file, RTLD_GLOBAL);
     library_handle = dlopen(library_file, RTLD_GLOBAL);
+
+    if (!library_handle) {
+        /* When deploying android app bundle format uncompressed native libs may not extract from apk to filesystem.
+           In this case we should use lib name without path. https://bugzilla.libsdl.org/show_bug.cgi?id=4739 */
+        const char *library_name = SDL_strrchr(library_file, '/');
+        if (library_name && *library_name) {
+            library_name += 1;
+            library_handle = dlopen(library_name, RTLD_GLOBAL);
+        }
+    }
+
     if (library_handle) {
     if (library_handle) {
         const char *function_name;
         const char *function_name;
         SDL_main_func SDL_main;
         SDL_main_func SDL_main;
@@ -705,6 +723,34 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
     SDL_SendDropComplete(NULL);
     SDL_SendDropComplete(NULL);
 }
 }
 
 
+/* Lock / Unlock Mutex */
+void Android_ActivityMutex_Lock() {
+    SDL_LockMutex(Android_ActivityMutex);
+}
+
+void Android_ActivityMutex_Unlock() {
+    SDL_UnlockMutex(Android_ActivityMutex);
+}
+
+/* Lock the Mutex when the Activity is in its 'Running' state */
+void Android_ActivityMutex_Lock_Running() {
+    int pauseSignaled = 0;
+    int resumeSignaled = 0;
+
+retry:
+
+    SDL_LockMutex(Android_ActivityMutex);
+
+    pauseSignaled = SDL_SemValue(Android_PauseSem);
+    resumeSignaled = SDL_SemValue(Android_ResumeSem);
+
+    if (pauseSignaled > resumeSignaled) {
+        SDL_UnlockMutex(Android_ActivityMutex);
+        SDL_Delay(50);
+        goto retry;
+    }
+}
+
 /* Set screen resolution */
 /* Set screen resolution */
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetScreenResolution)(
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetScreenResolution)(
                                     JNIEnv *env, jclass jcls,
                                     JNIEnv *env, jclass jcls,
@@ -1226,11 +1272,6 @@ static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder)
     }
     }
 }
 }
 
 
-static SDL_bool LocalReferenceHolder_IsActive(void)
-{
-    return (SDL_AtomicGet(&s_active) > 0);
-}
-
 ANativeWindow* Android_JNI_GetNativeWindow(void)
 ANativeWindow* Android_JNI_GetNativeWindow(void)
 {
 {
     ANativeWindow *anw = NULL;
     ANativeWindow *anw = NULL;
@@ -1270,7 +1311,7 @@ void Android_JNI_SetActivityTitle(const char *title)
 {
 {
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
 
 
-    jstring jtitle = (jstring)((*env)->NewStringUTF(env, title));
+    jstring jtitle = (*env)->NewStringUTF(env, title);
     (*env)->CallStaticBooleanMethod(env, mActivityClass, midSetActivityTitle, jtitle);
     (*env)->CallStaticBooleanMethod(env, mActivityClass, midSetActivityTitle, jtitle);
     (*env)->DeleteLocalRef(env, jtitle);
     (*env)->DeleteLocalRef(env, jtitle);
 }
 }
@@ -1285,11 +1326,23 @@ void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint)
 {
 {
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
 
 
-    jstring jhint = (jstring)((*env)->NewStringUTF(env, (hint ? hint : "")));
+    jstring jhint = (*env)->NewStringUTF(env, (hint ? hint : ""));
     (*env)->CallStaticVoidMethod(env, mActivityClass, midSetOrientation, w, h, (resizable? 1 : 0), jhint);
     (*env)->CallStaticVoidMethod(env, mActivityClass, midSetOrientation, w, h, (resizable? 1 : 0), jhint);
     (*env)->DeleteLocalRef(env, jhint);
     (*env)->DeleteLocalRef(env, jhint);
 }
 }
 
 
+void Android_JNI_MinizeWindow()
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    (*env)->CallStaticVoidMethod(env, mActivityClass, midMinimizeWindow);
+}
+
+SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss()
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    return (*env)->CallStaticBooleanMethod(env, mActivityClass, midShouldMinimizeOnFocusLoss);
+}
+
 SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
 SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
 {
 {
     int i;
     int i;
@@ -1318,7 +1371,6 @@ static jobject captureBuffer = NULL;
 int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec)
 int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec)
 {
 {
     int audioformat;
     int audioformat;
-    int numBufferFrames;
     jobject jbufobj = NULL;
     jobject jbufobj = NULL;
     jobject result;
     jobject result;
     int *resultElements;
     int *resultElements;
@@ -1423,7 +1475,6 @@ int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec)
         audioBufferFormat = audioformat;
         audioBufferFormat = audioformat;
         audioBuffer = jbufobj;
         audioBuffer = jbufobj;
     }
     }
-    numBufferFrames = (*env)->GetArrayLength(env, (jarray)jbufobj);
 
 
     if (!iscapture) {
     if (!iscapture) {
         isCopy = JNI_FALSE;
         isCopy = JNI_FALSE;
@@ -1525,7 +1576,7 @@ int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
         if (br > 0) {
         if (br > 0) {
             jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
             jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
             SDL_memcpy(buffer, ptr, br);
             SDL_memcpy(buffer, ptr, br);
-            (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
+            (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, ptr, JNI_ABORT);
         }
         }
         break;
         break;
     case ENCODING_PCM_16BIT:
     case ENCODING_PCM_16BIT:
@@ -1535,7 +1586,7 @@ int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
             jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
             jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
             br *= sizeof(Sint16);
             br *= sizeof(Sint16);
             SDL_memcpy(buffer, ptr, br);
             SDL_memcpy(buffer, ptr, br);
-            (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
+            (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, ptr, JNI_ABORT);
         }
         }
         break;
         break;
     case ENCODING_PCM_FLOAT:
     case ENCODING_PCM_FLOAT:
@@ -1545,7 +1596,7 @@ int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
             jfloat *ptr = (*env)->GetFloatArrayElements(env, (jfloatArray)captureBuffer, &isCopy);
             jfloat *ptr = (*env)->GetFloatArrayElements(env, (jfloatArray)captureBuffer, &isCopy);
             br *= sizeof(float);
             br *= sizeof(float);
             SDL_memcpy(buffer, ptr, br);
             SDL_memcpy(buffer, ptr, br);
-            (*env)->ReleaseFloatArrayElements(env, (jfloatArray)captureBuffer, (jfloat *)ptr, JNI_ABORT);
+            (*env)->ReleaseFloatArrayElements(env, (jfloatArray)captureBuffer, ptr, JNI_ABORT);
         }
         }
         break;
         break;
     default:
     default:
@@ -1634,7 +1685,7 @@ static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
     jthrowable exception;
     jthrowable exception;
 
 
     /* Detect mismatch LocalReferenceHolder_Init/Cleanup */
     /* Detect mismatch LocalReferenceHolder_Init/Cleanup */
-    SDL_assert(LocalReferenceHolder_IsActive());
+    SDL_assert(SDL_AtomicGet(&s_active) > 0);
 
 
     exception = (*env)->ExceptionOccurred(env);
     exception = (*env)->ExceptionOccurred(env);
     if (exception != NULL) {
     if (exception != NULL) {
@@ -1999,7 +2050,6 @@ Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence)
             default:
             default:
                 return SDL_SetError("Unknown value for 'whence'");
                 return SDL_SetError("Unknown value for 'whence'");
         }
         }
-        whence = SEEK_SET;
 
 
         ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
         ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
         if (ret == -1) return -1;
         if (ret == -1) return -1;
@@ -2327,11 +2377,19 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu
     button_texts = (*env)->NewObjectArray(env, messageboxdata->numbuttons,
     button_texts = (*env)->NewObjectArray(env, messageboxdata->numbuttons,
         clazz, NULL);
         clazz, NULL);
     for (i = 0; i < messageboxdata->numbuttons; ++i) {
     for (i = 0; i < messageboxdata->numbuttons; ++i) {
-        temp = messageboxdata->buttons[i].flags;
+        const SDL_MessageBoxButtonData *sdlButton;
+
+        if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
+            sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
+        } else {
+            sdlButton = &messageboxdata->buttons[i];
+        }
+
+        temp = sdlButton->flags;
         (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
         (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
-        temp = messageboxdata->buttons[i].buttonid;
+        temp = sdlButton->buttonid;
         (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
         (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
-        text = (*env)->NewStringUTF(env, messageboxdata->buttons[i].text);
+        text = (*env)->NewStringUTF(env, sdlButton->text);
         (*env)->SetObjectArrayElement(env, button_texts, i, text);
         (*env)->SetObjectArrayElement(env, button_texts, i, text);
         (*env)->DeleteLocalRef(env, text);
         (*env)->DeleteLocalRef(env, text);
     }
     }
@@ -2339,7 +2397,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu
     if (messageboxdata->colorScheme) {
     if (messageboxdata->colorScheme) {
         colors = (*env)->NewIntArray(env, SDL_MESSAGEBOX_COLOR_MAX);
         colors = (*env)->NewIntArray(env, SDL_MESSAGEBOX_COLOR_MAX);
         for (i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; ++i) {
         for (i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; ++i) {
-            temp = (0xFF << 24) |
+            temp = (0xFFU << 24) |
                    (messageboxdata->colorScheme->colors[i].r << 16) |
                    (messageboxdata->colorScheme->colors[i].r << 16) |
                    (messageboxdata->colorScheme->colors[i].g << 8) |
                    (messageboxdata->colorScheme->colors[i].g << 8) |
                    (messageboxdata->colorScheme->colors[i].b << 0);
                    (messageboxdata->colorScheme->colors[i].b << 0);
@@ -2446,7 +2504,7 @@ SDL_bool SDL_IsDeXMode(void)
 void SDL_AndroidBackButton(void)
 void SDL_AndroidBackButton(void)
 {
 {
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
-    return (*env)->CallStaticVoidMethod(env, mActivityClass, midManualBackButton);
+    (*env)->CallStaticVoidMethod(env, mActivityClass, midManualBackButton);
 }
 }
 
 
 const char * SDL_AndroidGetInternalStoragePath(void)
 const char * SDL_AndroidGetInternalStoragePath(void)

+ 6 - 0
sdl.mod/SDL/src/core/android/SDL_android.h

@@ -39,6 +39,8 @@ extern "C" {
 extern void Android_JNI_SetActivityTitle(const char *title);
 extern void Android_JNI_SetActivityTitle(const char *title);
 extern void Android_JNI_SetWindowStyle(SDL_bool fullscreen);
 extern void Android_JNI_SetWindowStyle(SDL_bool fullscreen);
 extern void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint);
 extern void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint);
+extern void Android_JNI_MinizeWindow(void);
+extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void);
 
 
 extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
 extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
 extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
 extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
@@ -129,6 +131,10 @@ SDL_bool SDL_IsAndroidTV(void);
 SDL_bool SDL_IsChromebook(void);
 SDL_bool SDL_IsChromebook(void);
 SDL_bool SDL_IsDeXMode(void);
 SDL_bool SDL_IsDeXMode(void);
 
 
+void Android_ActivityMutex_Lock(void);
+void Android_ActivityMutex_Unlock(void);
+void Android_ActivityMutex_Lock_Running(void);
+
 /* Ends C function definitions when using C++ */
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 #ifdef __cplusplus
 /* *INDENT-OFF* */
 /* *INDENT-OFF* */

+ 20 - 8
sdl.mod/SDL/src/core/linux/SDL_dbus.c

@@ -111,8 +111,19 @@ LoadDBUSLibrary(void)
 void
 void
 SDL_DBus_Init(void)
 SDL_DBus_Init(void)
 {
 {
-    if (!dbus.session_conn && LoadDBUSLibrary() != -1) {
+    static SDL_bool is_dbus_available = SDL_TRUE;
+    if (!is_dbus_available) {
+        return;  /* don't keep trying if this fails. */
+    }
+
+    if (!dbus.session_conn) {
         DBusError err;
         DBusError err;
+
+        if (LoadDBUSLibrary() == -1) {
+            is_dbus_available = SDL_FALSE;  /* can't load at all? Don't keep trying. */
+            return;  /* oh well */
+        }
+
         dbus.error_init(&err);
         dbus.error_init(&err);
         dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
         dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
         if (!dbus.error_is_set(&err)) {
         if (!dbus.error_is_set(&err)) {
@@ -121,6 +132,7 @@ SDL_DBus_Init(void)
         if (dbus.error_is_set(&err)) {
         if (dbus.error_is_set(&err)) {
             dbus.error_free(&err);
             dbus.error_free(&err);
             SDL_DBus_Quit();
             SDL_DBus_Quit();
+            is_dbus_available = SDL_FALSE;
             return;  /* oh well */
             return;  /* oh well */
         }
         }
         dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
         dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0);
@@ -154,15 +166,11 @@ SDL_DBus_Quit(void)
 SDL_DBusContext *
 SDL_DBusContext *
 SDL_DBus_GetContext(void)
 SDL_DBus_GetContext(void)
 {
 {
-    if(!dbus_handle || !dbus.session_conn){
+    if (!dbus_handle || !dbus.session_conn) {
         SDL_DBus_Init();
         SDL_DBus_Init();
     }
     }
     
     
-    if(dbus_handle && dbus.session_conn){
-        return &dbus;
-    } else {
-        return NULL;
-    }
+    return (dbus_handle && dbus.session_conn) ? &dbus : NULL;
 }
 }
 
 
 static SDL_bool
 static SDL_bool
@@ -310,7 +318,11 @@ SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface
 void
 void
 SDL_DBus_ScreensaverTickle(void)
 SDL_DBus_ScreensaverTickle(void)
 {
 {
-    SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
+    if (screensaver_cookie == 0) {  /* no need to tickle if we're inhibiting. */
+        /* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */
+        SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
+        SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
+    }
 }
 }
 
 
 SDL_bool
 SDL_bool

+ 57 - 22
sdl.mod/SDL/src/core/linux/SDL_evdev.c

@@ -129,6 +129,14 @@ static Uint8 EVDEV_MouseButtons[] = {
     SDL_BUTTON_X2 + 3           /*  BTN_TASK        0x117 */
     SDL_BUTTON_X2 + 3           /*  BTN_TASK        0x117 */
 };
 };
 
 
+static int
+SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled)
+{
+    /* Mice already send relative events through this interface */
+    return 0;
+}
+
+
 int
 int
 SDL_EVDEV_Init(void)
 SDL_EVDEV_Init(void)
 {
 {
@@ -162,6 +170,8 @@ SDL_EVDEV_Init(void)
         _this->kbd = SDL_EVDEV_kbd_init();
         _this->kbd = SDL_EVDEV_kbd_init();
     }
     }
 
 
+    SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode;
+
     _this->ref_count += 1;
     _this->ref_count += 1;
 
 
     return 0;
     return 0;
@@ -272,6 +282,12 @@ SDL_EVDEV_Poll(void)
                        position is sent in EV_ABS ABS_X/ABS_Y, switching to
                        position is sent in EV_ABS ABS_X/ABS_Y, switching to
                        next finger after earlist is released) */
                        next finger after earlist is released) */
                     if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
                     if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
+                        if (item->touchscreen_data->max_slots == 1) {
+                            if (events[i].value)
+                                item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
+                            else
+                                item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_UP;
+                        }
                         break;
                         break;
                     }
                     }
 
 
@@ -328,14 +344,20 @@ SDL_EVDEV_Poll(void)
                         }
                         }
                         break;
                         break;
                     case ABS_X:
                     case ABS_X:
-                        if (item->is_touchscreen) /* FIXME: temp hack */
-                            break;
-                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
+                        if (item->is_touchscreen) {
+                            if (item->touchscreen_data->max_slots != 1)
+                                break;
+                            item->touchscreen_data->slots[0].x = events[i].value;
+                        } else
+                            SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
                         break;
                         break;
                     case ABS_Y:
                     case ABS_Y:
-                        if (item->is_touchscreen) /* FIXME: temp hack */
-                            break;
-                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
+                        if (item->is_touchscreen) {
+                            if (item->touchscreen_data->max_slots != 1)
+                                break;
+                            item->touchscreen_data->slots[0].y = events[i].value;
+                        } else
+                            SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
                         break;
                         break;
                     default:
                     default:
                         break;
                         break;
@@ -379,18 +401,21 @@ SDL_EVDEV_Poll(void)
                                 norm_pressure = 1.0f;
                                 norm_pressure = 1.0f;
                             }
                             }
 
 
+                            /* FIXME: the touch's window shouldn't be null, but
+                             * the coordinate space of touch positions needs to
+                             * be window-relative in that case. */
                             switch(item->touchscreen_data->slots[j].delta) {
                             switch(item->touchscreen_data->slots[j].delta) {
                             case EVDEV_TOUCH_SLOTDELTA_DOWN:
                             case EVDEV_TOUCH_SLOTDELTA_DOWN:
-                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, norm_pressure);
+                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_TRUE, norm_x, norm_y, norm_pressure);
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 break;
                                 break;
                             case EVDEV_TOUCH_SLOTDELTA_UP:
                             case EVDEV_TOUCH_SLOTDELTA_UP:
-                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, norm_pressure);
+                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_FALSE, norm_x, norm_y, norm_pressure);
                                 item->touchscreen_data->slots[j].tracking_id = -1;
                                 item->touchscreen_data->slots[j].tracking_id = -1;
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 break;
                                 break;
                             case EVDEV_TOUCH_SLOTDELTA_MOVE:
                             case EVDEV_TOUCH_SLOTDELTA_MOVE:
-                                SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, norm_pressure);
+                                SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, norm_x, norm_y, norm_pressure);
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 break;
                                 break;
                             default:
                             default:
@@ -444,6 +469,7 @@ static int
 SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 {
 {
     int ret, i;
     int ret, i;
+    unsigned long xreq, yreq;
     char name[64];
     char name[64];
     struct input_absinfo abs_info;
     struct input_absinfo abs_info;
 
 
@@ -466,7 +492,24 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
 
 
-    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
+    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
+    if (ret < 0) {
+        SDL_free(item->touchscreen_data->name);
+        SDL_free(item->touchscreen_data);
+        return SDL_SetError("Failed to get evdev touchscreen limits");
+    }
+
+    if (abs_info.maximum == 0) {
+        item->touchscreen_data->max_slots = 1;
+        xreq = EVIOCGABS(ABS_X);
+        yreq = EVIOCGABS(ABS_Y);
+    } else {
+        item->touchscreen_data->max_slots = abs_info.maximum + 1;
+        xreq = EVIOCGABS(ABS_MT_POSITION_X);
+        yreq = EVIOCGABS(ABS_MT_POSITION_Y);
+    }
+
+    ret = ioctl(item->fd, xreq, &abs_info);
     if (ret < 0) {
     if (ret < 0) {
         SDL_free(item->touchscreen_data->name);
         SDL_free(item->touchscreen_data->name);
         SDL_free(item->touchscreen_data);
         SDL_free(item->touchscreen_data);
@@ -476,7 +519,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
     item->touchscreen_data->max_x = abs_info.maximum;
     item->touchscreen_data->max_x = abs_info.maximum;
     item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
     item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
 
 
-    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
+    ret = ioctl(item->fd, yreq, &abs_info);
     if (ret < 0) {
     if (ret < 0) {
         SDL_free(item->touchscreen_data->name);
         SDL_free(item->touchscreen_data->name);
         SDL_free(item->touchscreen_data);
         SDL_free(item->touchscreen_data);
@@ -496,14 +539,6 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
     item->touchscreen_data->max_pressure = abs_info.maximum;
     item->touchscreen_data->max_pressure = abs_info.maximum;
     item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
     item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
 
 
-    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
-    if (ret < 0) {
-        SDL_free(item->touchscreen_data->name);
-        SDL_free(item->touchscreen_data);
-        return SDL_SetError("Failed to get evdev touchscreen limits");
-    }
-    item->touchscreen_data->max_slots = abs_info.maximum + 1;
-
     item->touchscreen_data->slots = SDL_calloc(
     item->touchscreen_data->slots = SDL_calloc(
         item->touchscreen_data->max_slots,
         item->touchscreen_data->max_slots,
         sizeof(*item->touchscreen_data->slots));
         sizeof(*item->touchscreen_data->slots));
@@ -556,8 +591,8 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
      *
      *
      * this is the structure we're trying to emulate
      * this is the structure we're trying to emulate
      */
      */
-    __u32* mt_req_code;
-    __s32* mt_req_values;
+    Uint32* mt_req_code;
+    Sint32* mt_req_values;
     size_t mt_req_size;
     size_t mt_req_size;
 
 
     /* TODO: sync devices other than touchscreen */
     /* TODO: sync devices other than touchscreen */
@@ -572,7 +607,7 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
         return;
         return;
     }
     }
 
 
-    mt_req_values = (__s32*)mt_req_code + 1;
+    mt_req_values = (Sint32*)mt_req_code + 1;
 
 
     *mt_req_code = ABS_MT_TRACKING_ID;
     *mt_req_code = ABS_MT_TRACKING_ID;
     ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
     ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);

+ 0 - 1
sdl.mod/SDL/src/core/linux/SDL_evdev_kbd.c

@@ -216,7 +216,6 @@ static void kbd_cleanup(void)
     }
     }
     kbd_cleanup_state = NULL;
     kbd_cleanup_state = NULL;
 
 
-    fprintf(stderr, "(SDL restoring keyboard) ");
     ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
     ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
 }
 }
 
 

+ 13 - 9
sdl.mod/SDL/src/core/linux/SDL_threadprio.c

@@ -22,14 +22,17 @@
 
 
 #ifdef __LINUX__
 #ifdef __LINUX__
 
 
+#include "SDL_stdinc.h"
+
 #if !SDL_THREADS_DISABLED
 #if !SDL_THREADS_DISABLED
 #include <sys/time.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/resource.h>
 #include <pthread.h>
 #include <pthread.h>
 #include "SDL_system.h"
 #include "SDL_system.h"
 
 
-#if SDL_USE_LIBDBUS
 #include "SDL_dbus.h"
 #include "SDL_dbus.h"
+
+#if SDL_USE_LIBDBUS
 /* d-bus queries to org.freedesktop.RealtimeKit1. */
 /* d-bus queries to org.freedesktop.RealtimeKit1. */
 #define RTKIT_DBUS_NODE "org.freedesktop.RealtimeKit1"
 #define RTKIT_DBUS_NODE "org.freedesktop.RealtimeKit1"
 #define RTKIT_DBUS_PATH "/org/freedesktop/RealtimeKit1"
 #define RTKIT_DBUS_PATH "/org/freedesktop/RealtimeKit1"
@@ -86,14 +89,15 @@ SDL_LinuxSetThreadPriority(Sint64 threadID, int priority)
     }
     }
 
 
 #if SDL_USE_LIBDBUS
 #if SDL_USE_LIBDBUS
-    /* Note that this fails if you're trying to set high priority
-       and you don't have root permission. BUT DON'T RUN AS ROOT!
-
-       You can grant the ability to increase thread priority by
-       running the following command on your application binary:
-          sudo setcap 'cap_sys_nice=eip' <application>
-
-       Let's try setting priority with RealtimeKit...
+    /* Note that this fails you most likely:
+         * Have your process's scheduler incorrectly configured.
+           See the requirements at:
+           http://git.0pointer.net/rtkit.git/tree/README#n16
+         * Encountered dbus/polkit security restrictions. Note
+           that the RealtimeKit1 dbus endpoint is inaccessible
+           over ssh connections for most common distro configs.
+           You might want to check your local config for details:
+           /usr/share/polkit-1/actions/org.freedesktop.RealtimeKit1.policy
 
 
        README and sample code at: http://git.0pointer.net/rtkit.git
        README and sample code at: http://git.0pointer.net/rtkit.git
     */
     */

+ 7 - 0
sdl.mod/SDL/src/core/linux/SDL_udev.c

@@ -34,6 +34,7 @@
 #include "SDL_assert.h"
 #include "SDL_assert.h"
 #include "SDL_loadso.h"
 #include "SDL_loadso.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
+#include "SDL_hints.h"
 #include "../unix/SDL_poll.h"
 #include "../unix/SDL_poll.h"
 
 
 static const char *SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" };
 static const char *SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" };
@@ -420,6 +421,12 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
         if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
         if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
             devclass |= SDL_UDEV_DEVICE_JOYSTICK;
             devclass |= SDL_UDEV_DEVICE_JOYSTICK;
         }
         }
+
+        val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER");
+        if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE) &&
+            val != NULL && SDL_strcmp(val, "1") == 0 ) {
+            devclass |= SDL_UDEV_DEVICE_JOYSTICK;
+	}
         
         
         val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
         val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
         if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
         if (val != NULL && SDL_strcmp(val, "1") == 0 ) {

+ 65 - 4
sdl.mod/SDL/src/cpuinfo/SDL_cpuinfo.c

@@ -22,7 +22,6 @@
 #include "SDL_config.h"
 #include "SDL_config.h"
 #else
 #else
 #include "../SDL_internal.h"
 #include "../SDL_internal.h"
-#include "SDL_simd.h"
 #endif
 #endif
 
 
 #if defined(__WIN32__) || defined(__WINRT__)
 #if defined(__WIN32__) || defined(__WINRT__)
@@ -68,6 +67,13 @@
 #ifndef AT_HWCAP
 #ifndef AT_HWCAP
 #define AT_HWCAP 16
 #define AT_HWCAP 16
 #endif
 #endif
+#ifndef AT_PLATFORM
+#define AT_PLATFORM 15
+#endif
+/* Prevent compilation error when including elf.h would also try to define AT_* as an enum */
+#ifndef AT_NULL
+#define AT_NULL 0
+#endif
 #ifndef HWCAP_NEON
 #ifndef HWCAP_NEON
 #define HWCAP_NEON (1 << 12)
 #define HWCAP_NEON (1 << 12)
 #endif
 #endif
@@ -97,6 +103,7 @@
 #define CPU_HAS_AVX2    (1 << 10)
 #define CPU_HAS_AVX2    (1 << 10)
 #define CPU_HAS_NEON    (1 << 11)
 #define CPU_HAS_NEON    (1 << 11)
 #define CPU_HAS_AVX512F (1 << 12)
 #define CPU_HAS_AVX512F (1 << 12)
+#define CPU_HAS_ARM_SIMD (1 << 13)
 
 
 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
 #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
 /* This is the brute force way of detecting instruction sets...
 /* This is the brute force way of detecting instruction sets...
@@ -326,7 +333,50 @@ CPU_haveAltiVec(void)
     return altivec;
     return altivec;
 }
 }
 
 
-#if defined(__LINUX__) && defined(__ARM_ARCH) && !defined(HAVE_GETAUXVAL)
+#if !defined(__ARM_ARCH)
+static SDL_bool CPU_haveARMSIMD(void) { return 0; }
+
+#elif defined(__linux__)
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <elf.h>
+
+static SDL_bool
+CPU_haveARMSIMD(void)
+{
+    int arm_simd = 0;
+    int fd;
+
+    fd = open("/proc/self/auxv", O_RDONLY);
+    if (fd >= 0)
+    {
+        Elf32_auxv_t aux;
+        while (read(fd, &aux, sizeof aux) == sizeof aux)
+        {
+            if (aux.a_type == AT_PLATFORM)
+            {
+                const char *plat = (const char *) aux.a_un.a_val;
+                arm_simd = strncmp(plat, "v6l", 3) == 0 ||
+                           strncmp(plat, "v7l", 3) == 0;
+            }
+        }
+        close(fd);
+    }
+    return arm_simd;
+}
+
+#else
+static SDL_bool
+CPU_haveARMSIMD(void)
+{
+    #warning SDL_HasARMSIMD is not implemented for this ARM platform. Write me.
+    return 0;
+}
+#endif
+
+#if (defined(__LINUX__) || defined(__ANDROID__)) && defined(__ARM_ARCH) && !defined(HAVE_GETAUXVAL)
 static int
 static int
 readProcAuxvForNeon(void)
 readProcAuxvForNeon(void)
 {
 {
@@ -603,7 +653,7 @@ SDL_GetCPUCacheLineSize(void)
     if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
     if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
         cpuid(0x00000001, a, b, c, d);
         cpuid(0x00000001, a, b, c, d);
         return (((b >> 8) & 0xff) * 8);
         return (((b >> 8) & 0xff) * 8);
-    } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
+    } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0 || SDL_strcmp(cpuType, "HygonGenuine") == 0) {
         cpuid(0x80000005, a, b, c, d);
         cpuid(0x80000005, a, b, c, d);
         return (c & 0xff);
         return (c & 0xff);
     } else {
     } else {
@@ -621,7 +671,7 @@ SDL_GetCPUFeatures(void)
     if (SDL_CPUFeatures == 0xFFFFFFFF) {
     if (SDL_CPUFeatures == 0xFFFFFFFF) {
         CPU_calcCPUIDFeatures();
         CPU_calcCPUIDFeatures();
         SDL_CPUFeatures = 0;
         SDL_CPUFeatures = 0;
-        SDL_SIMDAlignment = 4;  /* a good safe base value */
+        SDL_SIMDAlignment = sizeof(void *);  /* a good safe base value */
         if (CPU_haveRDTSC()) {
         if (CPU_haveRDTSC()) {
             SDL_CPUFeatures |= CPU_HAS_RDTSC;
             SDL_CPUFeatures |= CPU_HAS_RDTSC;
         }
         }
@@ -669,6 +719,10 @@ SDL_GetCPUFeatures(void)
             SDL_CPUFeatures |= CPU_HAS_AVX512F;
             SDL_CPUFeatures |= CPU_HAS_AVX512F;
             SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 64);
             SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 64);
         }
         }
+        if (CPU_haveARMSIMD()) {
+            SDL_CPUFeatures |= CPU_HAS_ARM_SIMD;
+            SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16);
+        }
         if (CPU_haveNEON()) {
         if (CPU_haveNEON()) {
             SDL_CPUFeatures |= CPU_HAS_NEON;
             SDL_CPUFeatures |= CPU_HAS_NEON;
             SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16);
             SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16);
@@ -750,6 +804,12 @@ SDL_HasAVX512F(void)
     return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX512F);
     return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX512F);
 }
 }
 
 
+SDL_bool
+SDL_HasARMSIMD(void)
+{
+    return CPU_FEATURE_AVAILABLE(CPU_HAS_ARM_SIMD);
+}
+
 SDL_bool
 SDL_bool
 SDL_HasNEON(void)
 SDL_HasNEON(void)
 {
 {
@@ -871,6 +931,7 @@ main()
     printf("AVX: %d\n", SDL_HasAVX());
     printf("AVX: %d\n", SDL_HasAVX());
     printf("AVX2: %d\n", SDL_HasAVX2());
     printf("AVX2: %d\n", SDL_HasAVX2());
     printf("AVX-512F: %d\n", SDL_HasAVX512F());
     printf("AVX-512F: %d\n", SDL_HasAVX512F());
+    printf("ARM SIMD: %d\n", SDL_HasARMSIMD());
     printf("NEON: %d\n", SDL_HasNEON());
     printf("NEON: %d\n", SDL_HasNEON());
     printf("RAM: %d MB\n", SDL_GetSystemRAM());
     printf("RAM: %d MB\n", SDL_GetSystemRAM());
     return 0;
     return 0;

+ 0 - 88
sdl.mod/SDL/src/cpuinfo/SDL_simd.h

@@ -1,88 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2019 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "SDL.h"
-#include "../SDL_internal.h"
-
-/**
- * \brief Report the alignment this system needs for SIMD allocations.
- *
- * This will return the minimum number of bytes to which a pointer must be
- *  aligned to be compatible with SIMD instructions on the current machine.
- *  For example, if the machine supports SSE only, it will return 16, but if
- *  it supports AVX-512F, it'll return 64 (etc). This only reports values for
- *  instruction sets SDL knows about, so if your SDL build doesn't have
- *  SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and
- *  not 64 for the AVX-512 instructions that exist but SDL doesn't know about.
- *  Plan accordingly.
- */
-extern size_t SDL_SIMDGetAlignment(void);
-
-/**
- * \brief Allocate memory in a SIMD-friendly way.
- *
- * This will allocate a block of memory that is suitable for use with SIMD
- *  instructions. Specifically, it will be properly aligned and padded for
- *  the system's supported vector instructions.
- *
- * The memory returned will be padded such that it is safe to read or write
- *  an incomplete vector at the end of the memory block. This can be useful
- *  so you don't have to drop back to a scalar fallback at the end of your
- *  SIMD processing loop to deal with the final elements without overflowing
- *  the allocated buffer.
- *
- * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free()
- *  or delete[], etc.
- *
- * Note that SDL will only deal with SIMD instruction sets it is aware of;
- *  for example, SDL 2.0.8 knows that SSE wants 16-byte vectors
- *  (SDL_HasSSE()), and AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't
- *  know that AVX-512 wants 64. To be clear: if you can't decide to use an
- *  instruction set with an SDL_Has*() function, don't use that instruction
- *  set with memory allocated through here.
- *
- * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't
- *  out of memory.
- *
- *  \param len The length, in bytes, of the block to allocated. The actual
- *             allocated block might be larger due to padding, etc.
- * \return Pointer to newly-allocated block, NULL if out of memory.
- *
- * \sa SDL_SIMDAlignment
- * \sa SDL_SIMDFree
- */
-extern void * SDL_SIMDAlloc(const size_t len);
-
-/**
- * \brief Deallocate memory obtained from SDL_SIMDAlloc
- *
- * It is not valid to use this function on a pointer from anything but
- *  SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
- *  SDL_malloc, memalign, new[], etc.
- *
- * However, SDL_SIMDFree(NULL) is a legal no-op.
- *
- * \sa SDL_SIMDAlloc
- */
-extern void SDL_SIMDFree(void *ptr);
-
-/* vi: set ts=4 sw=4 expandtab: */
-

+ 42 - 13
sdl.mod/SDL/src/dynapi/SDL_dynapi.c

@@ -251,12 +251,12 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
     HMODULE hmodule;
     HMODULE hmodule;
     PFN retval = NULL;
     PFN retval = NULL;
     char error[256];
     char error[256];
-    if (DosLoadModule(&error, sizeof(error), fname, &hmodule) == NO_ERROR) {
+    if (DosLoadModule(error, sizeof(error), fname, &hmodule) == NO_ERROR) {
         if (DosQueryProcAddr(hmodule, 0, sym, &retval) != NO_ERROR) {
         if (DosQueryProcAddr(hmodule, 0, sym, &retval) != NO_ERROR) {
             DosFreeModule(hmodule);
             DosFreeModule(hmodule);
         }
         }
     }
     }
-    return (void *) retval;
+    return (void *)retval;
 }
 }
 
 
 #else
 #else
@@ -264,29 +264,58 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
 #endif
 #endif
 
 
 
 
+static void dynapi_warn(const char *msg)
+{
+    const char *caption = "SDL Dynamic API Failure!";
+    /* SDL_ShowSimpleMessageBox() is a too heavy for here. */
+    #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
+    MessageBoxA(NULL, msg, caption, MB_OK | MB_ICONERROR);
+    #else
+    fprintf(stderr, "\n\n%s\n%s\n\n", caption, msg);
+    fflush(stderr);
+    #endif
+}
+
+/* This is not declared in any header, although it is shared between some
+    parts of SDL, because we don't want anything calling it without an
+    extremely good reason. */
+#if defined(__WATCOMC__)
+void SDL_ExitProcess(int exitcode);
+#pragma aux SDL_ExitProcess aborts;
+#endif
+SDL_NORETURN void SDL_ExitProcess(int exitcode);
+
+
 static void
 static void
 SDL_InitDynamicAPILocked(void)
 SDL_InitDynamicAPILocked(void)
 {
 {
     const char *libname = SDL_getenv_REAL("SDL_DYNAMIC_API");
     const char *libname = SDL_getenv_REAL("SDL_DYNAMIC_API");
     SDL_DYNAPI_ENTRYFN entry = NULL;  /* funcs from here by default. */
     SDL_DYNAPI_ENTRYFN entry = NULL;  /* funcs from here by default. */
+    SDL_bool use_internal = SDL_TRUE;
 
 
     if (libname) {
     if (libname) {
         entry = (SDL_DYNAPI_ENTRYFN) get_sdlapi_entry(libname, "SDL_DYNAPI_entry");
         entry = (SDL_DYNAPI_ENTRYFN) get_sdlapi_entry(libname, "SDL_DYNAPI_entry");
         if (!entry) {
         if (!entry) {
-            /* !!! FIXME: fail to startup here instead? */
-            /* !!! FIXME: definitely warn user. */
-            /* Just fill in the function pointers from this library. */
+            dynapi_warn("Couldn't load overriding SDL library. Please fix or remove the SDL_DYNAMIC_API environment variable. Using the default SDL.");
+            /* Just fill in the function pointers from this library, later. */
         }
         }
     }
     }
 
 
-    if (!entry || (entry(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table)) < 0)) {
-        /* !!! FIXME: fail to startup here instead? */
-        /* !!! FIXME: definitely warn user. */
-        /* Just fill in the function pointers from this library. */
-        if (!entry) {
-            if (!initialize_jumptable(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table))) {
-                /* !!! FIXME: now we're screwed. Should definitely abort now. */
-            }
+    if (entry) {
+        if (entry(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table)) < 0) {
+            dynapi_warn("Couldn't override SDL library. Using a newer SDL build might help. Please fix or remove the SDL_DYNAMIC_API environment variable. Using the default SDL.");
+            /* Just fill in the function pointers from this library, later. */
+        } else {
+            use_internal = SDL_FALSE;   /* We overrode SDL! Don't use the internal version! */
+        }
+    }
+
+    /* Just fill in the function pointers from this library. */
+    if (use_internal) {
+        if (initialize_jumptable(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table)) < 0) {
+            /* Now we're screwed. Should definitely abort now. */
+            dynapi_warn("Failed to initialize internal SDL dynapi. As this would otherwise crash, we have to abort now.");
+            SDL_ExitProcess(86);
         }
         }
     }
     }
 
 

+ 14 - 0
sdl.mod/SDL/src/dynapi/SDL_dynapi_overrides.h

@@ -714,3 +714,17 @@
 #define SDL_RenderCopyExF SDL_RenderCopyExF_REAL
 #define SDL_RenderCopyExF SDL_RenderCopyExF_REAL
 #define SDL_GetTouchDeviceType SDL_GetTouchDeviceType_REAL
 #define SDL_GetTouchDeviceType SDL_GetTouchDeviceType_REAL
 #define SDL_UIKitRunApp SDL_UIKitRunApp_REAL
 #define SDL_UIKitRunApp SDL_UIKitRunApp_REAL
+#define SDL_SIMDGetAlignment SDL_SIMDGetAlignment_REAL
+#define SDL_SIMDAlloc SDL_SIMDAlloc_REAL
+#define SDL_SIMDFree SDL_SIMDFree_REAL
+#define SDL_RWsize SDL_RWsize_REAL
+#define SDL_RWseek SDL_RWseek_REAL
+#define SDL_RWtell SDL_RWtell_REAL
+#define SDL_RWread SDL_RWread_REAL
+#define SDL_RWwrite SDL_RWwrite_REAL
+#define SDL_RWclose SDL_RWclose_REAL
+#define SDL_LoadFile SDL_LoadFile_REAL
+#define SDL_Metal_CreateView SDL_Metal_CreateView_REAL
+#define SDL_Metal_DestroyView SDL_Metal_DestroyView_REAL
+#define SDL_LockTextureToSurface SDL_LockTextureToSurface_REAL
+#define SDL_HasARMSIMD SDL_HasARMSIMD_REAL

+ 15 - 1
sdl.mod/SDL/src/dynapi/SDL_dynapi_procs.h

@@ -715,7 +715,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX512F,(void),(),return)
 #ifdef __ANDROID__
 #ifdef __ANDROID__
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return)
-SDL_DYNAPI_PROC(void,SDL_AndroidBackButton,(void),(),return)
+SDL_DYNAPI_PROC(void,SDL_AndroidBackButton,(void),(),)
 #endif
 #endif
 SDL_DYNAPI_PROC(double,SDL_exp,(double a),(a),return)
 SDL_DYNAPI_PROC(double,SDL_exp,(double a),(a),return)
 SDL_DYNAPI_PROC(float,SDL_expf,(float a),(a),return)
 SDL_DYNAPI_PROC(float,SDL_expf,(float a),(a),return)
@@ -770,3 +770,17 @@ SDL_DYNAPI_PROC(SDL_TouchDeviceType,SDL_GetTouchDeviceType,(SDL_TouchID a),(a),r
 #ifdef __IPHONEOS__
 #ifdef __IPHONEOS__
 SDL_DYNAPI_PROC(int,SDL_UIKitRunApp,(int a, char *b, SDL_main_func c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_UIKitRunApp,(int a, char *b, SDL_main_func c),(a,b,c),return)
 #endif
 #endif
+SDL_DYNAPI_PROC(size_t,SDL_SIMDGetAlignment,(void),(),return)
+SDL_DYNAPI_PROC(void*,SDL_SIMDAlloc,(const size_t a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_SIMDFree,(void *a),(a),)
+SDL_DYNAPI_PROC(Sint64,SDL_RWsize,(SDL_RWops *a),(a),return)
+SDL_DYNAPI_PROC(Sint64,SDL_RWseek,(SDL_RWops *a, Sint64 b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(Sint64,SDL_RWtell,(SDL_RWops *a),(a),return)
+SDL_DYNAPI_PROC(size_t,SDL_RWread,(SDL_RWops *a, void *b, size_t c, size_t d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(size_t,SDL_RWwrite,(SDL_RWops *a, const void *b, size_t c, size_t d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(int,SDL_RWclose,(SDL_RWops *a),(a),return)
+SDL_DYNAPI_PROC(void*,SDL_LoadFile,(const char *a, size_t *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_MetalView,SDL_Metal_CreateView,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_Metal_DestroyView,(SDL_MetalView a),(a),)
+SDL_DYNAPI_PROC(int,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_HasARMSIMD,(void),(),return)

+ 3 - 3
sdl.mod/SDL/src/dynapi/gendynapi.pl

@@ -49,9 +49,9 @@ open(SDL_DYNAPI_PROCS_H, '>>', $sdl_dynapi_procs_h) or die("Can't open $sdl_dyna
 open(SDL_DYNAPI_OVERRIDES_H, '>>', $sdl_dynapi_overrides_h) or die("Can't open $sdl_dynapi_overrides_h: $!\n");
 open(SDL_DYNAPI_OVERRIDES_H, '>>', $sdl_dynapi_overrides_h) or die("Can't open $sdl_dynapi_overrides_h: $!\n");
 
 
 opendir(HEADERS, 'include') or die("Can't open include dir: $!\n");
 opendir(HEADERS, 'include') or die("Can't open include dir: $!\n");
-while (readdir(HEADERS)) {
-    next if not /\.h\Z/;
-    my $header = "include/$_";
+while (my $d = readdir(HEADERS)) {
+    next if not $d =~ /\.h\Z/;
+    my $header = "include/$d";
     open(HEADER, '<', $header) or die("Can't open $header: $!\n");
     open(HEADER, '<', $header) or die("Can't open $header: $!\n");
     while (<HEADER>) {
     while (<HEADER>) {
         chomp;
         chomp;

+ 9 - 9
sdl.mod/SDL/src/events/SDL_events.c

@@ -278,9 +278,9 @@ SDL_LogEvent(const SDL_Event *event)
         #undef PRINT_CONTROLLERDEV_EVENT
         #undef PRINT_CONTROLLERDEV_EVENT
 
 
         #define PRINT_FINGER_EVENT(event) \
         #define PRINT_FINGER_EVENT(event) \
-            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%lld fingerid=%lld x=%f y=%f dx=%f dy=%f pressure=%f)", \
-                (uint) event->tfinger.timestamp, (long long) event->tfinger.touchId, \
-                (long long) event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \
+            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" fingerid=%"SDL_PRIs64" x=%f y=%f dx=%f dy=%f pressure=%f)", \
+                (uint) event->tfinger.timestamp, event->tfinger.touchId, \
+                event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \
                 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
                 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
         SDL_EVENT_CASE(SDL_FINGERDOWN) PRINT_FINGER_EVENT(event); break;
         SDL_EVENT_CASE(SDL_FINGERDOWN) PRINT_FINGER_EVENT(event); break;
         SDL_EVENT_CASE(SDL_FINGERUP) PRINT_FINGER_EVENT(event); break;
         SDL_EVENT_CASE(SDL_FINGERUP) PRINT_FINGER_EVENT(event); break;
@@ -288,17 +288,17 @@ SDL_LogEvent(const SDL_Event *event)
         #undef PRINT_FINGER_EVENT
         #undef PRINT_FINGER_EVENT
 
 
         #define PRINT_DOLLAR_EVENT(event) \
         #define PRINT_DOLLAR_EVENT(event) \
-            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%lld gestureid=%lld numfingers=%u error=%f x=%f y=%f)", \
-                (uint) event->dgesture.timestamp, (long long) event->dgesture.touchId, \
-                (long long) event->dgesture.gestureId, (uint) event->dgesture.numFingers, \
+            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" gestureid=%"SDL_PRIs64" numfingers=%u error=%f x=%f y=%f)", \
+                (uint) event->dgesture.timestamp, event->dgesture.touchId, \
+                event->dgesture.gestureId, (uint) event->dgesture.numFingers, \
                 event->dgesture.error, event->dgesture.x, event->dgesture.y);
                 event->dgesture.error, event->dgesture.x, event->dgesture.y);
         SDL_EVENT_CASE(SDL_DOLLARGESTURE) PRINT_DOLLAR_EVENT(event); break;
         SDL_EVENT_CASE(SDL_DOLLARGESTURE) PRINT_DOLLAR_EVENT(event); break;
         SDL_EVENT_CASE(SDL_DOLLARRECORD) PRINT_DOLLAR_EVENT(event); break;
         SDL_EVENT_CASE(SDL_DOLLARRECORD) PRINT_DOLLAR_EVENT(event); break;
         #undef PRINT_DOLLAR_EVENT
         #undef PRINT_DOLLAR_EVENT
 
 
         SDL_EVENT_CASE(SDL_MULTIGESTURE)
         SDL_EVENT_CASE(SDL_MULTIGESTURE)
-            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%lld dtheta=%f ddist=%f x=%f y=%f numfingers=%u)",
-                (uint) event->mgesture.timestamp, (long long) event->mgesture.touchId,
+            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" dtheta=%f ddist=%f x=%f y=%f numfingers=%u)",
+                (uint) event->mgesture.timestamp, event->mgesture.touchId,
                 event->mgesture.dTheta, event->mgesture.dDist,
                 event->mgesture.dTheta, event->mgesture.dDist,
                 event->mgesture.x, event->mgesture.y, (uint) event->mgesture.numFingers);
                 event->mgesture.x, event->mgesture.y, (uint) event->mgesture.numFingers);
             break;
             break;
@@ -728,7 +728,7 @@ SDL_WaitEventTimeout(SDL_Event * event, int timeout)
                 /* Timeout expired and no events */
                 /* Timeout expired and no events */
                 return 0;
                 return 0;
             }
             }
-            SDL_Delay(10);
+            SDL_Delay(1);
             break;
             break;
         default:
         default:
             /* Has events */
             /* Has events */

+ 45 - 36
sdl.mod/SDL/src/events/SDL_gesture.c

@@ -36,12 +36,14 @@
 
 
 #define MAXPATHSIZE 1024
 #define MAXPATHSIZE 1024
 
 
-#define DOLLARNPOINTS 64
-#define DOLLARSIZE 256
-
 #define ENABLE_DOLLAR
 #define ENABLE_DOLLAR
 
 
-#define PHI 0.618033989
+#define DOLLARNPOINTS 64
+
+#if defined(ENABLE_DOLLAR)
+#  define DOLLARSIZE 256
+#  define PHI 0.618033989
+#endif
 
 
 typedef struct {
 typedef struct {
     float x,y;
     float x,y;
@@ -335,7 +337,7 @@ static float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ)
 }
 }
 
 
 /* DollarPath contains raw points, plus (possibly) the calculated length */
 /* DollarPath contains raw points, plus (possibly) the calculated length */
-static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
+static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points, SDL_bool is_recording)
 {
 {
     int i;
     int i;
     float interval;
     float interval;
@@ -381,7 +383,9 @@ static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
         dist += d;
         dist += d;
     }
     }
     if (numPoints < DOLLARNPOINTS-1) {
     if (numPoints < DOLLARNPOINTS-1) {
-        SDL_SetError("ERROR: NumPoints = %i", numPoints);
+        if (is_recording) {
+            SDL_SetError("ERROR: NumPoints = %i", numPoints);
+        }
         return 0;
         return 0;
     }
     }
     /* copy the last point */
     /* copy the last point */
@@ -435,7 +439,7 @@ static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_Gestu
 
 
     SDL_memset(points, 0, sizeof(points));
     SDL_memset(points, 0, sizeof(points));
 
 
-    dollarNormalize(path,points);
+    dollarNormalize(path, points, SDL_FALSE);
 
 
     /* PrintPath(points); */
     /* PrintPath(points); */
     *bestTempl = -1;
     *bestTempl = -1;
@@ -498,43 +502,48 @@ static SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id)
     return NULL;
     return NULL;
 }
 }
 
 
-static int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
+static void SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
 {
 {
-    SDL_Event event;
-    event.mgesture.type = SDL_MULTIGESTURE;
-    event.mgesture.touchId = touch->id;
-    event.mgesture.x = touch->centroid.x;
-    event.mgesture.y = touch->centroid.y;
-    event.mgesture.dTheta = dTheta;
-    event.mgesture.dDist = dDist;
-    event.mgesture.numFingers = touch->numDownFingers;
-    return SDL_PushEvent(&event) > 0;
+    if (SDL_GetEventState(SDL_MULTIGESTURE) == SDL_ENABLE) {
+        SDL_Event event;
+        event.mgesture.type = SDL_MULTIGESTURE;
+        event.mgesture.touchId = touch->id;
+        event.mgesture.x = touch->centroid.x;
+        event.mgesture.y = touch->centroid.y;
+        event.mgesture.dTheta = dTheta;
+        event.mgesture.dDist = dDist;
+        event.mgesture.numFingers = touch->numDownFingers;
+        SDL_PushEvent(&event);
+    }
 }
 }
 
 
 #if defined(ENABLE_DOLLAR)
 #if defined(ENABLE_DOLLAR)
-static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
+static void SDL_SendGestureDollar(SDL_GestureTouch* touch,
                           SDL_GestureID gestureId,float error)
                           SDL_GestureID gestureId,float error)
 {
 {
-    SDL_Event event;
-    event.dgesture.type = SDL_DOLLARGESTURE;
-    event.dgesture.touchId = touch->id;
-    event.dgesture.x = touch->centroid.x;
-    event.dgesture.y = touch->centroid.y;
-    event.dgesture.gestureId = gestureId;
-    event.dgesture.error = error;
-    /* A finger came up to trigger this event. */
-    event.dgesture.numFingers = touch->numDownFingers + 1;
-    return SDL_PushEvent(&event) > 0;
+    if (SDL_GetEventState(SDL_DOLLARGESTURE) == SDL_ENABLE) {
+        SDL_Event event;
+        event.dgesture.type = SDL_DOLLARGESTURE;
+        event.dgesture.touchId = touch->id;
+        event.dgesture.x = touch->centroid.x;
+        event.dgesture.y = touch->centroid.y;
+        event.dgesture.gestureId = gestureId;
+        event.dgesture.error = error;
+        /* A finger came up to trigger this event. */
+        event.dgesture.numFingers = touch->numDownFingers + 1;
+        SDL_PushEvent(&event);
+    }
 }
 }
 
 
-
-static int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
+static void SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
 {
 {
-    SDL_Event event;
-    event.dgesture.type = SDL_DOLLARRECORD;
-    event.dgesture.touchId = touch->id;
-    event.dgesture.gestureId = gestureId;
-    return SDL_PushEvent(&event) > 0;
+    if (SDL_GetEventState(SDL_DOLLARRECORD) == SDL_ENABLE) {
+        SDL_Event event;
+        event.dgesture.type = SDL_DOLLARRECORD;
+        event.dgesture.touchId = touch->id;
+        event.dgesture.gestureId = gestureId;
+        SDL_PushEvent(&event);
+    }
 }
 }
 #endif
 #endif
 
 
@@ -576,7 +585,7 @@ void SDL_GestureProcessEvent(SDL_Event* event)
 #if defined(ENABLE_DOLLAR)
 #if defined(ENABLE_DOLLAR)
             if (inTouch->recording) {
             if (inTouch->recording) {
                 inTouch->recording = SDL_FALSE;
                 inTouch->recording = SDL_FALSE;
-                dollarNormalize(&inTouch->dollarPath,path);
+                dollarNormalize(&inTouch->dollarPath, path, SDL_TRUE);
                 /* PrintPath(path); */
                 /* PrintPath(path); */
                 if (recordAll) {
                 if (recordAll) {
                     index = SDL_AddDollarGesture(NULL,path);
                     index = SDL_AddDollarGesture(NULL,path);

+ 2 - 2
sdl.mod/SDL/src/events/SDL_keyboard.c

@@ -878,7 +878,7 @@ SDL_GetKeyFromScancode(SDL_Scancode scancode)
 {
 {
     SDL_Keyboard *keyboard = &SDL_keyboard;
     SDL_Keyboard *keyboard = &SDL_keyboard;
 
 
-    if (((int)scancode) < ((int)SDL_SCANCODE_UNKNOWN) || scancode >= SDL_NUM_SCANCODES) {
+    if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
           SDL_InvalidParamError("scancode");
           SDL_InvalidParamError("scancode");
           return 0;
           return 0;
     }
     }
@@ -905,7 +905,7 @@ const char *
 SDL_GetScancodeName(SDL_Scancode scancode)
 SDL_GetScancodeName(SDL_Scancode scancode)
 {
 {
     const char *name;
     const char *name;
-    if (((int)scancode) < ((int)SDL_SCANCODE_UNKNOWN) || scancode >= SDL_NUM_SCANCODES) {
+    if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
           SDL_InvalidParamError("scancode");
           SDL_InvalidParamError("scancode");
           return "";
           return "";
     }
     }

+ 43 - 24
sdl.mod/SDL/src/events/SDL_mouse.c

@@ -156,6 +156,8 @@ SDL_MouseInit(void)
     SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
     SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
                         SDL_MouseTouchEventsChanged, mouse);
                         SDL_MouseTouchEventsChanged, mouse);
 
 
+    mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
+
     mouse->cursor_shown = SDL_TRUE;
     mouse->cursor_shown = SDL_TRUE;
 
 
     return (0);
     return (0);
@@ -244,7 +246,7 @@ SDL_SetMouseFocus(SDL_Window * window)
 
 
 /* Check to see if we need to synthesize focus events */
 /* Check to see if we need to synthesize focus events */
 static SDL_bool
 static SDL_bool
-SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
+SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_bool send_mouse_motion)
 {
 {
     SDL_Mouse *mouse = SDL_GetMouse();
     SDL_Mouse *mouse = SDL_GetMouse();
     SDL_bool inWindow = SDL_TRUE;
     SDL_bool inWindow = SDL_TRUE;
@@ -275,7 +277,9 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
 #ifdef DEBUG_MOUSE
 #ifdef DEBUG_MOUSE
             printf("Mouse left window, synthesizing move & focus lost event\n");
             printf("Mouse left window, synthesizing move & focus lost event\n");
 #endif
 #endif
-            SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
+            if (send_mouse_motion) {
+                SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
+            }
             SDL_SetMouseFocus(NULL);
             SDL_SetMouseFocus(NULL);
         }
         }
         return SDL_FALSE;
         return SDL_FALSE;
@@ -286,7 +290,9 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
         printf("Mouse entered window, synthesizing focus gain & move event\n");
         printf("Mouse entered window, synthesizing focus gain & move event\n");
 #endif
 #endif
         SDL_SetMouseFocus(window);
         SDL_SetMouseFocus(window);
-        SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
+        if (send_mouse_motion) {
+            SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
+        }
     }
     }
     return SDL_TRUE;
     return SDL_TRUE;
 }
 }
@@ -296,7 +302,7 @@ SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int
 {
 {
     if (window && !relative) {
     if (window && !relative) {
         SDL_Mouse *mouse = SDL_GetMouse();
         SDL_Mouse *mouse = SDL_GetMouse();
-        if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
+        if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate, (mouseID == SDL_TOUCH_MOUSEID) ? SDL_FALSE : SDL_TRUE)) {
             return 0;
             return 0;
         }
         }
     }
     }
@@ -333,11 +339,18 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
             if (window) {
             if (window) {
                 float fx = (float)x / (float)window->w;
                 float fx = (float)x / (float)window->w;
                 float fy = (float)y / (float)window->h;
                 float fy = (float)y / (float)window->h;
-                SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, fx, fy, 1.0f);
+                SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, window, fx, fy, 1.0f);
             }
             }
         }
         }
     }
     }
 
 
+    /* SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer */
+    if (mouse->touch_mouse_events == 0) {
+        if (mouseID == SDL_TOUCH_MOUSEID) {
+            return 0;
+        }
+    }
+
     if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
     if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
         int center_x = 0, center_y = 0;
         int center_x = 0, center_y = 0;
         SDL_GetWindowSize(window, &center_x, &center_y);
         SDL_GetWindowSize(window, &center_x, &center_y);
@@ -368,19 +381,16 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
         yrel = y - mouse->last_y;
         yrel = y - mouse->last_y;
     }
     }
 
 
-    /* Drop events that don't change state */
-    if (!xrel && !yrel) {
-#ifdef DEBUG_MOUSE
-        printf("Mouse event didn't change state - dropped!\n");
-#endif
-        return 0;
-    }
-
     /* Ignore relative motion when first positioning the mouse */
     /* Ignore relative motion when first positioning the mouse */
     if (!mouse->has_position) {
     if (!mouse->has_position) {
         xrel = 0;
         xrel = 0;
         yrel = 0;
         yrel = 0;
         mouse->has_position = SDL_TRUE;
         mouse->has_position = SDL_TRUE;
+    } else if (!xrel && !yrel) {  /* Drop events that don't change state */
+#ifdef DEBUG_MOUSE
+        printf("Mouse event didn't change state - dropped!\n");
+#endif
+        return 0;
     }
     }
 
 
     /* Ignore relative motion positioning the first touch */
     /* Ignore relative motion positioning the first touch */
@@ -439,6 +449,8 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
         event.motion.type = SDL_MOUSEMOTION;
         event.motion.type = SDL_MOUSEMOTION;
         event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
         event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
         event.motion.which = mouseID;
         event.motion.which = mouseID;
+        /* Set us pending (or clear during a normal mouse movement event) as having triggered */
+        mouse->was_touch_mouse_events = (mouseID == SDL_TOUCH_MOUSEID)? SDL_TRUE : SDL_FALSE;
         event.motion.state = mouse->buttonstate;
         event.motion.state = mouse->buttonstate;
         event.motion.x = mouse->x;
         event.motion.x = mouse->x;
         event.motion.y = mouse->y;
         event.motion.y = mouse->y;
@@ -494,11 +506,18 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
             if (window) {
             if (window) {
                 float fx = (float)mouse->x / (float)window->w;
                 float fx = (float)mouse->x / (float)window->w;
                 float fy = (float)mouse->y / (float)window->h;
                 float fy = (float)mouse->y / (float)window->h;
-                SDL_SendTouch(SDL_MOUSE_TOUCHID, 0, track_mouse_down, fx, fy, 1.0f);
+                SDL_SendTouch(SDL_MOUSE_TOUCHID, 0, window, track_mouse_down, fx, fy, 1.0f);
             }
             }
         }
         }
     }
     }
 
 
+    /* SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer */
+    if (mouse->touch_mouse_events == 0) {
+        if (mouseID == SDL_TOUCH_MOUSEID) {
+            return 0;
+        }
+    }
+
     /* Figure out which event to perform */
     /* Figure out which event to perform */
     switch (state) {
     switch (state) {
     case SDL_PRESSED:
     case SDL_PRESSED:
@@ -516,7 +535,7 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
 
 
     /* We do this after calculating buttonstate so button presses gain focus */
     /* We do this after calculating buttonstate so button presses gain focus */
     if (window && state == SDL_PRESSED) {
     if (window && state == SDL_PRESSED) {
-        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
+        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE);
     }
     }
 
 
     if (buttonstate == mouse->buttonstate) {
     if (buttonstate == mouse->buttonstate) {
@@ -566,7 +585,7 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
 
 
     /* We do this after dispatching event so button releases can lose focus */
     /* We do this after dispatching event so button releases can lose focus */
     if (window && state == SDL_RELEASED) {
     if (window && state == SDL_RELEASED) {
-        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
+        SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE);
     }
     }
 
 
     return posted;
     return posted;
@@ -783,14 +802,6 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
         return 0;
         return 0;
     }
     }
 
 
-    if (enabled && focusWindow) {
-        /* Center it in the focused window to prevent clicks from going through
-         * to background windows.
-         */
-        SDL_SetMouseFocus(focusWindow);
-        SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
-    }
-
     /* Set the relative mode */
     /* Set the relative mode */
     if (!enabled && mouse->relative_mode_warp) {
     if (!enabled && mouse->relative_mode_warp) {
         mouse->relative_mode_warp = SDL_FALSE;
         mouse->relative_mode_warp = SDL_FALSE;
@@ -809,6 +820,14 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
     mouse->scale_accum_x = 0.0f;
     mouse->scale_accum_x = 0.0f;
     mouse->scale_accum_y = 0.0f;
     mouse->scale_accum_y = 0.0f;
 
 
+    if (enabled && focusWindow) {
+        /* Center it in the focused window to prevent clicks from going through
+         * to background windows.
+         */
+        SDL_SetMouseFocus(focusWindow);
+        SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
+    }
+
     if (mouse->focus) {
     if (mouse->focus) {
         SDL_UpdateWindowGrab(mouse->focus);
         SDL_UpdateWindowGrab(mouse->focus);
 
 

+ 1 - 0
sdl.mod/SDL/src/events/SDL_mouse_c.h

@@ -94,6 +94,7 @@ typedef struct
     int double_click_radius;
     int double_click_radius;
     SDL_bool touch_mouse_events;
     SDL_bool touch_mouse_events;
     SDL_bool mouse_touch_events;
     SDL_bool mouse_touch_events;
+    SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */
 
 
     /* Data for double-click tracking */
     /* Data for double-click tracking */
     int num_clickstates;
     int num_clickstates;

+ 36 - 8
sdl.mod/SDL/src/events/SDL_touch.c

@@ -32,9 +32,14 @@ static int SDL_num_touch = 0;
 static SDL_Touch **SDL_touchDevices = NULL;
 static SDL_Touch **SDL_touchDevices = NULL;
 
 
 /* for mapping touch events to mice */
 /* for mapping touch events to mice */
+
+#define SYNTHESIZE_TOUCH_TO_MOUSE 1
+
+#if SYNTHESIZE_TOUCH_TO_MOUSE
 static SDL_bool finger_touching = SDL_FALSE;
 static SDL_bool finger_touching = SDL_FALSE;
 static SDL_FingerID track_fingerid;
 static SDL_FingerID track_fingerid;
 static SDL_TouchID  track_touchid;
 static SDL_TouchID  track_touchid;
+#endif
 
 
 /* Public functions */
 /* Public functions */
 int
 int
@@ -234,24 +239,26 @@ SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid)
 }
 }
 
 
 int
 int
-SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
+SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
               SDL_bool down, float x, float y, float pressure)
               SDL_bool down, float x, float y, float pressure)
 {
 {
     int posted;
     int posted;
     SDL_Finger *finger;
     SDL_Finger *finger;
+    SDL_Mouse *mouse;
 
 
     SDL_Touch* touch = SDL_GetTouch(id);
     SDL_Touch* touch = SDL_GetTouch(id);
     if (!touch) {
     if (!touch) {
         return -1;
         return -1;
     }
     }
 
 
+    mouse = SDL_GetMouse();
+
+#if SYNTHESIZE_TOUCH_TO_MOUSE
     /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
     /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
     {
     {
-        SDL_Mouse *mouse = SDL_GetMouse();
         if (mouse->touch_mouse_events) {
         if (mouse->touch_mouse_events) {
             /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
             /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
             if (id != SDL_MOUSE_TOUCHID) {
             if (id != SDL_MOUSE_TOUCHID) {
-                SDL_Window *window = SDL_GetMouseFocus();
                 if (window) {
                 if (window) {
                     if (down) {
                     if (down) {
                         if (finger_touching == SDL_FALSE) {
                         if (finger_touching == SDL_FALSE) {
@@ -284,6 +291,14 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
             }
             }
         }
         }
     }
     }
+#endif
+
+    /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
+    if (mouse->mouse_touch_events == 0) {
+        if (id == SDL_MOUSE_TOUCHID) {
+            return 0;
+        }
+    }
 
 
     finger = SDL_GetFinger(touch, fingerid);
     finger = SDL_GetFinger(touch, fingerid);
     if (down) {
     if (down) {
@@ -307,6 +322,7 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
             event.tfinger.dx = 0;
             event.tfinger.dx = 0;
             event.tfinger.dy = 0;
             event.tfinger.dy = 0;
             event.tfinger.pressure = pressure;
             event.tfinger.pressure = pressure;
+            event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
             posted = (SDL_PushEvent(&event) > 0);
             posted = (SDL_PushEvent(&event) > 0);
         }
         }
     } else {
     } else {
@@ -319,7 +335,7 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
         if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
         if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
             SDL_Event event;
             SDL_Event event;
             event.tfinger.type = SDL_FINGERUP;
             event.tfinger.type = SDL_FINGERUP;
-            event.tfinger.touchId =  id;
+            event.tfinger.touchId = id;
             event.tfinger.fingerId = fingerid;
             event.tfinger.fingerId = fingerid;
             /* I don't trust the coordinates passed on fingerUp */
             /* I don't trust the coordinates passed on fingerUp */
             event.tfinger.x = finger->x;
             event.tfinger.x = finger->x;
@@ -327,6 +343,7 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
             event.tfinger.dx = 0;
             event.tfinger.dx = 0;
             event.tfinger.dy = 0;
             event.tfinger.dy = 0;
             event.tfinger.pressure = pressure;
             event.tfinger.pressure = pressure;
+            event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
             posted = (SDL_PushEvent(&event) > 0);
             posted = (SDL_PushEvent(&event) > 0);
         }
         }
 
 
@@ -336,11 +353,12 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
 }
 }
 
 
 int
 int
-SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
+SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
                     float x, float y, float pressure)
                     float x, float y, float pressure)
 {
 {
     SDL_Touch *touch;
     SDL_Touch *touch;
     SDL_Finger *finger;
     SDL_Finger *finger;
+    SDL_Mouse *mouse;
     int posted;
     int posted;
     float xrel, yrel, prel;
     float xrel, yrel, prel;
 
 
@@ -349,12 +367,13 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
         return -1;
         return -1;
     }
     }
 
 
+    mouse = SDL_GetMouse();
+
+#if SYNTHESIZE_TOUCH_TO_MOUSE
     /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
     /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
     {
     {
-        SDL_Mouse *mouse = SDL_GetMouse();
         if (mouse->touch_mouse_events) {
         if (mouse->touch_mouse_events) {
             if (id != SDL_MOUSE_TOUCHID) {
             if (id != SDL_MOUSE_TOUCHID) {
-                SDL_Window *window = SDL_GetMouseFocus();
                 if (window) {
                 if (window) {
                     if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
                     if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
                         int pos_x = (int)(x * (float)window->w);
                         int pos_x = (int)(x * (float)window->w);
@@ -369,10 +388,18 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
             }
             }
         }
         }
     }
     }
+#endif
+
+    /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
+    if (mouse->mouse_touch_events == 0) {
+        if (id == SDL_MOUSE_TOUCHID) {
+            return 0;
+        }
+    }
 
 
     finger = SDL_GetFinger(touch,fingerid);
     finger = SDL_GetFinger(touch,fingerid);
     if (!finger) {
     if (!finger) {
-        return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
+        return SDL_SendTouch(id, fingerid, window, SDL_TRUE, x, y, pressure);
     }
     }
 
 
     xrel = x - finger->x;
     xrel = x - finger->x;
@@ -404,6 +431,7 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
         event.tfinger.dx = xrel;
         event.tfinger.dx = xrel;
         event.tfinger.dy = yrel;
         event.tfinger.dy = yrel;
         event.tfinger.pressure = pressure;
         event.tfinger.pressure = pressure;
+        event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
         posted = (SDL_PushEvent(&event) > 0);
         posted = (SDL_PushEvent(&event) > 0);
     }
     }
     return posted;
     return posted;

+ 2 - 2
sdl.mod/SDL/src/events/SDL_touch_c.h

@@ -44,11 +44,11 @@ extern int SDL_AddTouch(SDL_TouchID id, SDL_TouchDeviceType type, const char *na
 extern SDL_Touch *SDL_GetTouch(SDL_TouchID id);
 extern SDL_Touch *SDL_GetTouch(SDL_TouchID id);
 
 
 /* Send a touch down/up event for a touch */
 /* Send a touch down/up event for a touch */
-extern int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
+extern int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
                          SDL_bool down, float x, float y, float pressure);
                          SDL_bool down, float x, float y, float pressure);
 
 
 /* Send a touch motion event for a touch */
 /* Send a touch motion event for a touch */
-extern int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
+extern int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
                                float x, float y, float pressure);
                                float x, float y, float pressure);
 
 
 /* Remove a touch */
 /* Remove a touch */

+ 61 - 3
sdl.mod/SDL/src/file/SDL_rwops.c

@@ -361,13 +361,29 @@ stdio_size(SDL_RWops * context)
 static Sint64 SDLCALL
 static Sint64 SDLCALL
 stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
 stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
 {
 {
+    int stdiowhence;
+
+    switch (whence) {
+    case RW_SEEK_SET:
+        stdiowhence = SEEK_SET;
+        break;
+    case RW_SEEK_CUR:
+        stdiowhence = SEEK_CUR;
+        break;
+    case RW_SEEK_END:
+        stdiowhence = SEEK_END;
+        break;
+    default:
+        return SDL_SetError("Unknown value for 'whence'");
+    }
+
 #if defined(FSEEK_OFF_MIN) && defined(FSEEK_OFF_MAX)
 #if defined(FSEEK_OFF_MIN) && defined(FSEEK_OFF_MAX)
     if (offset < (Sint64)(FSEEK_OFF_MIN) || offset > (Sint64)(FSEEK_OFF_MAX)) {
     if (offset < (Sint64)(FSEEK_OFF_MIN) || offset > (Sint64)(FSEEK_OFF_MAX)) {
         return SDL_SetError("Seek offset out of range");
         return SDL_SetError("Seek offset out of range");
     }
     }
 #endif
 #endif
 
 
-    if (fseek(context->hidden.stdio.fp, (fseek_off_t)offset, whence) == 0) {
+    if (fseek(context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) {
         Sint64 pos = ftell(context->hidden.stdio.fp);
         Sint64 pos = ftell(context->hidden.stdio.fp);
         if (pos < 0) {
         if (pos < 0) {
             return SDL_SetError("Couldn't get stream offset");
             return SDL_SetError("Couldn't get stream offset");
@@ -462,7 +478,7 @@ mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
 
 
     total_bytes = (maxnum * size);
     total_bytes = (maxnum * size);
     if ((maxnum <= 0) || (size <= 0)
     if ((maxnum <= 0) || (size <= 0)
-        || ((total_bytes / maxnum) != (size_t) size)) {
+        || ((total_bytes / maxnum) != size)) {
         return 0;
         return 0;
     }
     }
 
 
@@ -585,7 +601,7 @@ SDL_RWFromFile(const char *file, const char *mode)
         if (fp == NULL) {
         if (fp == NULL) {
             SDL_SetError("Couldn't open %s", file);
             SDL_SetError("Couldn't open %s", file);
         } else {
         } else {
-            rwops = SDL_RWFromFP(fp, 1);
+            rwops = SDL_RWFromFP(fp, SDL_TRUE);
         }
         }
     }
     }
 #else
 #else
@@ -752,6 +768,48 @@ done:
     return data;
     return data;
 }
 }
 
 
+void *
+SDL_LoadFile(const char *file, size_t *datasize)
+{
+   return SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1);
+}
+
+Sint64
+SDL_RWsize(SDL_RWops *context)
+{
+    return context->size(context);
+}
+
+Sint64
+SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence)
+{
+    return context->seek(context, offset, whence);
+}
+
+Sint64
+SDL_RWtell(SDL_RWops *context)
+{
+    return context->seek(context, 0, RW_SEEK_CUR);
+}
+
+size_t
+SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
+{
+    return context->read(context, ptr, size, maxnum);
+}
+
+size_t
+SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t num)
+{
+    return context->write(context, ptr, size, num);
+}
+
+int
+SDL_RWclose(SDL_RWops *context)
+{
+    return context->close(context);
+}
+
 /* Functions for dynamically reading and writing endian-specific values */
 /* Functions for dynamically reading and writing endian-specific values */
 
 
 Uint8
 Uint8

+ 21 - 0
sdl.mod/SDL/src/filesystem/cocoa/SDL_sysfilesystem.m

@@ -32,6 +32,7 @@
 #include "SDL_error.h"
 #include "SDL_error.h"
 #include "SDL_stdinc.h"
 #include "SDL_stdinc.h"
 #include "SDL_filesystem.h"
 #include "SDL_filesystem.h"
+#include "SDL_log.h"
 
 
 char *
 char *
 SDL_GetBasePath(void)
 SDL_GetBasePath(void)
@@ -80,7 +81,27 @@ SDL_GetPrefPath(const char *org, const char *app)
     }
     }
 
 
     char *retval = NULL;
     char *retval = NULL;
+#if !TARGET_OS_TV
     NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
     NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+#else
+    /* tvOS does not have persistent local storage!
+     * The only place on-device where we can store data is
+     * a cache directory that the OS can empty at any time.
+     *
+     * It's therefore very likely that save data will be erased
+     * between sessions. If you want your app's save data to
+     * actually stick around, you'll need to use iCloud storage.
+     */
+
+    static SDL_bool shown = SDL_FALSE;
+    if (!shown)
+    {
+        shown = SDL_TRUE;
+        SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n");
+    }
+
+    NSArray *array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+#endif /* !TARGET_OS_TV */
 
 
     if ([array count] > 0) {  /* we only want the first item in the list. */
     if ([array count] > 0) {  /* we only want the first item in the list. */
         NSString *str = [array objectAtIndex:0];
         NSString *str = [array objectAtIndex:0];

+ 1 - 1
sdl.mod/SDL/src/filesystem/unix/SDL_sysfilesystem.c

@@ -140,7 +140,7 @@ SDL_GetBasePath(void)
         if (retval == NULL) {
         if (retval == NULL) {
             /* older kernels don't have /proc/self ... try PID version... */
             /* older kernels don't have /proc/self ... try PID version... */
             char path[64];
             char path[64];
-            const int rc = (int) SDL_snprintf(path, sizeof(path),
+            const int rc = SDL_snprintf(path, sizeof(path),
                                               "/proc/%llu/exe",
                                               "/proc/%llu/exe",
                                               (unsigned long long) getpid());
                                               (unsigned long long) getpid());
             if ( (rc > 0) && (rc < sizeof(path)) ) {
             if ( (rc > 0) && (rc < sizeof(path)) ) {

+ 1 - 1
sdl.mod/SDL/src/hidapi/AUTHORS.txt

@@ -12,5 +12,5 @@ Ludovic Rousseau <[email protected]>:
 
 
 
 
 For a comprehensive list of contributions, see the commit list at github:
 For a comprehensive list of contributions, see the commit list at github:
-	http://github.com/signal11/hidapi/commits/master
+	https://github.com/libusb/hidapi/commits/master
 
 

+ 1 - 1
sdl.mod/SDL/src/hidapi/README.txt

@@ -122,7 +122,7 @@ HIDAPI may be used by one of three licenses as outlined in LICENSE.txt.
 Download
 Download
 =========
 =========
 HIDAPI can be downloaded from github
 HIDAPI can be downloaded from github
-	git clone git://github.com/signal11/hidapi.git
+	git clone git://github.com/libusb/hidapi.git
 
 
 Build Instructions
 Build Instructions
 ===================
 ===================

+ 744 - 0
sdl.mod/SDL/src/hidapi/SDL_hidapi.c

@@ -0,0 +1,744 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2019 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* Original hybrid wrapper for Linux by Valve Software. Their original notes:
+ *
+ * The libusb version doesn't support Bluetooth, but not all Linux
+ * distributions allow access to /dev/hidraw*
+ *
+ * This merges the two, at a small performance cost, until distributions
+ * have granted access to /dev/hidraw*
+ */
+
+#include "../SDL_internal.h"
+#include "SDL_loadso.h"
+
+#ifdef SDL_JOYSTICK_HIDAPI
+
+/* Platform HIDAPI Implementation */
+
+#define hid_device_                     PLATFORM_hid_device_
+#define hid_device                      PLATFORM_hid_device
+#define hid_device_info                 PLATFORM_hid_device_info
+#define hid_init                        PLATFORM_hid_init
+#define hid_exit                        PLATFORM_hid_exit
+#define hid_enumerate                   PLATFORM_hid_enumerate
+#define hid_free_enumeration            PLATFORM_hid_free_enumeration
+#define hid_open                        PLATFORM_hid_open
+#define hid_open_path                   PLATFORM_hid_open_path
+#define hid_write                       PLATFORM_hid_write
+#define hid_read_timeout                PLATFORM_hid_read_timeout
+#define hid_read                        PLATFORM_hid_read
+#define hid_set_nonblocking             PLATFORM_hid_set_nonblocking
+#define hid_send_feature_report         PLATFORM_hid_send_feature_report
+#define hid_get_feature_report          PLATFORM_hid_get_feature_report
+#define hid_close                       PLATFORM_hid_close
+#define hid_get_manufacturer_string     PLATFORM_hid_get_manufacturer_string
+#define hid_get_product_string          PLATFORM_hid_get_product_string
+#define hid_get_serial_number_string    PLATFORM_hid_get_serial_number_string
+#define hid_get_indexed_string          PLATFORM_hid_get_indexed_string
+#define hid_error                       PLATFORM_hid_error
+#define new_hid_device                  PLATFORM_new_hid_device
+#define free_hid_device                 PLATFORM_free_hid_device
+#define input_report                    PLATFORM_input_report
+#define return_data                     PLATFORM_return_data
+#define make_path                       PLATFORM_make_path
+#define read_thread                     PLATFORM_read_thread
+
+#if __LINUX__
+
+#include "../../core/linux/SDL_udev.h"
+#if SDL_USE_LIBUDEV
+static const SDL_UDEV_Symbols *udev_ctx = NULL;
+
+#define udev_device_get_sysattr_value                    udev_ctx->udev_device_get_sysattr_value
+#define udev_new                                         udev_ctx->udev_new
+#define udev_unref                                       udev_ctx->udev_unref
+#define udev_device_new_from_devnum                      udev_ctx->udev_device_new_from_devnum
+#define udev_device_get_parent_with_subsystem_devtype    udev_ctx->udev_device_get_parent_with_subsystem_devtype
+#define udev_device_unref                                udev_ctx->udev_device_unref
+#define udev_enumerate_new                               udev_ctx->udev_enumerate_new
+#define udev_enumerate_add_match_subsystem               udev_ctx->udev_enumerate_add_match_subsystem
+#define udev_enumerate_scan_devices                      udev_ctx->udev_enumerate_scan_devices
+#define udev_enumerate_get_list_entry                    udev_ctx->udev_enumerate_get_list_entry
+#define udev_list_entry_get_name                         udev_ctx->udev_list_entry_get_name
+#define udev_device_new_from_syspath                     udev_ctx->udev_device_new_from_syspath
+#define udev_device_get_devnode                          udev_ctx->udev_device_get_devnode
+#define udev_list_entry_get_next                         udev_ctx->udev_list_entry_get_next
+#define udev_enumerate_unref                             udev_ctx->udev_enumerate_unref
+
+#include "linux/hid.c"
+#define HAVE_PLATFORM_BACKEND 1
+#endif /* SDL_USE_LIBUDEV */
+
+#elif __MACOSX__
+#include "mac/hid.c"
+#define HAVE_PLATFORM_BACKEND 1
+#define udev_ctx 1
+#elif __WINDOWS__
+#include "windows/hid.c"
+#define HAVE_PLATFORM_BACKEND 1
+#define udev_ctx 1
+#else
+#error Need a hid.c for this platform!
+#endif
+
+#undef hid_device_
+#undef hid_device
+#undef hid_device_info
+#undef hid_init
+#undef hid_exit
+#undef hid_enumerate
+#undef hid_free_enumeration
+#undef hid_open
+#undef hid_open_path
+#undef hid_write
+#undef hid_read_timeout
+#undef hid_read
+#undef hid_set_nonblocking
+#undef hid_send_feature_report
+#undef hid_get_feature_report
+#undef hid_close
+#undef hid_get_manufacturer_string
+#undef hid_get_product_string
+#undef hid_get_serial_number_string
+#undef hid_get_indexed_string
+#undef hid_error
+#undef new_hid_device
+#undef free_hid_device
+#undef input_report
+#undef return_data
+#undef make_path
+#undef read_thread
+
+#ifndef SDL_LIBUSB_DYNAMIC
+#if __WINDOWS__
+#define SDL_LIBUSB_DYNAMIC "libusb-1.0.dll"
+#endif /* __WINDOWS__ */
+#endif /* SDL_LIBUSB_DYNAMIC */
+
+#ifdef SDL_LIBUSB_DYNAMIC
+/* libusb HIDAPI Implementation */
+
+/* Include this now, for our dynamically-loaded libusb context */
+#include <libusb.h>
+
+static struct
+{
+    void* libhandle;
+
+    int (*init)(libusb_context **ctx);
+    void (*exit)(libusb_context *ctx);
+    ssize_t (*get_device_list)(libusb_context *ctx, libusb_device ***list);
+    void (*free_device_list)(libusb_device **list, int unref_devices);
+    int (*get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc);
+    int (*get_active_config_descriptor)(libusb_device *dev,    struct libusb_config_descriptor **config);
+    int (*get_config_descriptor)(
+        libusb_device *dev,
+        uint8_t config_index,
+        struct libusb_config_descriptor **config
+    );
+    void (*free_config_descriptor)(struct libusb_config_descriptor *config);
+    uint8_t (*get_bus_number)(libusb_device *dev);
+    uint8_t (*get_device_address)(libusb_device *dev);
+    int (*open)(libusb_device *dev, libusb_device_handle **dev_handle);
+    void (*close)(libusb_device_handle *dev_handle);
+    int (*claim_interface)(libusb_device_handle *dev_handle, int interface_number);
+    int (*release_interface)(libusb_device_handle *dev_handle, int interface_number);
+    int (*kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number);
+    int (*detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
+    struct libusb_transfer * (*alloc_transfer)(int iso_packets);
+    int (*submit_transfer)(struct libusb_transfer *transfer);
+    int (*cancel_transfer)(struct libusb_transfer *transfer);
+    void (*free_transfer)(struct libusb_transfer *transfer);
+    int (*control_transfer)(
+        libusb_device_handle *dev_handle,
+        uint8_t request_type,
+        uint8_t bRequest,
+        uint16_t wValue,
+        uint16_t wIndex,
+        unsigned char *data,
+        uint16_t wLength,
+        unsigned int timeout
+    );
+    int (*interrupt_transfer)(
+        libusb_device_handle *dev_handle,
+        unsigned char endpoint,
+        unsigned char *data,
+        int length,
+        int *actual_length,
+        unsigned int timeout
+    );
+    int (*handle_events)(libusb_context *ctx);
+    int (*handle_events_completed)(libusb_context *ctx, int *completed);
+} libusb_ctx;
+
+#define libusb_init                            libusb_ctx.init
+#define libusb_exit                            libusb_ctx.exit
+#define libusb_get_device_list                 libusb_ctx.get_device_list
+#define libusb_free_device_list                libusb_ctx.free_device_list
+#define libusb_get_device_descriptor           libusb_ctx.get_device_descriptor
+#define libusb_get_active_config_descriptor    libusb_ctx.get_active_config_descriptor
+#define libusb_get_config_descriptor           libusb_ctx.get_config_descriptor
+#define libusb_free_config_descriptor          libusb_ctx.free_config_descriptor
+#define libusb_get_bus_number                  libusb_ctx.get_bus_number
+#define libusb_get_device_address              libusb_ctx.get_device_address
+#define libusb_open                            libusb_ctx.open
+#define libusb_close                           libusb_ctx.close
+#define libusb_claim_interface                 libusb_ctx.claim_interface
+#define libusb_release_interface               libusb_ctx.release_interface
+#define libusb_kernel_driver_active            libusb_ctx.kernel_driver_active
+#define libusb_detach_kernel_driver            libusb_ctx.detach_kernel_driver
+#define libusb_alloc_transfer                  libusb_ctx.alloc_transfer
+#define libusb_submit_transfer                 libusb_ctx.submit_transfer
+#define libusb_cancel_transfer                 libusb_ctx.cancel_transfer
+#define libusb_free_transfer                   libusb_ctx.free_transfer
+#define libusb_control_transfer                libusb_ctx.control_transfer
+#define libusb_interrupt_transfer              libusb_ctx.interrupt_transfer
+#define libusb_handle_events                   libusb_ctx.handle_events
+#define libusb_handle_events_completed         libusb_ctx.handle_events_completed
+
+#define hid_device_                     LIBUSB_hid_device_
+#define hid_device                      LIBUSB_hid_device
+#define hid_device_info                 LIBUSB_hid_device_info
+#define hid_init                        LIBUSB_hid_init
+#define hid_exit                        LIBUSB_hid_exit
+#define hid_enumerate                   LIBUSB_hid_enumerate
+#define hid_free_enumeration            LIBUSB_hid_free_enumeration
+#define hid_open                        LIBUSB_hid_open
+#define hid_open_path                   LIBUSB_hid_open_path
+#define hid_write                       LIBUSB_hid_write
+#define hid_read_timeout                LIBUSB_hid_read_timeout
+#define hid_read                        LIBUSB_hid_read
+#define hid_set_nonblocking             LIBUSB_hid_set_nonblocking
+#define hid_send_feature_report         LIBUSB_hid_send_feature_report
+#define hid_get_feature_report          LIBUSB_hid_get_feature_report
+#define hid_close                       LIBUSB_hid_close
+#define hid_get_manufacturer_string     LIBUSB_hid_get_manufacturer_string
+#define hid_get_product_string          LIBUSB_hid_get_product_string
+#define hid_get_serial_number_string    LIBUSB_hid_get_serial_number_string
+#define hid_get_indexed_string          LIBUSB_hid_get_indexed_string
+#define hid_error                       LIBUSB_hid_error
+#define new_hid_device                  LIBUSB_new_hid_device
+#define free_hid_device                 LIBUSB_free_hid_device
+#define input_report                    LIBUSB_input_report
+#define return_data                     LIBUSB_return_data
+#define make_path                       LIBUSB_make_path
+#define read_thread                     LIBUSB_read_thread
+
+#ifndef __FreeBSD__
+/* this is awkwardly inlined, so we need to re-implement it here
+ * so we can override the libusb_control_transfer call */
+static int
+SDL_libusb_get_string_descriptor(libusb_device_handle *dev,
+                                 uint8_t descriptor_index, uint16_t lang_id,
+                                 unsigned char *data, int length)
+{
+    return libusb_control_transfer(dev,
+                                   LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */
+                                   LIBUSB_REQUEST_GET_DESCRIPTOR,
+                                   (LIBUSB_DT_STRING << 8) | descriptor_index,
+                                   lang_id,
+                                   data,
+                                   (uint16_t) length,
+                                   1000);
+}
+#define libusb_get_string_descriptor SDL_libusb_get_string_descriptor
+#endif /* __FreeBSD__ */
+
+#undef HIDAPI_H__
+#include "libusb/hid.c"
+
+#undef hid_device_
+#undef hid_device
+#undef hid_device_info
+#undef hid_init
+#undef hid_exit
+#undef hid_enumerate
+#undef hid_free_enumeration
+#undef hid_open
+#undef hid_open_path
+#undef hid_write
+#undef hid_read_timeout
+#undef hid_read
+#undef hid_set_nonblocking
+#undef hid_send_feature_report
+#undef hid_get_feature_report
+#undef hid_close
+#undef hid_get_manufacturer_string
+#undef hid_get_product_string
+#undef hid_get_serial_number_string
+#undef hid_get_indexed_string
+#undef hid_error
+#undef new_hid_device
+#undef free_hid_device
+#undef input_report
+#undef return_data
+#undef make_path
+#undef read_thread
+
+#endif /* SDL_LIBUSB_DYNAMIC */
+
+/* Shared HIDAPI Implementation */
+
+#undef HIDAPI_H__
+#include "hidapi.h"
+
+struct hidapi_backend {
+#define F(x) typeof(x) *x
+    F(hid_write);
+    F(hid_read_timeout);
+    F(hid_read);
+    F(hid_set_nonblocking);
+    F(hid_send_feature_report);
+    F(hid_get_feature_report);
+    F(hid_close);
+    F(hid_get_manufacturer_string);
+    F(hid_get_product_string);
+    F(hid_get_serial_number_string);
+    F(hid_get_indexed_string);
+    F(hid_error);
+#undef F
+};
+
+#if HAVE_PLATFORM_BACKEND
+static const struct hidapi_backend PLATFORM_Backend = {
+    (void*)PLATFORM_hid_write,
+    (void*)PLATFORM_hid_read_timeout,
+    (void*)PLATFORM_hid_read,
+    (void*)PLATFORM_hid_set_nonblocking,
+    (void*)PLATFORM_hid_send_feature_report,
+    (void*)PLATFORM_hid_get_feature_report,
+    (void*)PLATFORM_hid_close,
+    (void*)PLATFORM_hid_get_manufacturer_string,
+    (void*)PLATFORM_hid_get_product_string,
+    (void*)PLATFORM_hid_get_serial_number_string,
+    (void*)PLATFORM_hid_get_indexed_string,
+    (void*)PLATFORM_hid_error
+};
+#endif /* HAVE_PLATFORM_BACKEND */
+
+#ifdef SDL_LIBUSB_DYNAMIC
+static const struct hidapi_backend LIBUSB_Backend = {
+    (void*)LIBUSB_hid_write,
+    (void*)LIBUSB_hid_read_timeout,
+    (void*)LIBUSB_hid_read,
+    (void*)LIBUSB_hid_set_nonblocking,
+    (void*)LIBUSB_hid_send_feature_report,
+    (void*)LIBUSB_hid_get_feature_report,
+    (void*)LIBUSB_hid_close,
+    (void*)LIBUSB_hid_get_manufacturer_string,
+    (void*)LIBUSB_hid_get_product_string,
+    (void*)LIBUSB_hid_get_serial_number_string,
+    (void*)LIBUSB_hid_get_indexed_string,
+    (void*)LIBUSB_hid_error
+};
+#endif /* SDL_LIBUSB_DYNAMIC */
+
+typedef struct _HIDDeviceWrapper HIDDeviceWrapper;
+struct _HIDDeviceWrapper
+{
+    hid_device *device; /* must be first field */
+    const struct hidapi_backend *backend;
+};
+
+static HIDDeviceWrapper *
+CreateHIDDeviceWrapper(hid_device *device, const struct hidapi_backend *backend)
+{
+    HIDDeviceWrapper *ret = SDL_malloc(sizeof(*ret));
+    ret->device = device;
+    ret->backend = backend;
+    return ret;
+}
+
+static hid_device *
+WrapHIDDevice(HIDDeviceWrapper *wrapper)
+{
+    return (hid_device *)wrapper;
+}
+
+static HIDDeviceWrapper *
+UnwrapHIDDevice(hid_device *device)
+{
+    return (HIDDeviceWrapper *)device;
+}
+
+static void
+DeleteHIDDeviceWrapper(HIDDeviceWrapper *device)
+{
+    SDL_free(device);
+}
+
+#define COPY_IF_EXISTS(var) \
+    if (pSrc->var != NULL) { \
+        pDst->var = SDL_strdup(pSrc->var); \
+    } else { \
+        pDst->var = NULL; \
+    }
+#define WCOPY_IF_EXISTS(var) \
+    if (pSrc->var != NULL) { \
+        pDst->var = SDL_wcsdup(pSrc->var); \
+    } else { \
+        pDst->var = NULL; \
+    }
+
+#ifdef SDL_LIBUSB_DYNAMIC
+static void
+LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info *pSrc,
+                         struct hid_device_info *pDst)
+{
+    COPY_IF_EXISTS(path)
+    pDst->vendor_id = pSrc->vendor_id;
+    pDst->product_id = pSrc->product_id;
+    WCOPY_IF_EXISTS(serial_number)
+    pDst->release_number = pSrc->release_number;
+    WCOPY_IF_EXISTS(manufacturer_string)
+    WCOPY_IF_EXISTS(product_string)
+    pDst->usage_page = pSrc->usage_page;
+    pDst->usage = pSrc->usage;
+    pDst->interface_number = pSrc->interface_number;
+    pDst->next = NULL;
+}
+#endif /* SDL_LIBUSB_DYNAMIC */
+
+#if HAVE_PLATFORM_BACKEND
+static void
+PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info *pSrc,
+                           struct hid_device_info *pDst)
+{
+    COPY_IF_EXISTS(path)
+    pDst->vendor_id = pSrc->vendor_id;
+    pDst->product_id = pSrc->product_id;
+    WCOPY_IF_EXISTS(serial_number)
+    pDst->release_number = pSrc->release_number;
+    WCOPY_IF_EXISTS(manufacturer_string)
+    WCOPY_IF_EXISTS(product_string)
+    pDst->usage_page = pSrc->usage_page;
+    pDst->usage = pSrc->usage;
+    pDst->interface_number = pSrc->interface_number;
+    pDst->next = NULL;
+}
+#endif /* HAVE_PLATFORM_BACKEND */
+
+#undef COPY_IF_EXISTS
+#undef WCOPY_IF_EXISTS
+
+static SDL_bool SDL_hidapi_wasinit = SDL_FALSE;
+
+int HID_API_EXPORT HID_API_CALL hid_init(void)
+{
+    int err;
+
+    if (SDL_hidapi_wasinit == SDL_TRUE) {
+        return 0;
+    }
+
+#ifdef SDL_LIBUSB_DYNAMIC
+    libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
+    if (libusb_ctx.libhandle != NULL) {
+        #define LOAD_LIBUSB_SYMBOL(func) \
+            libusb_ctx.func = SDL_LoadFunction(libusb_ctx.libhandle, "libusb_" #func);
+        LOAD_LIBUSB_SYMBOL(init)
+        LOAD_LIBUSB_SYMBOL(exit)
+        LOAD_LIBUSB_SYMBOL(get_device_list)
+        LOAD_LIBUSB_SYMBOL(free_device_list)
+        LOAD_LIBUSB_SYMBOL(get_device_descriptor)
+        LOAD_LIBUSB_SYMBOL(get_active_config_descriptor)
+        LOAD_LIBUSB_SYMBOL(get_config_descriptor)
+        LOAD_LIBUSB_SYMBOL(free_config_descriptor)
+        LOAD_LIBUSB_SYMBOL(get_bus_number)
+        LOAD_LIBUSB_SYMBOL(get_device_address)
+        LOAD_LIBUSB_SYMBOL(open)
+        LOAD_LIBUSB_SYMBOL(close)
+        LOAD_LIBUSB_SYMBOL(claim_interface)
+        LOAD_LIBUSB_SYMBOL(release_interface)
+        LOAD_LIBUSB_SYMBOL(kernel_driver_active)
+        LOAD_LIBUSB_SYMBOL(detach_kernel_driver)
+        LOAD_LIBUSB_SYMBOL(alloc_transfer)
+        LOAD_LIBUSB_SYMBOL(submit_transfer)
+        LOAD_LIBUSB_SYMBOL(cancel_transfer)
+        LOAD_LIBUSB_SYMBOL(free_transfer)
+        LOAD_LIBUSB_SYMBOL(control_transfer)
+        LOAD_LIBUSB_SYMBOL(interrupt_transfer)
+        LOAD_LIBUSB_SYMBOL(handle_events)
+        LOAD_LIBUSB_SYMBOL(handle_events_completed)
+        #undef LOAD_LIBUSB_SYMBOL
+
+        if ((err = LIBUSB_hid_init()) < 0) {
+            SDL_UnloadObject(libusb_ctx.libhandle);
+            return err;
+        }
+    }
+#endif /* SDL_LIBUSB_DYNAMIC */
+
+#if HAVE_PLATFORM_BACKEND
+#if __LINUX__
+    udev_ctx = SDL_UDEV_GetUdevSyms();
+#endif /* __LINUX __ */
+    if (udev_ctx && (err = PLATFORM_hid_init()) < 0) {
+#ifdef SDL_LIBUSB_DYNAMIC
+        if (libusb_ctx.libhandle) {
+            SDL_UnloadObject(libusb_ctx.libhandle);
+        }
+#endif /* SDL_LIBUSB_DYNAMIC */
+        return err;
+    }
+#endif /* HAVE_PLATFORM_BACKEND */
+
+    return 0;
+}
+
+int HID_API_EXPORT HID_API_CALL hid_exit(void)
+{
+    int err = 0;
+
+    if (SDL_hidapi_wasinit == SDL_FALSE) {
+        return 0;
+    }
+
+#if HAVE_PLATFORM_BACKEND
+    if (udev_ctx) {
+        err = PLATFORM_hid_exit();
+    }
+#endif /* HAVE_PLATFORM_BACKEND */
+#ifdef SDL_LIBUSB_DYNAMIC
+    if (libusb_ctx.libhandle) {
+        err |= LIBUSB_hid_exit(); /* Ehhhhh */
+        SDL_UnloadObject(libusb_ctx.libhandle);
+    }
+#endif /* SDL_LIBUSB_DYNAMIC */
+    return err;
+}
+
+struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+#if HAVE_PLATFORM_BACKEND
+    struct PLATFORM_hid_device_info *raw_devs = NULL;
+    struct PLATFORM_hid_device_info *raw_dev;
+#endif /* HAVE_PLATFORM_BACKEND */
+    struct hid_device_info *devs = NULL, *last = NULL, *new_dev;
+    SDL_bool bFound;
+
+    if (SDL_hidapi_wasinit == SDL_FALSE) {
+        hid_init();
+    }
+
+#if HAVE_PLATFORM_BACKEND
+    if (udev_ctx) {
+        raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
+    }
+#endif /* HAVE_PLATFORM_BACKEND */
+
+#ifdef SDL_LIBUSB_DYNAMIC
+    if (libusb_ctx.libhandle) {
+        struct LIBUSB_hid_device_info *usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
+        struct LIBUSB_hid_device_info *usb_dev;
+        for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
+            bFound = SDL_FALSE;
+#if HAVE_PLATFORM_BACKEND
+            for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
+                if (usb_dev->vendor_id == raw_dev->vendor_id &&
+                    usb_dev->product_id == raw_dev->product_id) {
+
+                    bFound = SDL_TRUE;
+                    break;
+                }
+            }
+#endif
+
+            if (!bFound) {
+                new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
+                LIBUSB_CopyHIDDeviceInfo(usb_dev, new_dev);
+
+                if (last != NULL) {
+                    last->next = new_dev;
+                } else {
+                    devs = new_dev;
+                }
+                last = new_dev;
+            }
+        }
+        LIBUSB_hid_free_enumeration(usb_devs);
+    }
+#endif /* SDL_LIBUSB_DYNAMIC */
+
+#if HAVE_PLATFORM_BACKEND
+    if (udev_ctx) {
+        for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
+            new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
+            PLATFORM_CopyHIDDeviceInfo(raw_dev, new_dev);
+            new_dev->next = NULL;
+
+            if (last != NULL) {
+                last->next = new_dev;
+            } else {
+                devs = new_dev;
+            }
+            last = new_dev;
+        }
+        PLATFORM_hid_free_enumeration(raw_devs);
+    }
+#endif /* HAVE_PLATFORM_BACKEND */
+
+    return devs;
+}
+
+void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
+{
+    while (devs) {
+        struct hid_device_info *next = devs->next;
+        SDL_free(devs->path);
+        SDL_free(devs->serial_number);
+        SDL_free(devs->manufacturer_string);
+        SDL_free(devs->product_string);
+        SDL_free(devs);
+        devs = next;
+    }
+}
+
+HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+    hid_device *pDevice = NULL;
+
+    if (SDL_hidapi_wasinit == SDL_FALSE) {
+        hid_init();
+    }
+
+#if HAVE_PLATFORM_BACKEND
+    if (udev_ctx &&
+        (pDevice = (hid_device*) PLATFORM_hid_open(vendor_id, product_id, serial_number)) != NULL) {
+
+        HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
+        return WrapHIDDevice(wrapper);
+    }
+#endif /* HAVE_PLATFORM_BACKEND */
+#ifdef SDL_LIBUSB_DYNAMIC
+    if (libusb_ctx.libhandle &&
+        (pDevice = (hid_device*) LIBUSB_hid_open(vendor_id, product_id, serial_number)) != NULL) {
+
+        HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
+        return WrapHIDDevice(wrapper);
+    }
+#endif /* SDL_LIBUSB_DYNAMIC */
+    return NULL;
+}
+
+HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */)
+{
+    hid_device *pDevice = NULL;
+
+    if (SDL_hidapi_wasinit == SDL_FALSE) {
+        hid_init();
+    }
+
+#if HAVE_PLATFORM_BACKEND
+    if (udev_ctx &&
+        (pDevice = (hid_device*) PLATFORM_hid_open_path(path, bExclusive)) != NULL) {
+
+        HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
+        return WrapHIDDevice(wrapper);
+    }
+#endif /* HAVE_PLATFORM_BACKEND */
+#ifdef SDL_LIBUSB_DYNAMIC
+    if (libusb_ctx.libhandle &&
+        (pDevice = (hid_device*) LIBUSB_hid_open_path(path, bExclusive)) != NULL) {
+
+        HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
+        return WrapHIDDevice(wrapper);
+    }
+#endif /* SDL_LIBUSB_DYNAMIC */
+    return NULL;
+}
+
+int  HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_write(wrapper->device, data, length);
+}
+
+int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_read_timeout(wrapper->device, data, length, milliseconds);
+}
+
+int  HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_read(wrapper->device, data, length);
+}
+
+int  HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_set_nonblocking(wrapper->device, nonblock);
+}
+
+int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_send_feature_report(wrapper->device, data, length);
+}
+
+int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_get_feature_report(wrapper->device, data, length);
+}
+
+void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    wrapper->backend->hid_close(wrapper->device);
+    DeleteHIDDeviceWrapper(wrapper);
+}
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_get_manufacturer_string(wrapper->device, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_get_product_string(wrapper->device, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_get_serial_number_string(wrapper->device, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_get_indexed_string(wrapper->device, string_index, string, maxlen);
+}
+
+HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
+{
+    HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
+    return wrapper->backend->hid_error(wrapper->device);
+}
+
+#endif /* SDL_JOYSTICK_HIDAPI */

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio