shithub: ft²

Download patch

ref: 4ae8fd191b543e610c97a905e05b10bdbab79e48
parent: 0ae7a5a616127349a3a14c77ccaf8ab49a05b924
parent: 222085f30fbe34639ba07ee5bf7ebc1a179384d6
author: qwx <qwx@sciops.net>
date: Sat Mar 23 19:32:52 EDT 2024

sync upstream

--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_assert.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_assert.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_atomic.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_atomic.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -209,7 +209,7 @@
 #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_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__)
 #ifdef __thumb__
 /* The mcr instruction isn't available in thumb mode, use real functions */
 #define SDL_MEMORY_BARRIER_USES_FUNCTION
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_audio.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_audio.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_bits.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_bits.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_blendmode.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_blendmode.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -65,8 +65,8 @@
 typedef enum
 {
     SDL_BLENDOPERATION_ADD              = 0x1,  /**< dst + src: supported by all renderers */
-    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
-    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
     SDL_BLENDOPERATION_MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D9, D3D11 */
     SDL_BLENDOPERATION_MAXIMUM          = 0x5   /**< max(dst, src) : supported by D3D9, D3D11 */
 } SDL_BlendOperation;
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_clipboard.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_clipboard.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_config.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_config.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_config_macosx.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_config_macosx.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_copying.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_copying.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_cpuinfo.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_cpuinfo.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_endian.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_endian.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_error.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_error.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_events.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_events.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -131,6 +131,8 @@
     SDL_CONTROLLERTOUCHPADMOTION,      /**< Game controller touchpad finger was moved */
     SDL_CONTROLLERTOUCHPADUP,          /**< Game controller touchpad finger was lifted */
     SDL_CONTROLLERSENSORUPDATE,        /**< Game controller sensor was updated */
+    SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3,
+    SDL_CONTROLLERSTEAMHANDLEUPDATED,  /**< Game controller Steam handle has changed */
 
     /* Touch events */
     SDL_FINGERDOWN      = 0x700,
@@ -446,7 +448,7 @@
  */
 typedef struct SDL_ControllerDeviceEvent
 {
-    Uint32 type;        /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
+    Uint32 type;        /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */
     Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
     Sint32 which;       /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
 } SDL_ControllerDeviceEvent;
@@ -579,15 +581,6 @@
     Uint32 type;        /**< ::SDL_QUIT */
     Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
 } SDL_QuitEvent;
-
-/**
- *  \brief OS Specific event
- */
-typedef struct SDL_OSEvent
-{
-    Uint32 type;        /**< ::SDL_QUIT */
-    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
-} SDL_OSEvent;
 
 /**
  *  \brief A user-defined event type (event.user.*)
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_filesystem.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_filesystem.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -64,7 +64,7 @@
  * directory of the application as it is uncommon to store resources outside
  * the executable. As such it is not a writable directory.
  *
- * The returned path is guaranteed to end with a path separator ('\' on
+ * The returned path is guaranteed to end with a path separator ('\\' on
  * Windows, '/' on most other platforms).
  *
  * The pointer returned is owned by the caller. Please call SDL_free() on the
@@ -120,7 +120,7 @@
  * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
  *   Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
  *
- * The returned path is guaranteed to end with a path separator ('\' on
+ * The returned path is guaranteed to end with a path separator ('\\' on
  * Windows, '/' on most other platforms).
  *
  * The pointer returned is owned by the caller. Please call SDL_free() on the
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_gamecontroller.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_gamecontroller.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -73,7 +73,8 @@
     SDL_CONTROLLER_TYPE_NVIDIA_SHIELD,
     SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT,
     SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT,
-    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
+    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR,
+    SDL_CONTROLLER_TYPE_MAX
 } SDL_GameControllerType;
 
 typedef enum
@@ -524,6 +525,20 @@
 extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
 
 /**
+ * Get the Steam Input handle of an opened controller, if available.
+ *
+ * Returns an InputHandle_t for the controller that can be used with Steam Input API:
+ * https://partner.steamgames.com/doc/api/ISteamInput
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the gamepad handle, or 0 if unavailable.
+ *
+ * \since This function is available since SDL 2.30.0.
+ */
+extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller);
+
+
+/**
  * Check if a controller has been opened and is currently connected.
  *
  * \param gamecontroller a game controller identifier previously returned by
@@ -598,7 +613,9 @@
  *  and are centered within ~8000 of zero, though advanced UI will allow users to set
  *  or autodetect the dead zone, which varies between controllers.
  *
- *  Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX.
+ *  Trigger axis values range from 0 (released) to SDL_JOYSTICK_AXIS_MAX
+ *  (fully pressed) when reported by SDL_GameControllerGetAxis(). Note that this is not the
+ *  same range that will be reported by the lower-level SDL_GetJoystickAxis().
  */
 typedef enum
 {
@@ -687,8 +704,13 @@
  *
  * The axis indices start at index 0.
  *
- * The state is a value ranging from -32768 to 32767. Triggers, however, range
- * from 0 to 32767 (they never return a negative value).
+ * For thumbsticks, the state is a value ranging from -32768 (up/left)
+ * to 32767 (down/right).
+ *
+ * Triggers range from 0 when released to 32767 when fully pressed, and
+ * never return a negative value. Note that this differs from the value
+ * reported by the lower-level SDL_GetJoystickAxis(), which normally uses
+ * the full range.
  *
  * \param gamecontroller a game controller
  * \param axis an axis index (one of the SDL_GameControllerAxis values)
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_gesture.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_gesture.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_guid.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_guid.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_haptic.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_haptic.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_hidapi.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_hidapi.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_hints.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_hints.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -632,6 +632,110 @@
 #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
 
 /**
+ *  A variable containing a list of arcade stick style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of devices that should not be considerd joysticks.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES"
+
+/**
+ *  A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of flightstick style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of devices known to have a GameCube form factor.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES"
+
+/**
+ *  A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED"
+
+/**
  *  \brief  A variable controlling whether the HIDAPI joystick drivers should be used.
  *
  *  This variable can be set to the following values:
@@ -840,6 +944,17 @@
 #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM"
 
 /**
+ *  \brief  A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller 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_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK"
+
+/**
  *  \brief  A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used.
  *
  *  This variable can be set to the following values:
@@ -966,6 +1081,24 @@
 #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED"
 
 /**
+  *  A variable controlling whether IOKit should be used for controller handling.
+  *
+  *  This variable can be set to the following values:
+  *    "0"       - IOKit is not used
+  *    "1"       - IOKit is used (the default)
+  */
+#define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT"
+
+/**
+  *  A variable controlling whether GCController should be used for controller handling.
+  *
+  *  This variable can be set to the following values:
+  *    "0"       - GCController is not used
+  *    "1"       - GCController is used (the default)
+  */
+#define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI"
+
+/**
   *  \brief  A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices.
   *
   *  This variable can be set to the following values:
@@ -1008,6 +1141,32 @@
 #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
 
 /**
+ *  A variable containing a list of throttle style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED"
+
+/**
   *  \brief  A variable controlling whether Windows.Gaming.Input should be used for controller handling.
   *
   *  This variable can be set to the following values:
@@ -1017,6 +1176,45 @@
 #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI"
 
 /**
+ *  A variable containing a list of wheel style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of devices known to have all axes centered at zero.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES"
+
+/**
  * \brief Determines whether SDL enforces that DRM master is required in order
  *        to initialize the KMSDRM video backend.
  *
@@ -1085,6 +1283,22 @@
 #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES"
 
 /**
+ *  \brief A variable controlling the default SDL log levels.
+ *
+ *  This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications.
+ *
+ *  The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category.
+ *
+ *  The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category.
+ *
+ *  You can omit the category if you want to set the logging level for all categories.
+ *
+ *  If this hint isn't set, the default log levels are equivalent to:
+ *  "app=info,assert=warn,test=verbose,*=error"
+ */
+#define SDL_HINT_LOGGING   "SDL_LOGGING"
+
+/**
 *  \brief  When set don't force the SDL app to become a foreground process
 *
 *  This hint only applies to Mac OS X.
@@ -1486,6 +1700,32 @@
 #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"
 
 /**
+ *  A variable containing a list of ROG gamepad capable mice.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE"
+
+/**
+ *  A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED"
+
+/**
  *  \brief  A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
  *
  *  This variable can be set to the following values:
@@ -2441,6 +2681,22 @@
  *  This hint is available since SDL 2.24.0.
  */
 #define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY"
+
+/**
+ * Cause SDL to call dbus_shutdown() on quit.
+ *
+ * This is useful as a debug tool to validate memory leaks, but shouldn't ever
+ * be set in production applications, as other libraries used by the application
+ * might use dbus under the hood and this cause cause crashes if they continue
+ * after SDL_Quit().
+ *
+ * This variable can be set to the following values:
+ *   "0"       - SDL will not call dbus_shutdown() on quit (default)
+ *   "1"       - SDL will call dbus_shutdown() on quit
+ *
+ * This hint is available since SDL 2.30.0.
+ */
+#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT"
 
 
 /**
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_joystick.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_joystick.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_keyboard.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_keyboard.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -298,8 +298,10 @@
 extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputShown(void);
 
 /**
- * Set the rectangle used to type Unicode text inputs.
- *
+ * Set the rectangle used to type Unicode text inputs. Native input methods
+ * will place a window with word suggestions near it, without covering the
+ * text being inputted.
+ * 
  * To start text input in a given location, this function is intended to be
  * called before SDL_StartTextInput, although some platforms support moving
  * the rectangle even while text input (and a composition) is active.
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_keycode.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_keycode.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_loadso.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_loadso.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_locale.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_locale.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_log.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_log.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -59,7 +59,7 @@
  *  By default the application category is enabled at the INFO level,
  *  the assert category is enabled at the WARN level, test is enabled
  *  at the VERBOSE level and all other categories are enabled at the
- *  CRITICAL level.
+ *  ERROR level.
  */
 typedef enum
 {
@@ -352,7 +352,7 @@
  */
 extern DECLSPEC void SDLCALL SDL_LogMessageV(int category,
                                              SDL_LogPriority priority,
-                                             const char *fmt, va_list ap);
+                                             SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3);
 
 /**
  * The prototype for the log output callback function.
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_main.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_main.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_messagebox.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_messagebox.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_metal.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_metal.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_misc.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_misc.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_mouse.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_mouse.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_mutex.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_mutex.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_name.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_name.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_opengl.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_opengl.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_opengles.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_opengles.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_opengles2.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_opengles2.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_pixels.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_pixels.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -61,7 +61,10 @@
     SDL_PIXELTYPE_ARRAYU16,
     SDL_PIXELTYPE_ARRAYU32,
     SDL_PIXELTYPE_ARRAYF16,
-    SDL_PIXELTYPE_ARRAYF32
+    SDL_PIXELTYPE_ARRAYF32,
+
+    /* This must be at the end of the list to avoid breaking the existing ABI */
+    SDL_PIXELTYPE_INDEX2
 } SDL_PixelType;
 
 /** Bitmap pixel order, high bit -> low bit. */
@@ -134,6 +137,7 @@
 #define SDL_ISPIXELFORMAT_INDEXED(format)   \
     (!SDL_ISPIXELFORMAT_FOURCC(format) && \
      ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \
+      (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \
       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
 
@@ -177,6 +181,12 @@
     SDL_PIXELFORMAT_INDEX1MSB =
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,
                                1, 0),
+    SDL_PIXELFORMAT_INDEX2LSB =
+        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0,
+                               2, 0),
+    SDL_PIXELFORMAT_INDEX2MSB =
+        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0,
+                               2, 0),
     SDL_PIXELFORMAT_INDEX4LSB =
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,
                                4, 0),
@@ -276,11 +286,19 @@
     SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888,
     SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888,
     SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888,
+    SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_RGBX8888,
+    SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_XRGB8888,
+    SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_BGRX8888,
+    SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888,
 #else
     SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888,
     SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888,
     SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888,
     SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888,
+    SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_XBGR8888,
+    SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_BGRX8888,
+    SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_XRGB8888,
+    SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888,
 #endif
 
     SDL_PIXELFORMAT_YV12 =      /**< Planar mode: Y + V + U  (3 planes) */
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_platform.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_platform.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -165,6 +165,12 @@
 #else
 #define WINAPI_FAMILY_WINRT 0
 #endif /* HAVE_WINAPIFAMILY_H */
+
+#if (HAVE_WINAPIFAMILY_H) && defined(WINAPI_FAMILY_PHONE_APP)
+#define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+#else
+#define SDL_WINAPI_FAMILY_PHONE 0
+#endif
 
 #if WINAPI_FAMILY_WINRT
 #undef __WINRT__
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_power.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_power.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_quit.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_quit.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_rect.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_rect.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_render.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_render.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -42,7 +42,7 @@
  *  of the many good 3D engines.
  *
  *  These functions must be called from the main thread.
- *  See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995
+ *  See this bug for details: https://github.com/libsdl-org/SDL/issues/986
  */
 
 #ifndef SDL_render_h_
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_revision.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_revision.h
@@ -1,7 +1,7 @@
 /* Generated by updaterev.sh, do not edit */
 #ifdef SDL_VENDOR_INFO
-#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40 (" SDL_VENDOR_INFO ")"
+#define SDL_REVISION "SDL-release-2.30.1-0-g5adbf3765 (" SDL_VENDOR_INFO ")"
 #else
-#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40"
+#define SDL_REVISION "SDL-release-2.30.1-0-g5adbf3765"
 #endif
 #define SDL_REVISION_NUMBER 0
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_rwops.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_rwops.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_scancode.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_scancode.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_sensor.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_sensor.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_shape.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_shape.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_stdinc.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_stdinc.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -257,7 +257,7 @@
 #define SDL_PRIs64 PRIs64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIs64 "I64d"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIs64 "ld"
 #else
 #define SDL_PRIs64 "lld"
@@ -268,7 +268,7 @@
 #define SDL_PRIu64 PRIu64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIu64 "I64u"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIu64 "lu"
 #else
 #define SDL_PRIu64 "llu"
@@ -279,7 +279,7 @@
 #define SDL_PRIx64 PRIx64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIx64 "I64x"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIx64 "lx"
 #else
 #define SDL_PRIx64 "llx"
@@ -290,7 +290,7 @@
 #define SDL_PRIX64 PRIX64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIX64 "I64X"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIX64 "lX"
 #else
 #define SDL_PRIX64 "llX"
@@ -336,7 +336,9 @@
 #define SDL_PRINTF_FORMAT_STRING
 #define SDL_SCANF_FORMAT_STRING
 #define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber )
 #define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNCV( fmtargnumber )
 #else
 #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
 #include <sal.h>
@@ -362,10 +364,14 @@
 #endif
 #if defined(__GNUC__)
 #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 )))
+#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __printf__, fmtargnumber, 0 )))
 #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 )))
+#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 )))
 #else
 #define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber )
 #define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNCV( fmtargnumber )
 #endif
 #endif /* SDL_DISABLE_ANALYZE_MACROS */
 
@@ -603,11 +609,11 @@
 extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len);
 
 extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2);
-extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2);
 extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3);
-extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3);
 extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
-extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2);
 
 #ifndef HAVE_M_PI
 #ifndef M_PI
@@ -688,8 +694,8 @@
                                          size_t * outbytesleft);
 
 /**
- * This function converts a buffer or string between encodings in one pass, returning a
- * string that must be freed with SDL_free() or NULL on error.
+ * This function converts a buffer or string between encodings in one pass,
+ * returning a string that must be freed with SDL_free() or NULL on error.
  *
  * \since This function is available since SDL 2.0.0.
  */
@@ -698,8 +704,8 @@
                                                const char *inbuf,
                                                size_t inbytesleft);
 #define SDL_iconv_utf8_locale(S)    SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1)
-#define SDL_iconv_utf8_ucs2(S)      (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
-#define SDL_iconv_utf8_ucs4(S)      (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs2(S)      (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs4(S)      (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)
 #define SDL_iconv_wchar_utf8(S)     SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t))
 
 /* force builds using Clang's static analysis tools to use literal C runtime
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_surface.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_surface.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_system.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_system.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -593,7 +593,8 @@
 
 /* Functions used only by GDK */
 #if defined(__GDK__)
-typedef struct XTaskQueueObject * XTaskQueueHandle;
+typedef struct XTaskQueueObject *XTaskQueueHandle;
+typedef struct XUser *XUserHandle;
 
 /**
  * Gets a reference to the global async task queue handle for GDK,
@@ -609,6 +610,20 @@
  * \since This function is available since SDL 2.24.0.
  */
 extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue);
+
+/**
+ * Gets a reference to the default user handle for GDK.
+ *
+ * This is effectively a synchronous version of XUserAddAsync, which always
+ * prefers the default user and allows a sign-in UI.
+ *
+ * \param outUserHandle a pointer to be filled in with the default user
+ *                      handle.
+ * \returns 0 if success, -1 if any error occurs.
+ *
+ * \since This function is available since SDL 2.28.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(XUserHandle * outUserHandle);
 
 #endif
 
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_syswm.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_syswm.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_thread.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_thread.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_timer.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_timer.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_touch.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_touch.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_types.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_types.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_version.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_version.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -58,8 +58,8 @@
 /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
 */
 #define SDL_MAJOR_VERSION   2
-#define SDL_MINOR_VERSION   28
-#define SDL_PATCHLEVEL      5
+#define SDL_MINOR_VERSION   30
+#define SDL_PATCHLEVEL      1
 
 /**
  * Macro to determine SDL version program was compiled against.
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_video.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/SDL_video.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -1278,7 +1278,8 @@
 /**
  * Return whether the window has a surface associated with it.
  *
- * \returns SDL_TRUE if there is a surface associated with the window, or SDL_FALSE otherwise.
+ * \returns SDL_TRUE if there is a surface associated with the window, or
+ *          SDL_FALSE otherwise.
  *
  * \since This function is available since SDL 2.28.0.
  *
@@ -1339,6 +1340,11 @@
  * on the screen.
  *
  * This function is equivalent to the SDL 1.2 API SDL_UpdateRects().
+ *
+ * Note that this function will update _at least_ the rectangles specified,
+ * but this is only intended as an optimization; in practice, this might
+ * update more of the screen (or all of the screen!), depending on what
+ * method SDL uses to send pixels to the system.
  *
  * \param window the window to update
  * \param rects an array of SDL_Rect structures representing areas of the
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/begin_code.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/begin_code.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -36,6 +36,8 @@
 #ifndef SDL_DEPRECATED
 #  if defined(__GNUC__) && (__GNUC__ >= 4)  /* technically, this arrived in gcc 3.1, but oh well. */
 #    define SDL_DEPRECATED __attribute__((deprecated))
+#  elif defined(_MSC_VER)
+#    define SDL_DEPRECATED __declspec(deprecated)
 #  else
 #    define SDL_DEPRECATED
 #  endif
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/close_code.h
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Headers/close_code.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Resources/CMake/sdl2-config.cmake
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Resources/CMake/sdl2-config.cmake
@@ -31,8 +31,15 @@
 
 set(SDL2_FOUND TRUE)
 
-string(REGEX REPLACE "SDL2\\.framework.*" "SDL2.framework" SDL2_FRAMEWORK_PATH "${CMAKE_CURRENT_LIST_DIR}")
-string(REGEX REPLACE "SDL2\\.framework.*" "" SDL2_FRAMEWORK_PARENT_PATH "${CMAKE_CURRENT_LIST_DIR}")
+# Compute the installation prefix relative to this file.
+set(SDL2_FRAMEWORK_PATH "${CMAKE_CURRENT_LIST_DIR}")                                # > /SDL2.framework/Resources/CMake/
+get_filename_component(SDL2_FRAMEWORK_PATH "${SDL2_FRAMEWORK_PATH}" REALPATH)       # > /SDL2.framework/Versions/Current/Resources/CMake
+get_filename_component(SDL2_FRAMEWORK_PATH "${SDL2_FRAMEWORK_PATH}" REALPATH)       # > /SDL2.framework/Versions/A/Resources/CMake/
+get_filename_component(SDL2_FRAMEWORK_PATH "${SDL2_FRAMEWORK_PATH}" PATH)           # > /SDL2.framework/Versions/A/Resources/
+get_filename_component(SDL2_FRAMEWORK_PATH "${SDL2_FRAMEWORK_PATH}" PATH)           # > /SDL2.framework/Versions/A/
+get_filename_component(SDL2_FRAMEWORK_PATH "${SDL2_FRAMEWORK_PATH}" PATH)           # > /SDL2.framework/Versions/
+get_filename_component(SDL2_FRAMEWORK_PATH "${SDL2_FRAMEWORK_PATH}" PATH)           # > /SDL2.framework/
+get_filename_component(SDL2_FRAMEWORK_PARENT_PATH "${SDL2_FRAMEWORK_PATH}" PATH)    # > /
 
 # For compatibility with autotools sdl2-config.cmake, provide SDL2_* variables.
 
@@ -49,12 +56,12 @@
 # This is done for compatibility with CMake generated SDL2-target.cmake files.
 
 if(NOT TARGET SDL2::SDL2)
-    add_library(SDL2::SDL2 INTERFACE IMPORTED)
+    add_library(SDL2::SDL2 SHARED IMPORTED)
     set_target_properties(SDL2::SDL2
         PROPERTIES
-            INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\""
+            FRAMEWORK "TRUE"
+            IMPORTED_LOCATION "${SDL2_FRAMEWORK_PATH}/Versions/A/SDL2"
             INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
-            INTERFACE_LINK_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\";SHELL:-framework SDL2"
             COMPATIBLE_INTERFACE_BOOL "SDL2_SHARED"
             INTERFACE_SDL2_SHARED "ON"
             COMPATIBLE_INTERFACE_STRING "SDL_VERSION"
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Resources/Info.plist
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Resources/Info.plist
@@ -3,7 +3,7 @@
 <plist version="1.0">
 <dict>
 	<key>BuildMachineOSBuild</key>
-	<string>22F82</string>
+	<string>23D60</string>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>English</string>
 	<key>CFBundleExecutable</key>
@@ -19,7 +19,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.28.5</string>
+	<string>2.30.1</string>
 	<key>CFBundleSignature</key>
 	<string>SDLX</string>
 	<key>CFBundleSupportedPlatforms</key>
@@ -27,7 +27,7 @@
 		<string>MacOSX</string>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>2.28.5</string>
+	<string>2.30.1</string>
 	<key>DTCompiler</key>
 	<string>com.apple.compilers.llvm.clang.1_0</string>
 	<key>DTPlatformBuild</key>
@@ -35,15 +35,15 @@
 	<key>DTPlatformName</key>
 	<string>macosx</string>
 	<key>DTPlatformVersion</key>
-	<string>13.3</string>
+	<string>14.2</string>
 	<key>DTSDKBuild</key>
-	<string>22E245</string>
+	<string>23C53</string>
 	<key>DTSDKName</key>
-	<string>macosx13.3</string>
+	<string>macosx14.2</string>
 	<key>DTXcode</key>
-	<string>1431</string>
+	<string>1520</string>
 	<key>DTXcodeBuild</key>
-	<string>14E300c</string>
+	<string>15C500b</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>10.11</string>
 </dict>
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Resources/License.txt
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/Resources/License.txt
@@ -1,6 +1,6 @@
 
 Simple DirectMedia Layer
-Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
   
 This software is provided 'as-is', without any express or implied
 warranty.  In no event will the authors be held liable for any damages
--- a/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/_CodeSignature/CodeResources
+++ b/release/macos/ft2-clone-macos.app/Contents/Frameworks/SDL2.framework/Versions/A/_CodeSignature/CodeResources
@@ -10,15 +10,15 @@
 		</data>
 		<key>Resources/CMake/sdl2-config.cmake</key>
 		<data>
-		s2hXhDxzy/ilC+gLamGy/Kq13jo=
+		HFjU0snuPDDpVpeJJsOGAfWEqrU=
 		</data>
 		<key>Resources/Info.plist</key>
 		<data>
-		E/exzjLmO25/xe18BS765cbGzWY=
+		ZHmmRK90boQu0lf8kuoupR5C534=
 		</data>
 		<key>Resources/License.txt</key>
 		<data>
-		fCUUBjJ4JuUAC8MRSCszNcY21v8=
+		A8VTYHTg+gsOssUp337xdGbdHW0=
 		</data>
 		<key>Resources/ReadMe.txt</key>
 		<data>
@@ -26,7 +26,7 @@
 		</data>
 		<key>Resources/default.metallib</key>
 		<data>
-		07w7GQmm31+NEK8ne4mSo7m70Do=
+		QwX80pzFcZED9JtaD8IhQ/uayn0=
 		</data>
 	</dict>
 	<key>files2</key>
@@ -35,11 +35,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			hzPz83uejvKAqzL0Xoi6aO8h8jw=
+			Lfl2hNX45Yauw4rksgqb/XdphDk=
 			</data>
 			<key>hash2</key>
 			<data>
-			9u/or17IhYmY6rFVU14yva0lEIgG9DmS4LbiwXBLBL8=
+			5ZHTKNpFq6FjJ9eAzN+z9MzYhRUuH9A2ld+654PJGxA=
 			</data>
 		</dict>
 		<key>Headers/SDL_assert.h</key>
@@ -46,11 +46,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			S50t60okfb3/ykWKavFC3tnkGgE=
+			pYW903dbT5whp+Qrix78+qX0jwE=
 			</data>
 			<key>hash2</key>
 			<data>
-			uPZQOi25pO/BZWjREOhxmXsoreSNJyZrNOnVJ/TyYzs=
+			8rHzmD0mEbISieyXtdyAKk4sVsPwozGVXxO+fPUcwh4=
 			</data>
 		</dict>
 		<key>Headers/SDL_atomic.h</key>
@@ -57,11 +57,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			yrv6uC/CjYpeCteZDUbBFr2nwiU=
+			kmlvyb/D7tTnqB5/SPn+uzEVwWo=
 			</data>
 			<key>hash2</key>
 			<data>
-			Mrfc980NeBAvQ5I040V8xusL6cHBcFfPaA9B2prA4dw=
+			jKCpopkvsvgFD4Kw3f33cJ/NnrINF539gONibFVIB9Q=
 			</data>
 		</dict>
 		<key>Headers/SDL_audio.h</key>
@@ -68,11 +68,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			ATRDpv42XjNUWqjKPDAPYqIqvDY=
+			mO1jIX10BMO3YSgktP4b6Z1Oyqs=
 			</data>
 			<key>hash2</key>
 			<data>
-			MThYj7HEVNC7MdUTbzgyHDqlDMDS9g664b6M5d7tsdY=
+			dwmzZFx1CKgM7pYIq4tw7eGJMeAAJ5s3CyXDbfXYKpI=
 			</data>
 		</dict>
 		<key>Headers/SDL_bits.h</key>
@@ -79,11 +79,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Y7zU8XCX6cvmN/FK9COruPP8VGs=
+			vq8tkT27C0LpOpam3jt6SPKcF38=
 			</data>
 			<key>hash2</key>
 			<data>
-			5bLOm9HAk5AScYemc5V1usN7NqP685ZYN5MOBjzC2IE=
+			ThaIbzANB0DHeg/muc+XlpzRJ/gquRny6eg+T3/AZRo=
 			</data>
 		</dict>
 		<key>Headers/SDL_blendmode.h</key>
@@ -90,11 +90,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			ThQw2vcWPo/mLtvKmhQrjhSQhLk=
+			UJ3UsJ8PkmGKXFMsWbGjktY/McY=
 			</data>
 			<key>hash2</key>
 			<data>
-			o3UtzbWJqnTeh6+r+oLVdOzcJZ1b3XhfPINDjKHftu4=
+			4fn7qawnnPu+HK3N6XAbRESMCm0k6OKgh/swb9XhboI=
 			</data>
 		</dict>
 		<key>Headers/SDL_clipboard.h</key>
@@ -101,11 +101,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			pFjnEWnFn2vCXZrSDQ6m8N6h0MM=
+			RnO4GfCniF8MlqHGKKb46VIosQc=
 			</data>
 			<key>hash2</key>
 			<data>
-			t9Fr9UxC9zwgfkCY5P5DW9k3TndMFRn+tU/heffUOQk=
+			Wz9oWs2a8ZN4QUrt0nEcldfa+eZpXfIcDToxBX1KzfI=
 			</data>
 		</dict>
 		<key>Headers/SDL_config.h</key>
@@ -112,11 +112,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			B13VD2wcb7zADcKXB+B/kBYhpHw=
+			ER627OINXZReUtB0UvhF/JFlrFk=
 			</data>
 			<key>hash2</key>
 			<data>
-			LmXzL1O6PasyaBOUhPezJnqtqwCV9rqOyiJNEvGKgHo=
+			1anVcKcfwQrtjHH7cteXCA5OCcOgmB7EFfDnCb+gSZk=
 			</data>
 		</dict>
 		<key>Headers/SDL_config_macosx.h</key>
@@ -123,11 +123,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			/CrGe7lmePlmR7DD9sqN4LHqM/0=
+			oU+969jqvMDgqHV1WA4yZm1gr9k=
 			</data>
 			<key>hash2</key>
 			<data>
-			EpnSzka/wAuxi4wcgIktwQnuYWsMAATYMt6yDmo4zOg=
+			c9+monw3gWrEZOhytKTuc1hSbhEo+HiCBZ4jJOpjg+M=
 			</data>
 		</dict>
 		<key>Headers/SDL_copying.h</key>
@@ -134,11 +134,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			OzEuv+IaGVfj3A2BEoXc87vV+Wk=
+			eMSBsshKdTT5uzXvgxE8eZJnqU0=
 			</data>
 			<key>hash2</key>
 			<data>
-			5zsYMLhj8aKXm4gWJoGHC55ipiUi1OIxXdOtUIHQQw4=
+			8rjaG1pCV5vum9i9zkW6VPXHWLgTjYk+LetUSsfhdho=
 			</data>
 		</dict>
 		<key>Headers/SDL_cpuinfo.h</key>
@@ -145,11 +145,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			4/UkY/aNgAY5RsZ61XSnwtCXW9I=
+			mdEBzZyevtfCXZXXEJ8sEfUNr4U=
 			</data>
 			<key>hash2</key>
 			<data>
-			pWPZkQcmPyAzgZNKcmiYutw8VFjBcHOinO+VVKIBeN0=
+			V8DTu2oLBQZVxwExFsdWY3S7eIvxwh2Kc/C9TgUHS/g=
 			</data>
 		</dict>
 		<key>Headers/SDL_endian.h</key>
@@ -156,11 +156,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			j6/tuHiJfdv8YaI9k3fogDw4bNc=
+			a0rFYa+ZaAeCp1OLc1MUigSxv3I=
 			</data>
 			<key>hash2</key>
 			<data>
-			P5KOVzR2wBlhdSw7biIJ3O78dnYnoGdi4pHxvyFcLdY=
+			KzsbIelOUqvXltchBHLBt2FYxr6ECXOXllAo8I4cgJQ=
 			</data>
 		</dict>
 		<key>Headers/SDL_error.h</key>
@@ -167,11 +167,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			6cwM6B1MfW2wTFB+g6c1GO9UH7g=
+			6FbRl5QI1EDOgcFrO88vwobsvgk=
 			</data>
 			<key>hash2</key>
 			<data>
-			ULQrtxP4RfbnV5GGj3i+PrYSI/rzDYskl0XQtCd72SU=
+			UK6Fy7gMMKetaQ8oLxZ5/YjRDBnehbSYWdS5NU+0bT8=
 			</data>
 		</dict>
 		<key>Headers/SDL_events.h</key>
@@ -178,11 +178,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			feHsZTKREoq2xXa4dv/4lzZqzUc=
+			DjRO2l0fKHz9CqTSSEjZmJfk9EQ=
 			</data>
 			<key>hash2</key>
 			<data>
-			FVz2yvXnjsUNWBsWQOcBqaZrXCCdohSRWDh1l3SKqRY=
+			D9kT1tG6R/HNm/q288zZFC6ukV75D69FcWgwYsnc8fc=
 			</data>
 		</dict>
 		<key>Headers/SDL_filesystem.h</key>
@@ -189,11 +189,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			sicIJ2kroxv3QVkoKklHGN3tbWo=
+			V8DtkwjBL6IAXnY3x3Y3GBN5V/g=
 			</data>
 			<key>hash2</key>
 			<data>
-			k3ybgbDF/Ap8kf4vKxLVZnRXoXtZwpFb4Nsk8GWqDCY=
+			0dS4S8y/h4M5KPReX8OBpo3gpKeCLfH7QvK3hnL0Z3Y=
 			</data>
 		</dict>
 		<key>Headers/SDL_gamecontroller.h</key>
@@ -200,11 +200,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			DGpJeIYXN/t/Yyqilband2kKOSk=
+			JpK2cxtJKHW3otMI+J0LB9HKV0I=
 			</data>
 			<key>hash2</key>
 			<data>
-			hgAaf8SQwVfc94yXKjNFA3VpsTCYwL65W5X6lXEnsgI=
+			05DHXySUkbPAFsZ06PH81S+gw42DJijM4g5o8b7GhdI=
 			</data>
 		</dict>
 		<key>Headers/SDL_gesture.h</key>
@@ -211,11 +211,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			iBwReSkmy4b/H3FD3mZZtLNdCMk=
+			jU1rTN3CXe1BxlIBiYoxftM6MYY=
 			</data>
 			<key>hash2</key>
 			<data>
-			H7K4JyorBvI9vlJegmEZ6NvapE7/l/2bhOGeQ9zudiE=
+			mgTChHVZZGYvTqJ1zFxt+PZbfvlOAXp1UoiPQtFcsVQ=
 			</data>
 		</dict>
 		<key>Headers/SDL_guid.h</key>
@@ -222,11 +222,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			jTpr9nvDtYvix2njIOclQs9xYuk=
+			L3CGapDqXLCS7ZfawgCKGbSjFQQ=
 			</data>
 			<key>hash2</key>
 			<data>
-			ifUKQBbQRJdNqsJBO7Mor3KqQyqDulvyNC82/RWPXhs=
+			qUA3cQGQCyMg0ipdfCbjASvzYDj0Zx7H5ffPcvWfwVw=
 			</data>
 		</dict>
 		<key>Headers/SDL_haptic.h</key>
@@ -233,11 +233,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			+Wt7zxeuXghMudXSohdJr12ueGM=
+			701dA7tkS7/YfKQufm9k5x1xP8Q=
 			</data>
 			<key>hash2</key>
 			<data>
-			VhCeKNAvsH+lrvZW9g65G84lg0FofrbORvS0TqPWaRQ=
+			ItVljPsplw8TGMOYCO77lZsUfVph375JnUCb+ne/SwY=
 			</data>
 		</dict>
 		<key>Headers/SDL_hidapi.h</key>
@@ -244,11 +244,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			CBwPZQMZ5wsa03aBND8rQvsLfUg=
+			0fdfgesRdg1vKFY634kkFiZ98Ng=
 			</data>
 			<key>hash2</key>
 			<data>
-			CJEdgW9T0b2VRNRFaEZqPeCTg3FjsEFOHZvwuJbVHX0=
+			ePZqkV6EC8UOvqW8YdC6QIqQj1WT+hV8A+iuyMBkTEM=
 			</data>
 		</dict>
 		<key>Headers/SDL_hints.h</key>
@@ -255,11 +255,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			SWTHcoPzInj/HwBHNEFfQGmL6Dw=
+			/qk7BWYdVU6PpDcEUcVmK+Wz2s8=
 			</data>
 			<key>hash2</key>
 			<data>
-			BQwW6YWVYXbaOLc9Id+ZjuKHs2VIfcSjM/Oo9JBI6Yk=
+			6H5P80fBEK45UuA2f9Pcl8+VY0Dep8nNNYIf02eZm6Q=
 			</data>
 		</dict>
 		<key>Headers/SDL_joystick.h</key>
@@ -266,11 +266,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Y/dkiMb7+9Wmo8oyyOuh4igQK4o=
+			OrlFzMtKvIkbEWrrrnwBGe3oboU=
 			</data>
 			<key>hash2</key>
 			<data>
-			d3rYIj9RV45IuiYZAbOQyNe3iR4DORkkqwYiSA81c6k=
+			sjqpfn82SFN+38d2/UGvZFO4MWM7MMFYXW0yiv5QTfo=
 			</data>
 		</dict>
 		<key>Headers/SDL_keyboard.h</key>
@@ -277,11 +277,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			4jiEP+XRfvz8VFmNWlHkcsMS2nI=
+			O8EeqERllEiSUVekqaGWTi+08SE=
 			</data>
 			<key>hash2</key>
 			<data>
-			EPdkxf3E/uXb/dm3gpxepX+d5JNWswuHP+PG/c33p84=
+			YY8QUjagHNuyjj7+A2likirYjtVGBLRrLaiL3XFF6pI=
 			</data>
 		</dict>
 		<key>Headers/SDL_keycode.h</key>
@@ -288,11 +288,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			j4z7vftDr05ahrBr5bZnBxZ3Ufs=
+			4M4+qKPCh8Nt9KMtKXhGfEHHGfA=
 			</data>
 			<key>hash2</key>
 			<data>
-			abAEws/ibkdlWSE/bP/uq0oIjcebU59aul5g4Lu0pbA=
+			RMfX8LUIJxh/jsaJU/xByIJkjv0Ad106DFZHsZv8pbM=
 			</data>
 		</dict>
 		<key>Headers/SDL_loadso.h</key>
@@ -299,11 +299,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			1fe02ZD9+yDX75ZVM1rk7RqDLCc=
+			Asx7u68oasK39D4GZW1/srAylls=
 			</data>
 			<key>hash2</key>
 			<data>
-			eOcuzAcWhFDvl3bV+3m54GtOrTQztPLIiFHK6NOQuZM=
+			RiRV45B7euwlx+hcq4qKfEFmHNSH1mkstcUpTVvYSSs=
 			</data>
 		</dict>
 		<key>Headers/SDL_locale.h</key>
@@ -310,11 +310,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			UOhBMG0JOnoQAEGMY7S6as755IY=
+			nRgzIlI3HM0T/WNjLJJEi38OPMo=
 			</data>
 			<key>hash2</key>
 			<data>
-			yM4RN7sKzLhnVlwbW1pJX3S6YLZl2LM/0qsLyQf5GXM=
+			EMRbgbDbQ+odh3x2XBIyspvdqB2kra0FOf74BrGKgPY=
 			</data>
 		</dict>
 		<key>Headers/SDL_log.h</key>
@@ -321,11 +321,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Ij4wEHg0aIMC28dTUSur/CAxQss=
+			tAwHSPVWPAZGWPtCSUlHq3JdvyA=
 			</data>
 			<key>hash2</key>
 			<data>
-			A1Xc1+qvTtDHCz8f4e6oWq8SlifqizcVZ1Q37GJkhG0=
+			VMaId0hYgkcr2YDH2N33c0i38gPrs9+L/ANMpAiny9g=
 			</data>
 		</dict>
 		<key>Headers/SDL_main.h</key>
@@ -332,11 +332,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			j0/bBvlkrYcnXeoB6sWoCQiIlV0=
+			lykTlv+S6hpMWHZrRgY1mlpO2Wg=
 			</data>
 			<key>hash2</key>
 			<data>
-			QOjL/8v8HMC/N+1jocNxIGBB5pifTDWxbwOvD7wJtRg=
+			LxrUoSwibHgYszYJXkUxZNBHRVOQWyteyv+bar2Dq5Y=
 			</data>
 		</dict>
 		<key>Headers/SDL_messagebox.h</key>
@@ -343,11 +343,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			TZHRdWCuyxbRdc1GZjnTjHdKV5A=
+			9nzIVO7dY406xCHa2KEIJcO1+j4=
 			</data>
 			<key>hash2</key>
 			<data>
-			Y+cutYk+JQOcbC9kbCdqbLr4oIBCxcX8HIzKJW+MOTE=
+			YU77COq8qX9fvy6hzGxakm44tOIAv/7OsoAKTdF6Az8=
 			</data>
 		</dict>
 		<key>Headers/SDL_metal.h</key>
@@ -354,11 +354,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			yggpDR8fWdb4ZAxZDLO7ztOMa84=
+			l3WpnmYNTFJDOc4VfGpqDOzca2A=
 			</data>
 			<key>hash2</key>
 			<data>
-			aVk9kP7LRPopLu52brj5b7qNwMeUyUOwDPVyXwOm4O0=
+			23emwjTJmRlFUl0ONQTFOXiwp5rZigMgRoNpVs+/3+8=
 			</data>
 		</dict>
 		<key>Headers/SDL_misc.h</key>
@@ -365,11 +365,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			wkzkXLc/0JwEBj+pVGBGODS/N7g=
+			jRjlVh5Vv0djqm/W/za7thtYCqA=
 			</data>
 			<key>hash2</key>
 			<data>
-			qClRwcNymRF0gmpjyJ+EQ7fChV48OUN8NAAM2x8NsRM=
+			ccGvw3H5qbNv1VNvV/f6zgzu62kpdXFy+r3mqfrVeBQ=
 			</data>
 		</dict>
 		<key>Headers/SDL_mouse.h</key>
@@ -376,11 +376,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			AL6jjX5llLXh3nscuX0MJQQJ7C0=
+			Gm6qznp86I5NOFZmRjhrT++5TBk=
 			</data>
 			<key>hash2</key>
 			<data>
-			8R3uVCCs2wF9vtwJEqAi+xjYtAtJ1F6UIqCPUhiBwxU=
+			gwvY1lfpF7M2HbTITBi8QZI+tbgVNvI9O1NxtoxBoRc=
 			</data>
 		</dict>
 		<key>Headers/SDL_mutex.h</key>
@@ -387,11 +387,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			c4s6haEURwhr1L/ZsIoQHgDC1Rw=
+			9vbOLsFVFElR47I5TtXjf4pedQo=
 			</data>
 			<key>hash2</key>
 			<data>
-			L1kG6r9N1C+njGEvU0sAJeAVFwr6gkCCwGcBxsjDuNU=
+			ffswmnD3jDjyU8iH7L06flM6p819OSNl8NEcZ4kHjoA=
 			</data>
 		</dict>
 		<key>Headers/SDL_name.h</key>
@@ -398,11 +398,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			86Aic9zf8RE0YQGymeyFxdGck34=
+			cnC/QF1H86przORFvDObebgj5EA=
 			</data>
 			<key>hash2</key>
 			<data>
-			U6Hh9de6D0JfccwHBmoAy/zaFw30VuNT1ofo30X7cCw=
+			9fbQrzTVlIE/DhtOXfxt0UmZ0XXGnb8fBspcvPpqzcg=
 			</data>
 		</dict>
 		<key>Headers/SDL_opengl.h</key>
@@ -409,11 +409,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			a83WQIdV8u+rut4US8joNjpA6kA=
+			fQnZ5+4QU4D2hdgVZbuajaBHPcs=
 			</data>
 			<key>hash2</key>
 			<data>
-			HxWMmpZ2o+Z1atgt7Ou2sf5/4s2raLbApxzyqqzQcGY=
+			2Ctx+UxI6AbjN3VC0IHf0VO8wTUUi3B3sEMe/Kw7JUo=
 			</data>
 		</dict>
 		<key>Headers/SDL_opengl_glext.h</key>
@@ -431,11 +431,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Vc//lrKlqY/bME9ocSWczplleP4=
+			qc/icyfTwVqep3xCBWgeJfq0XXU=
 			</data>
 			<key>hash2</key>
 			<data>
-			hJHBadVAgpV3dIMW++DPSJKqsNOCvkA8qNrMoFbXd5g=
+			lxKvbpPsHmGoSaeXFm2q1chRJyxVms+CzAJvRtK637k=
 			</data>
 		</dict>
 		<key>Headers/SDL_opengles2.h</key>
@@ -442,11 +442,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			gyrJUUv02Am+DYc5V42xH7EQev4=
+			jPiOGyiIm0zNA2ktCXPlPZSRNOA=
 			</data>
 			<key>hash2</key>
 			<data>
-			T7CsPQJXfeZ3+pVjGLqzKBfEjyHX2Ne0vV44iZMKDgs=
+			gz/JKk8t4jDIXWlHuYzPYJMnYJoVRKMaEGKxYB69dHA=
 			</data>
 		</dict>
 		<key>Headers/SDL_opengles2_gl2.h</key>
@@ -497,11 +497,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			4PRTgauh2fx03ubJfuuHNOPhN28=
+			MYcJ6ZiKAY8zdgCwA/FlUbT5a/4=
 			</data>
 			<key>hash2</key>
 			<data>
-			GZQPt4sz55DRDRzw6E2c1WMjhNqInkQA3gxLQiTPQlw=
+			k/Hwy+Me3zpo9gYWt1cxsQAkMKtg8FS2oZLB5H1IHms=
 			</data>
 		</dict>
 		<key>Headers/SDL_platform.h</key>
@@ -508,11 +508,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Ey0u3gHjhY9CsV6rnGPL6l/Lqx4=
+			wJW6P5cSLWw7CLKwCduRMFILJMs=
 			</data>
 			<key>hash2</key>
 			<data>
-			n9zH0IFb2hWb/ZQ3TBMQxLzDre/VQcI6Obhdmq8O7QU=
+			rfvhg9xhDPbHHDguY5qvRo/mzZyCbJMSA9625XkbQy0=
 			</data>
 		</dict>
 		<key>Headers/SDL_power.h</key>
@@ -519,11 +519,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			SmO5g1nUZ1IAgDQGIlzbR8F5udg=
+			alQ7owSLOu8oi+p5TCVtXLfg49U=
 			</data>
 			<key>hash2</key>
 			<data>
-			Lmp/XdN6xQbqR/eAmoKFcpqk+MM65gGxjv1cLYUqG8c=
+			/a3V+xg47qsi9m/jjhPv4j5epEExGUpm65R9DBKOgdU=
 			</data>
 		</dict>
 		<key>Headers/SDL_quit.h</key>
@@ -530,11 +530,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			xxqxk2GqAVUt7s8YiRcGMegy160=
+			HBhMaa9dpoxys7lX8bShTrrw26c=
 			</data>
 			<key>hash2</key>
 			<data>
-			cd4fDfe+MqMZ35xoFn5VPkGBafcN9tPvL9J74IeKtXI=
+			Zy837L/c8/F/z/t7UE/2IKDrEYSf+/9IM+y/rifeK9Q=
 			</data>
 		</dict>
 		<key>Headers/SDL_rect.h</key>
@@ -541,11 +541,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			AtB+xgoXRW94PDzzbBVBYyAW0gI=
+			TMAFS6Xx6FfFUZosiA08UZGMO7Y=
 			</data>
 			<key>hash2</key>
 			<data>
-			rFxcleBxja/rwskrEIytxw3evL+Drkx3YsihtllIw78=
+			B6FuiG3NCFAQRp2UVMcmgSowkeZ1hP5VCdzArvGYEjk=
 			</data>
 		</dict>
 		<key>Headers/SDL_render.h</key>
@@ -552,11 +552,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			5yyytzTD1eS/K13NSzW6faLAUlA=
+			kUCWkbsEF23oO4MCCs2EbwDQusI=
 			</data>
 			<key>hash2</key>
 			<data>
-			+ljWDPQHFdheD/Z6QxHzbpNQVg/XVlqx5+B3ovMbIF0=
+			FRXH4yrITpDqn2IBdQ2Lbx7Jn6o0UuPRsjd4OWj78yI=
 			</data>
 		</dict>
 		<key>Headers/SDL_revision.h</key>
@@ -563,11 +563,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			bdjBB5+RLx5fhpvXy3LbyEC9q70=
+			BP7HEBYnBwbk8tHzZPgc3YbrqxQ=
 			</data>
 			<key>hash2</key>
 			<data>
-			GAe3NNLzg+OqUvN6Bxys9o9XWV6xzSDq/uCDwqmLz2s=
+			OaVGrGQNu1FqBbGBlpCqSy2PHisu9o9LzvAg42f1/JI=
 			</data>
 		</dict>
 		<key>Headers/SDL_rwops.h</key>
@@ -574,11 +574,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			sCmzKOj8q3vee6JV6acptKOzBoQ=
+			X/FUhtgu4xCdkYBGb+ldcBcGZsY=
 			</data>
 			<key>hash2</key>
 			<data>
-			j6rnTfnMJaCsq2CviHQP8obbVNgrElC0OXJBt3ltyVg=
+			a2EUuuUAqW0fvq6RZT8pXnh5L/5v0fQWSLdrujvKMqA=
 			</data>
 		</dict>
 		<key>Headers/SDL_scancode.h</key>
@@ -585,11 +585,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			JPnDQuCIC32+ugD3OX3igjdGfmE=
+			KoO35m+cbDILMQvS85Ns37rEDjY=
 			</data>
 			<key>hash2</key>
 			<data>
-			vC/EC0A66ywzXwlp8iGE7nlOpWGZ18iHhEdS7BsM3VU=
+			i/34qMDYybTiAylZuNfCadHerKiHZ06/kBn6i/txqLk=
 			</data>
 		</dict>
 		<key>Headers/SDL_sensor.h</key>
@@ -596,11 +596,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			J+9woN1Qec074rah/rly1BHM5sY=
+			dt0dQe91kXtmVwHldbMs3pSqKuE=
 			</data>
 			<key>hash2</key>
 			<data>
-			sEfbN4S8Lpxm0XDblgOvnVV0fsgx/zo/q0s5h9OvhmE=
+			+J/fkDU0AnB1KtUPYvFD3BIcHr0mXLJoyHvrtofnlRs=
 			</data>
 		</dict>
 		<key>Headers/SDL_shape.h</key>
@@ -607,11 +607,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Hv8O7XLnXLIVAOf6cjF56yyrRkg=
+			kpJhZUECgTha8Y9BJVRTLbsu6p8=
 			</data>
 			<key>hash2</key>
 			<data>
-			XFA3qPWL1vJ3EQtae2baJlOZ9ESEmhB1FMYI3fITLZY=
+			DsOpuFRKUgZwW8zSjrvgzY5QiVnH4qzikkNFfE4R784=
 			</data>
 		</dict>
 		<key>Headers/SDL_stdinc.h</key>
@@ -618,11 +618,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			iliyExriwpoxEAgG8CI8CG8go54=
+			PIRMBuyz3AvzjRzhE27KkDue7jw=
 			</data>
 			<key>hash2</key>
 			<data>
-			I4aI+ExJq+16kZfDjF++Uaa2lHZjUWmuFc83IUDfuIk=
+			Y3QmCQscBokS/69IsU1FFMnAT3y9gE2tvU0uJkkC5F4=
 			</data>
 		</dict>
 		<key>Headers/SDL_surface.h</key>
@@ -629,11 +629,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Toy3u0xKUfSMmknlIToaUmf5vwE=
+			WtK2vSy/4+ez9IC9XEutgDDYqEQ=
 			</data>
 			<key>hash2</key>
 			<data>
-			CDctL0QJDSDvlB+uXO69kLW2uA0Xdc0xiJBN8h3pX74=
+			1j47d6UhPnUkiWpFDu/JiESXUSIoJc9usypSBXhkSXk=
 			</data>
 		</dict>
 		<key>Headers/SDL_system.h</key>
@@ -640,11 +640,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			I1i3X5zfVBg7YFzag2Dj43RzuUI=
+			2hXj/s+4iotUYQ/qacOSBEGZOwg=
 			</data>
 			<key>hash2</key>
 			<data>
-			mt328KSVoSMSjZ4Wy268tC04JQmyCAsDM60TWeG3K4s=
+			1UwQf2RE20ecBIH+hfGWJftxYFTVSAzailQDO2A4TNg=
 			</data>
 		</dict>
 		<key>Headers/SDL_syswm.h</key>
@@ -651,11 +651,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			7sdDIYSuCZbE13gdwZ+rmiqUBEk=
+			3bhBPpfxPHznhnK4qD/z3JMAH6M=
 			</data>
 			<key>hash2</key>
 			<data>
-			6QWGeehhVCpiwN9fQv1by5vpdNg8JqxY1XgR48Fxpdc=
+			MPw8TZLw/QvquHCjlJlNDPjjt8f1IlMKzMfWgn1EF3U=
 			</data>
 		</dict>
 		<key>Headers/SDL_thread.h</key>
@@ -662,11 +662,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			rdWafQMEiS2pSqeEGdRXDjaU96Q=
+			1EtqS0N8COfcjGjv8z6z+LQAX3U=
 			</data>
 			<key>hash2</key>
 			<data>
-			pVkN+av2tjneOX9IafFyXjDRaWe/ROSrLwUQRfCrYYA=
+			l8BOBXAsdov/Q/EbiOiV79CL9dMEnX4y5a/ET0zjVcM=
 			</data>
 		</dict>
 		<key>Headers/SDL_timer.h</key>
@@ -673,11 +673,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			Nstsm7GCSSnoH66923lImFIE0fY=
+			HA8k26mZn4Ws75q3lUPqNM195Ms=
 			</data>
 			<key>hash2</key>
 			<data>
-			6jmEztIQClT68gsMRHHP9tVPF5TxqLfBgmkTqOA00fs=
+			F20rU5/Zn2KplGmTtClppmMyMWHLeVaEONbGDAwZ5CI=
 			</data>
 		</dict>
 		<key>Headers/SDL_touch.h</key>
@@ -684,11 +684,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			LWDPymUVgQxlg3DwBCJ8klXPq6U=
+			MIP5UyBQZhIYlI9EqCgc5hJdhlI=
 			</data>
 			<key>hash2</key>
 			<data>
-			y/Kqn35XtKznNX9foqsPjC+jlnbRvBuF8A1MzKIjBmY=
+			D0XePcMfVFz1/CDx1TMFLtaZ1jo7wIcXt5wvjqVuipU=
 			</data>
 		</dict>
 		<key>Headers/SDL_types.h</key>
@@ -695,11 +695,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			8xeioL5fy1QauaS4i9g5UdMotoM=
+			xbfdEra92WqYikDB55Po6KyR06E=
 			</data>
 			<key>hash2</key>
 			<data>
-			Em64WSsB0scWcgjtDOAhVyy4XoRBRciw+YaG3vyn6hM=
+			1Zr6IHz0DVKoehzBggWv99qlrZ5SWYkYxt7cVypGIH4=
 			</data>
 		</dict>
 		<key>Headers/SDL_version.h</key>
@@ -706,11 +706,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			uQu/n7fxrWWekVzFRLxJgncZHTA=
+			OGZ8BfEEkHiQnTtIvNq9aYEj7FY=
 			</data>
 			<key>hash2</key>
 			<data>
-			DSeMgtt/ULGqpA7hISV4OMHyIDRvvY5Cr6a8loDxcVY=
+			juogOjtV5ZeXFCoHo69XFA1QWPNDN4r0MdblxepalE8=
 			</data>
 		</dict>
 		<key>Headers/SDL_video.h</key>
@@ -717,11 +717,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			oDSfm7hvyakVAn3MJ/vPYpDiTi8=
+			YH5SyVC9XgoGpFkq3vCcdbQd0uI=
 			</data>
 			<key>hash2</key>
 			<data>
-			4kgMp+1L702uCbe5U3mPNYx/zonCSDmAoqKxZGMWlC0=
+			Z5MS/bT5DfdUhSXGNao0cZWNyObx6ruc+zTPuGbg1s4=
 			</data>
 		</dict>
 		<key>Headers/SDL_vulkan.h</key>
@@ -739,11 +739,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			BXr58UQDjOvu3YEpLqbL6MzdnEw=
+			I6nkG0qY9s2AvaEtVSrocQiX4tQ=
 			</data>
 			<key>hash2</key>
 			<data>
-			lZjnBGKuQiSupwtm3kZTliIMMPlHVmUsVTRtQ7E0WMU=
+			8uTiBDsf/cQ5+5utD1yCakQ8kX788aZUQFgKId33VjA=
 			</data>
 		</dict>
 		<key>Headers/close_code.h</key>
@@ -750,11 +750,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			b9BWGnHVTllZJNggBlv8S0bczLA=
+			U4gdDidHLAHPBhe/aWRbzA1M9BQ=
 			</data>
 			<key>hash2</key>
 			<data>
-			/x8Gxc1GaIoziXOz/sebI7d0PytDiEWi8kWZfjkp0Ww=
+			ZczKDtPfhp/KAaAzO6wpeeU4I1z0Pn+FiHTmWV14GlM=
 			</data>
 		</dict>
 		<key>Resources/CMake/sdl2-config-version.cmake</key>
@@ -772,11 +772,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			s2hXhDxzy/ilC+gLamGy/Kq13jo=
+			HFjU0snuPDDpVpeJJsOGAfWEqrU=
 			</data>
 			<key>hash2</key>
 			<data>
-			DuTUW8idzRp7WT1FT5x/m1C1SbVH0FKvKRKOgVlRVhU=
+			3CcBgLSrIjtN3CnKminQz7NzcDt2kcMM2AW/PSX3/0Q=
 			</data>
 		</dict>
 		<key>Resources/Info.plist</key>
@@ -783,11 +783,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			E/exzjLmO25/xe18BS765cbGzWY=
+			ZHmmRK90boQu0lf8kuoupR5C534=
 			</data>
 			<key>hash2</key>
 			<data>
-			lMA4Mg67jCQrkxVHL0vBdN74dU3iomW7AggH3QYKJ44=
+			B6t0lho1afDvcrYh3u2JI7SM9qV8RRd+48xEAIyinO8=
 			</data>
 		</dict>
 		<key>Resources/License.txt</key>
@@ -794,11 +794,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			fCUUBjJ4JuUAC8MRSCszNcY21v8=
+			A8VTYHTg+gsOssUp337xdGbdHW0=
 			</data>
 			<key>hash2</key>
 			<data>
-			d+3CuMuNTuvjYs+HODz44b3nsOHwwJqlcyQOq7qhAPc=
+			UN4cvaEc5FbrLcR2jBIsS5miYCucbhF1iAKC2EMtJhM=
 			</data>
 		</dict>
 		<key>Resources/ReadMe.txt</key>
@@ -816,11 +816,11 @@
 		<dict>
 			<key>hash</key>
 			<data>
-			07w7GQmm31+NEK8ne4mSo7m70Do=
+			QwX80pzFcZED9JtaD8IhQ/uayn0=
 			</data>
 			<key>hash2</key>
 			<data>
-			vmrmeHQ4l7Q4flA5dILQw27M4T0Sc70MQIfP+lFY/do=
+			81kjRE2J1UCGqrIQCmKYXixkYjbOC68/+l4AoNBo6C8=
 			</data>
 		</dict>
 	</dict>
--- a/src/ft2_about.c
+++ b/src/ft2_about.c
@@ -2,19 +2,18 @@
 #include <math.h>
 #include "ft2_header.h"
 #include "ft2_gui.h"
-#include "ft2_pattern_ed.h"
 #include "ft2_bmp.h"
 #include "ft2_video.h"
 #include "ft2_structs.h"
+#include "ft2_pattern_ed.h" // exitPatternEditorExtended()
 
-#define NUM_STARS 3000
-#define ALPHA_FADE_MILLISECS 2000 /* amount of milliseconds until content is fully faded in */
+#define NUM_STARS 2000
+#define ABOUT_SCREEN_X 3
+#define ABOUT_SCREEN_Y 3
 #define ABOUT_SCREEN_W 626
 #define ABOUT_SCREEN_H 167
 #define ABOUT_LOGO_W 449
 #define ABOUT_LOGO_H 110
-#define ABOUT_TEXT_W 349
-#define ABOUT_TEXT_H 29
 
 typedef struct
 {
@@ -30,7 +29,7 @@
 static char *customText2 = "https://16-bits.org";
 static char customText3[256];
 static int16_t customText1Y, customText2Y, customText3Y, customText1X, customText2X, customText3X;
-static uint32_t logoTimer, alphaValue, randSeed, frameCounter;
+static uint32_t randSeed;
 static vector_t starPoints[NUM_STARS], rotation;
 static matrix_t matrix;
 
@@ -48,19 +47,19 @@
 
 static void rotateMatrix(void)
 {
-#define MY_PI_FLOAT 3.141592653589793f
+#define MY_2PI_FLOAT 6.2831853071796f
 
-	const float xx = rotation.x * MY_PI_FLOAT;
-	const float sa = sinf(xx);
-	const float ca = cosf(xx);
+	const float x2pi = rotation.x * MY_2PI_FLOAT;
+	const float sa = sinf(x2pi);
+	const float ca = cosf(x2pi);
 
-	const float yy = rotation.y * MY_PI_FLOAT;
-	const float sb = sinf(yy);
-	const float cb = cosf(yy);
+	const float y2pi = rotation.y * MY_2PI_FLOAT;
+	const float sb = sinf(y2pi);
+	const float cb = cosf(y2pi);
 
-	const float zz = rotation.z * MY_PI_FLOAT;
-	const float sc = sinf(zz);
-	const float cc = cosf(zz);
+	const float z2pi = rotation.z * MY_2PI_FLOAT;
+	const float sc = sinf(z2pi);
+	const float cc = cosf(z2pi);
 
 	// x
 	matrix.x.x = (ca * cc) + (sc * sa * sb);
@@ -78,7 +77,7 @@
 	matrix.z.z = cb * cc;
 }
 
-static void aboutInit(void)
+void initAboutScreen(void)
 {
 	vector_t *s = starPoints;
 	for (int32_t i = 0; i < NUM_STARS; i++, s++)
@@ -87,26 +86,21 @@
 		s->y = (float)(random32() * (1.0 / (UINT32_MAX+1.0)));
 		s->z = (float)(random32() * (1.0 / (UINT32_MAX+1.0)));
 	}
-
-	rotation.x = rotation.y = rotation.z = 0.0f;
-	alphaValue = 0;
-	frameCounter = 0;
-	logoTimer = 0;
 }
 
-static void blendPixel(int32_t x, int32_t y, int32_t r, int32_t g, int32_t b, int32_t alpha)
+static void blendPixel(int32_t x, int32_t y, uint32_t r, uint32_t g, uint32_t b, uint16_t alpha)
 {
 	uint32_t *p = &video.frameBuffer[(y * SCREEN_W) + x];
 
 	const uint32_t srcPixel = *p;
 
-	const int32_t srcR = RGB32_R(srcPixel);
-	const int32_t srcG = RGB32_G(srcPixel);
-	const int32_t srcB = RGB32_B(srcPixel);
+	const uint32_t srcR = RGB32_R(srcPixel);
+	const uint32_t srcG = RGB32_G(srcPixel);
+	const uint32_t srcB = RGB32_B(srcPixel);
 
-	r = ((srcR * (65536-alpha)) + (r * alpha)) >> 16;
-	g = ((srcG * (65536-alpha)) + (g * alpha)) >> 16;
-	b = ((srcB * (65536-alpha)) + (b * alpha)) >> 16;
+	r = ((srcR * (alpha ^ 65535)) + (r * alpha)) >> 16;
+	g = ((srcG * (alpha ^ 65535)) + (g * alpha)) >> 16;
+	b = ((srcB * (alpha ^ 65535)) + (b * alpha)) >> 16;
 
 	*p = RGB32(r, g, b);
 }
@@ -116,7 +110,7 @@
 	vector_t *star = starPoints;
 	for (int16_t i = 0; i < NUM_STARS; i++, star++)
 	{
-		star->z += 0.00015f;
+		star->z += 0.0001f;
 		if (star->z >= 0.5f)
 			star->z -= 1.0f;
 
@@ -124,18 +118,17 @@
 		if (z <= 0.0f)
 			continue;
 
-		float y = (ABOUT_SCREEN_H/2.0f) + ((((matrix.x.y * star->x) + (matrix.y.y * star->y) + (matrix.z.y * star->z)) / z) * 400.0f);
-		const int32_t outY = (int32_t)y;
-		if (outY < 3 || outY >= 3+ABOUT_SCREEN_H)
+		float y = (((matrix.x.y * star->x) + (matrix.y.y * star->y) + (matrix.z.y * star->z)) / z) * 400.0f;
+		const int32_t outY = (ABOUT_SCREEN_Y+(ABOUT_SCREEN_H/2)) + (int32_t)y;
+		if (outY < ABOUT_SCREEN_Y || outY >= ABOUT_SCREEN_Y+ABOUT_SCREEN_H)
 			continue;
 
-		float x = (ABOUT_SCREEN_W/2.0f) + ((((matrix.x.x * star->x) + (matrix.y.x * star->y) + (matrix.z.x * star->z)) / z) * 400.0f);
-
-		const int32_t outX = (int32_t)x;
-		if (outX < 3 || outX >= 3+ABOUT_SCREEN_W)
+		float x = (((matrix.x.x * star->x) + (matrix.y.x * star->y) + (matrix.z.x * star->z)) / z) * 400.0f;
+		const int32_t outX = (ABOUT_SCREEN_X+(ABOUT_SCREEN_W/2)) + (int32_t)x;
+		if (outX < ABOUT_SCREEN_X || outX >= ABOUT_SCREEN_X+ABOUT_SCREEN_W)
 			continue;
 
-		int32_t d = (int32_t)(z * 255.0f);
+		int32_t d = (int32_t)(z * 256.0f);
 		if (d > 255)
 			d = 255;
 		d ^= 255;
@@ -156,18 +149,18 @@
 
 		// blend sides of star
 
-		const int32_t sidesAlpha = 13000;
+		const uint16_t sidesAlpha = 13000;
 
-		if (outX-1 >= 3)
+		if (outX-1 >= ABOUT_SCREEN_X)
 			blendPixel(outX-1, outY, r, g, b, sidesAlpha);
 
-		if (outX+1 < 3+ABOUT_SCREEN_W)
+		if (outX+1 < ABOUT_SCREEN_X+ABOUT_SCREEN_W)
 			blendPixel(outX+1, outY, r, g, b, sidesAlpha);
 
-		if (outY-1 >= 3)
+		if (outY-1 >= ABOUT_SCREEN_Y)
 			blendPixel(outX, outY-1, r, g, b, sidesAlpha);
 
-		if (outY+1 < 3+ABOUT_SCREEN_H)
+		if (outY+1 < ABOUT_SCREEN_Y+ABOUT_SCREEN_H)
 			blendPixel(outX, outY+1, r, g, b, sidesAlpha);
 
 		// plot main star pixel
@@ -175,34 +168,23 @@
 	}
 }
 
-void aboutFrame(void) // called every frame when the about screen is shown
+void renderAboutScreenFrame(void)
 {
-	clearRect(3, 3, ABOUT_SCREEN_W, ABOUT_SCREEN_H);
+	// remember the good old days when you couldn't do this per frame?
+	clearRect(ABOUT_SCREEN_X, ABOUT_SCREEN_Y, ABOUT_SCREEN_W, ABOUT_SCREEN_H);
 
 	// 3D starfield
 	rotateMatrix();
+	rotation.x -= 0.00006f;
+	rotation.z += 0.00003f;
 	starfield();
-	rotation.x -= 0.00011f;
-	rotation.z += 0.00006f;
 
 	// logo + text
-	blit32Alpha(91, 31, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H, alphaValue);
-	textOutAlpha(customText1X, customText1Y, PAL_FORGRND, customText1, alphaValue);
-	textOutAlpha(customText2X, customText2Y, PAL_FORGRND, customText2, alphaValue);
-	textOutAlpha(customText3X, customText3Y, PAL_FORGRND, customText3, alphaValue);
+	blit32(91, 31, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H);
+	textOut(customText1X, customText1Y, PAL_FORGRND, customText1);
+	textOut(customText2X, customText2Y, PAL_FORGRND, customText2);
+	textOut(customText3X, customText3Y, PAL_FORGRND, customText3);
 
-	if (logoTimer > (int32_t)(VBLANK_HZ/4.0))
-	{
-		alphaValue += (uint32_t)((65536.0 / (ALPHA_FADE_MILLISECS / (1000.0 / VBLANK_HZ))) + 0.5);
-		if (alphaValue > 65536)
-			alphaValue = 65536;
-	}
-	else
-	{
-		logoTimer++;
-	}
-
-	// the exit button has to be redrawn since it gets overwritten :)
 	showPushButton(PB_EXIT_ABOUT);
 }
 
@@ -226,7 +208,6 @@
 	customText2Y = 157-12;
 	customText3Y = 157;
 
-	aboutInit();
 	ui.aboutScreenShown = true;
 }
 
--- a/src/ft2_about.h
+++ b/src/ft2_about.h
@@ -3,7 +3,8 @@
 
 #include <stdint.h>
 
-void aboutFrame(void);
+void initAboutScreen(void);
+void renderAboutScreenFrame(void);
 void seedAboutScreenRandom(uint32_t newseed);
 void showAboutScreen(void);
 void hideAboutScreen(void);
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -196,6 +196,8 @@
 	lockMixerCallback();
 	audio.interpolationType = interpolationType;
 
+	audio.sincInterpolation = false;
+
 	// set sinc LUT pointers
 	if (config.interpolation == INTERPOLATION_SINC8)
 	{
@@ -202,6 +204,8 @@
 		fKaiserSinc = fKaiserSinc_8;
 		fDownSample1 = fDownSample1_8;
 		fDownSample2 = fDownSample2_8;
+
+		audio.sincInterpolation = true;
 	}
 	else if (config.interpolation == INTERPOLATION_SINC16)
 	{
@@ -208,6 +212,8 @@
 		fKaiserSinc = fKaiserSinc_16;
 		fDownSample1 = fDownSample1_16;
 		fDownSample2 = fDownSample2_16;
+
+		audio.sincInterpolation = true;
 	}
 
 	unlockMixerCallback();
@@ -388,14 +394,13 @@
 				const double dHz = dPeriod2Hz(ch->finalPeriod);
 
 				// set voice delta
-				const uintCPUWord_t delta = v->oldDelta = (intCPUWord_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
+				const uint64_t delta = v->oldDelta = (int64_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
 
-				if (audio.interpolationType == INTERPOLATION_SINC8 || audio.interpolationType == INTERPOLATION_SINC16)
+				if (audio.sincInterpolation) // decide which sinc LUT to use according to the resampling ratio
 				{
-					// decide which sinc LUT to use according to the resampling ratio
-					if (delta <= (uintCPUWord_t)(1.1875 * MIXER_FRAC_SCALE))
+					if (delta <= sincDownsample1Ratio)
 						v->fSincLUT = fKaiserSinc;
-					else if (delta <= (uintCPUWord_t)(1.5 * MIXER_FRAC_SCALE))
+					else if (delta <= sincDownsample2Ratio)
 						v->fSincLUT = fDownSample1;
 					else
 						v->fSincLUT = fDownSample2;
@@ -403,7 +408,7 @@
 
 				// set scope delta
 				const double dHz2ScopeDeltaMul = SCOPE_FRAC_SCALE / (double)SCOPE_HZ;
-				v->scopeDelta = (intCPUWord_t)((dHz * dHz2ScopeDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
+				v->scopeDelta = (int64_t)((dHz * dHz2ScopeDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
 			}
 
 			v->delta = v->oldDelta;
@@ -980,11 +985,7 @@
 		return false;
 	}
 
-#if CPU_64BIT
 	if (have.freq != 44100 && have.freq != 48000 && have.freq != 96000)
-#else // 32-bit CPUs only support .16fp resampling precision. Not sensible with high rates.
-	if (have.freq != 44100 && have.freq != 48000)
-#endif
 	{
 		if (showErrorMsg)
 			showErrorMsgBox("Couldn't open audio device:\nThis program doesn't support an audio output rate of %dHz. Sorry!", have.freq);
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -5,7 +5,6 @@
 #include <stdbool.h>
 #include <SDL2/SDL.h>
 #include "ft2_replayer.h"
-#include "ft2_cpu.h"
 
 enum
 {
@@ -16,12 +15,7 @@
 #define DEFAULT_AUDIO_FREQ 48000
 
 #define MIN_AUDIO_FREQ 44100
-
-#if CPU_64BIT
 #define MAX_AUDIO_FREQ 96000
-#else
-#define MAX_AUDIO_FREQ 48000
-#endif
 
 #define MAX_AUDIO_DEVICES 99
 
@@ -43,7 +37,7 @@
 	char *currInputDevice, *currOutputDevice, *lastWorkingAudioDeviceName;
 	char *inputDeviceNames[MAX_AUDIO_DEVICES], *outputDeviceNames[MAX_AUDIO_DEVICES];
 	volatile bool locked, resetSyncTickTimeFlag, volumeRampingFlag;
-	bool linearPeriodsFlag, rescanAudioDevicesSupported;
+	bool linearPeriodsFlag, rescanAudioDevicesSupported, sincInterpolation;
 	volatile uint8_t interpolationType;
 	int32_t inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;
 	uint32_t quickVolRampSamples, freq;
@@ -71,8 +65,7 @@
 	uint8_t mixFuncOffset, panning, loopType, scopeVolume;
 	int32_t position, sampleEnd, loopStart, loopLength, oldPeriod;
 	uint32_t volumeRampLength;
-
-	uintCPUWord_t positionFrac, delta, oldDelta, scopeDelta;
+	uint64_t positionFrac, delta, oldDelta, scopeDelta;
 
 	// if (loopEnabled && hasLooped && samplingPos <= loopStart+MAX_LEFT_TAPS) readFixedTapsFromThisPointer();
 	const int8_t *leftEdgeTaps8;
--- a/src/ft2_config.c
+++ b/src/ft2_config.c
@@ -32,7 +32,6 @@
 #include "ft2_tables.h"
 #include "ft2_bmp.h"
 #include "ft2_structs.h"
-#include "ft2_cpu.h"
 
 config_t config; // globalized
 
@@ -155,11 +154,7 @@
 		config.recQuantRes = 16;
 	}
 
-#if CPU_64BIT
 	if (config.audioFreq != 44100 && config.audioFreq != 48000 && config.audioFreq != 96000)
-#else
-	if (config.audioFreq != 44100 && config.audioFreq != 48000)
-#endif
 		config.audioFreq = DEFAULT_AUDIO_FREQ;
 
 	if (config.audioInputFreq <= 1) // default value from FT2 (this was cdr_Sync) - set defaults
@@ -848,9 +843,7 @@
 	{
 		         case 44100:  tmpID = RB_CONFIG_AUDIO_44KHZ;  break;
 		default: case 48000:  tmpID = RB_CONFIG_AUDIO_48KHZ;  break;
-#if CPU_64BIT
 		         case 96000:  tmpID = RB_CONFIG_AUDIO_96KHZ;  break;
-#endif
 	}
 	radioButtons[tmpID].state = RADIOBUTTON_CHECKED;
 
@@ -1180,9 +1173,8 @@
 			textOutShadow(509,   3, PAL_FORGRND, PAL_DSKTOP2, "Audio output rate:");
 			textOutShadow(525,  17, PAL_FORGRND, PAL_DSKTOP2, "44100Hz");
 			textOutShadow(525,  31, PAL_FORGRND, PAL_DSKTOP2, "48000Hz");
-#if CPU_64BIT
 			textOutShadow(525,  45, PAL_FORGRND, PAL_DSKTOP2, "96000Hz");
-#endif
+
 			textOutShadow(509,  61, PAL_FORGRND, PAL_DSKTOP2, "Frequency slides:");
 			textOutShadow(525,  75, PAL_FORGRND, PAL_DSKTOP2, "Amiga");
 			textOutShadow(525,  89, PAL_FORGRND, PAL_DSKTOP2, "Linear (default)");
@@ -1661,13 +1653,11 @@
 	setNewAudioSettings();
 }
 
-#if CPU_64BIT
 void rbConfigAudio96kHz(void)
 {
 	config.audioFreq = 96000;
 	setNewAudioSettings();
 }
-#endif
 
 void rbConfigAudioInput44kHz(void)
 {
--- a/src/ft2_config.h
+++ b/src/ft2_config.h
@@ -5,7 +5,6 @@
 #include <stdbool.h>
 #include "ft2_replayer.h"
 #include "ft2_palette.h"
-#include "ft2_cpu.h"
 
 #define CFG_ID_STR "FastTracker 2.0 configuration file\x1A"
 #define CONFIG_FILE_SIZE 1736
@@ -226,9 +225,7 @@
 void rbConfigAudioIntrp16PointSinc(void);
 void rbConfigAudio44kHz(void);
 void rbConfigAudio48kHz(void);
-#if CPU_64BIT
 void rbConfigAudio96kHz(void);
-#endif
 void rbConfigAudioInput44kHz(void);
 void rbConfigAudioInput48kHz(void);
 void rbConfigAudioInput96kHz(void);
--- a/src/ft2_events.c
+++ b/src/ft2_events.c
@@ -503,11 +503,20 @@
 		else if (event.type == SDL_MOUSEBUTTONUP)
 		{
 			mouseButtonUpHandler(event.button.button);
+#if defined __APPLE__ && defined __aarch64__
+			armMacGhostMouseCursorFix();
+#endif
 		}
 		else if (event.type == SDL_MOUSEBUTTONDOWN)
 		{
 			mouseButtonDownHandler(event.button.button);
 		}
+#if defined __APPLE__ && defined __aarch64__
+		else if (event.type == SDL_MOUSEMOTION)
+		{
+			armMacGhostMouseCursorFix();
+		}
+#endif
 
 		if (editor.throwExit)
 			editor.programRunning = false;
--- a/src/ft2_gui.c
+++ b/src/ft2_gui.c
@@ -370,52 +370,6 @@
 	}
 }
 
-void charOutAlpha(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, uint32_t alpha)
-{
-	assert(xPos < SCREEN_W && yPos < SCREEN_H);
-
-	chr &= 0x7F; // this is important to get the nordic glyphs in the font
-	if (chr == ' ')
-		return;
-
-	if (alpha > 65536)
-		alpha = 65536;
-
-	const uint32_t pixVal = video.palette[paletteIndex];
-	const uint32_t palNum = paletteIndex << 24;
-	const uint8_t *srcPtr = &bmp.font1[chr * FONT1_CHAR_W];
-	uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
-
-	for (int32_t y = 0; y < FONT1_CHAR_H; y++)
-	{
-		for (int32_t x = 0; x < FONT1_CHAR_W; x++)
-		{
-			const uint32_t srcPixel = srcPtr[x];
-			if (srcPixel == 0)
-				continue;
-
-			const uint32_t dstPixel = dstPtr[x];
-
-			const int32_t srcR = RGB32_R(pixVal);
-			const int32_t srcG = RGB32_G(pixVal);
-			const int32_t srcB = RGB32_B(pixVal);
-
-			int32_t dstR = RGB32_R(dstPixel);
-			int32_t dstG = RGB32_G(dstPixel);
-			int32_t dstB = RGB32_B(dstPixel);
-
-			dstR = ((dstR * (65536-alpha)) + (srcR * alpha)) >> 16;
-			dstG = ((dstG * (65536-alpha)) + (srcG * alpha)) >> 16;
-			dstB = ((dstB * (65536-alpha)) + (srcB * alpha)) >> 16;
-
-			dstPtr[x] = RGB32(dstR, dstG, dstB) | palNum;
-		}
-
-		srcPtr += FONT1_WIDTH;
-		dstPtr += SCREEN_W;
-	}
-}
-
 void charOutBg(uint16_t xPos, uint16_t yPos, uint8_t fgPalette, uint8_t bgPalette, char chr)
 {
 	assert(xPos < SCREEN_W && yPos < SCREEN_H);
@@ -585,31 +539,6 @@
 	}
 }
 
-void textOutAlpha(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr, uint32_t alpha)
-{
-	char chr;
-	uint16_t currX;
-
-	assert(textPtr != NULL);
-
-	if (alpha >= 65536)
-	{
-		textOut(x, y, paletteIndex, textPtr);
-		return;
-	}
-
-	currX = x;
-	while (true)
-	{
-		chr = *textPtr++;
-		if (chr == '\0')
-			break;
-
-		charOutAlpha(currX, y, paletteIndex, chr, alpha);
-		currX += charWidth(chr);
-	}
-}
-
 void textOutBorder(uint16_t x, uint16_t y, uint8_t paletteIndex, uint8_t borderPaletteIndex, const char *textPtr)
 {
 	textOut(x,   y-1, borderPaletteIndex, textPtr); // top
@@ -805,47 +734,6 @@
 		{
 			if (srcPtr[x] != 0x00FF00)
 				dstPtr[x] = srcPtr[x] | 0xFF000000; // most significant 8 bits = palette number. 0xFF because no true palette
-		}
-
-		srcPtr += w;
-		dstPtr += SCREEN_W;
-	}
-}
-
-void blit32Alpha(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h, uint32_t alpha)
-{
-	assert(srcPtr != NULL && xPos < SCREEN_W && yPos < SCREEN_H && (xPos + w) <= SCREEN_W && (yPos + h) <= SCREEN_H);
-
-	if (alpha >= 65536)
-	{
-		blit32(xPos, yPos, srcPtr, w, h);
-		return;
-	}
-
-	uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
-	for (int32_t y = 0; y < h; y++)
-	{
-		for (int32_t x = 0; x < w; x++)
-		{
-			const uint32_t srcPixel = srcPtr[x];
-			if (srcPixel == 0x00FF00)
-				continue;
-
-			const uint32_t dstPixel = dstPtr[x];
-
-			const int32_t srcR = RGB32_R(srcPixel);
-			const int32_t srcG = RGB32_G(srcPixel);
-			const int32_t srcB = RGB32_B(srcPixel);
-
-			int32_t dstR = RGB32_R(dstPixel);
-			int32_t dstG = RGB32_G(dstPixel);
-			int32_t dstB = RGB32_B(dstPixel);
-
-			dstR = ((dstR * (65536-alpha)) + (srcR * alpha)) >> 16;
-			dstG = ((dstG * (65536-alpha)) + (srcG * alpha)) >> 16;
-			dstB = ((dstB * (65536-alpha)) + (srcB * alpha)) >> 16;
-
-			dstPtr[x] = RGB32(dstR, dstG, dstB) | 0xFF000000; // most significant 8 bits = palette number. 0xFF because no true palette
 		}
 
 		srcPtr += w;
--- a/src/ft2_gui.h
+++ b/src/ft2_gui.h
@@ -81,7 +81,6 @@
 void fillRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h, uint8_t paletteIndex);
 void drawFramework(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t type);
 void blit32(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h);
-void blit32Alpha(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h, uint32_t alpha);
 void blit(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h);
 void blitClipX(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h, uint16_t clipX);
 void blitFast(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h); // no transparency/colorkey
@@ -92,7 +91,6 @@
 void textOutTiny(int32_t xPos, int32_t yPos, char *str, uint32_t color); // A..Z/a..z and 0..9
 void textOutTinyOutline(int32_t xPos, int32_t yPos, char *str); // A..Z/a..z and 0..9
 void charOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr);
-void charOutAlpha(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, uint32_t alpha);
 void charOutBg(uint16_t xPos, uint16_t yPos, uint8_t fgPalette, uint8_t bgPalette, char chr);
 void charOutShadow(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, uint8_t shadowPaletteIndex, char chr);
 void charOutClipX(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, uint16_t clipX);
@@ -100,7 +98,6 @@
 void charOutShadow(uint16_t x, uint16_t y, uint8_t paletteIndex, uint8_t shadowPaletteIndex, char chr);
 void charOutOutlined(uint16_t x, uint16_t y, uint8_t paletteIndex, char chr);
 void textOut(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr);
-void textOutAlpha(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr, uint32_t alpha);
 void textOutBorder(uint16_t x, uint16_t y, uint8_t paletteIndex, uint8_t borderPaletteIndex, const char *textPtr);
 void textOutFixed(uint16_t x, uint16_t y, uint8_t fgPaltete, uint8_t bgPalette, const char *textPtr);
 void bigTextOut(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr);
--- a/src/ft2_header.h
+++ b/src/ft2_header.h
@@ -13,7 +13,7 @@
 #endif
 #include "ft2_replayer.h"
 
-#define PROG_VER_STR "1.76"
+#define PROG_VER_STR "1.79"
 
 // do NOT change these! It will only mess things up...
 
--- a/src/ft2_inst_ed.c
+++ b/src/ft2_inst_ed.c
@@ -2912,11 +2912,12 @@
 {
 	xiHdr_t ih;
 	sample_t *s;
+	FILE *f = NULL;
 
 	if (editor.tmpFilenameU == NULL)
 	{
 		okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL);
-		return false;
+		goto saveError;
 	}
 
 	const int32_t numSamples = getUsedSamples(saveInstrNum);
@@ -2923,14 +2924,14 @@
 	if (numSamples == 0 || instr[saveInstrNum] == NULL)
 	{
 		okBoxThreadSafe(0, "System message", "Instrument is empty!", NULL);
-		return false;
+		goto saveError;
 	}
 
-	FILE *f = UNICHAR_FOPEN(editor.tmpFilenameU, "wb");
+	f = UNICHAR_FOPEN(editor.tmpFilenameU, "wb");
 	if (f == NULL)
 	{
 		okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL);
-		return false;
+		goto saveError;
 	}
 
 	memset(&ih, 0, sizeof (ih)); // important, also clears reserved stuff
@@ -3025,9 +3026,8 @@
 	size_t result = fwrite(&ih, INSTR_XI_HEADER_SIZE + (ih.numSamples * sizeof (xmSmpHdr_t)), 1, f);
 	if (result != 1)
 	{
-		fclose(f);
 		okBoxThreadSafe(0, "System message", "Error saving instrument: general I/O error!", NULL);
-		return false;
+		goto saveError;
 	}
 
 	pauseAudio();
@@ -3047,9 +3047,8 @@
 			if (result != (size_t)SAMPLE_LENGTH_BYTES(s)) // write not OK
 			{
 				resumeAudio();
-				fclose(f);
 				okBoxThreadSafe(0, "System message", "Error saving instrument: general I/O error!", NULL);
-				return false;
+				goto saveError;
 			}
 		}
 	}
@@ -3062,6 +3061,15 @@
 
 	return true;
 
+saveError:
+	if (f != NULL)
+		fclose(f);
+
+	editor.diskOpReadDir = true; // force diskop re-read
+	setMouseBusy(false);
+
+	return false;
+
 	(void)ptr;
 }
 
@@ -3102,21 +3110,22 @@
 	xmSmpHdr_t *src;
 	sample_t *s;
 	instr_t *ins;
-
+	FILE *f = NULL;
 	bool stereoWarning = false;
+
 	numLoadedSamples = 0;
 
 	if (editor.tmpInstrFilenameU == NULL)
 	{
 		okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL);
-		return false;
+		goto loadDone;
 	}
 
-	FILE *f = UNICHAR_FOPEN(editor.tmpInstrFilenameU, "rb");
+	f = UNICHAR_FOPEN(editor.tmpInstrFilenameU, "rb");
 	if (f == NULL)
 	{
 		okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL);
-		return false;
+		goto loadDone;
 	}
 
 	memset(&xi_h, 0, sizeof (xi_h));
@@ -3435,32 +3444,36 @@
 	}
 
 loadDone:
-	fclose(f);
+	if (f != NULL)
+		fclose(f);
 
-	numLoadedSamples = CLAMP(numLoadedSamples, 1, MAX_SMP_PER_INST);
-
-	ins = instr[editor.curInstr];
-	if (ins != NULL)
+	if (numLoadedSamples > 0)
 	{
-		sanitizeInstrument(ins);
-		for (i = 0; i < numLoadedSamples; i++)
+		numLoadedSamples = CLAMP(numLoadedSamples, 1, MAX_SMP_PER_INST);
+
+		ins = instr[editor.curInstr];
+		if (ins != NULL)
 		{
-			s = &ins->smp[i];
-			sanitizeSample(s);
+			sanitizeInstrument(ins);
+			for (i = 0; i < numLoadedSamples; i++)
+			{
+				s = &ins->smp[i];
+				sanitizeSample(s);
 
-			if (s->dataPtr != NULL)
-				fixSample(s);
+				if (s->dataPtr != NULL)
+					fixSample(s);
+			}
+
+			fixInstrAndSampleNames(editor.curInstr);
 		}
+		editor.updateCurInstr = true; // setMouseBusy(false) is called in the input/video thread when done
 
-		fixInstrAndSampleNames(editor.curInstr);
-	}
-	editor.updateCurInstr = true; // setMouseBusy(false) is called in the input/video thread when done
+		if (numLoadedSamples > MAX_SMP_PER_INST)
+			okBoxThreadSafe(0, "System message", "Warning: The instrument contained >16 samples. The extra samples were discarded!", NULL);
 
-	if (numLoadedSamples > MAX_SMP_PER_INST)
-		okBoxThreadSafe(0, "System message", "Warning: The instrument contained >16 samples. The extra samples were discarded!", NULL);
-
-	if (stereoWarning)
-		okBoxThreadSafe(0, "System message", "Warning: The instrument contained stereo sample(s). They were mixed to mono!", NULL);
+		if (stereoWarning)
+			okBoxThreadSafe(0, "System message", "Warning: The instrument contained stereo sample(s). They were mixed to mono!", NULL);
+	}
 
 	return true;
 	(void)ptr;
--- a/src/ft2_keyboard.c
+++ b/src/ft2_keyboard.c
@@ -723,11 +723,6 @@
 			if (keyb.leftAltPressed)
 			{
 				toggleFullscreen();
-
-				// prevent fullscreen toggle from firing twice on certain SDL2 Linux ports
-#ifdef __unix__
-				SDL_Delay(100);
-#endif
 				return true;
 			}
 		}
--- a/src/ft2_main.c
+++ b/src/ft2_main.c
@@ -136,6 +136,7 @@
 		showErrorMsgBox("Couldn't initialize SDL:\n%s", SDL_GetError());
 		return 1;
 	}
+
 	SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
 
 	/* Text input is started by default in SDL2, turn it off to remove ~2ms spikes per key press.
@@ -214,6 +215,7 @@
 		return 1;
 	}
 
+	initAboutScreen();
 	pauseAudio();
 	resumeAudio();
 	rescanAudioDevices();
--- a/src/ft2_module_loader.c
+++ b/src/ft2_module_loader.c
@@ -26,6 +26,9 @@
 #include "ft2_structs.h"
 #include "ft2_sysreqs.h"
 
+bool detectBEM(FILE* f);
+bool loadBEM(FILE* f, uint32_t filesize);
+
 bool loadDIGI(FILE *f, uint32_t filesize);
 bool loadMOD(FILE *f, uint32_t filesize);
 bool loadS3M(FILE *f, uint32_t filesize);
@@ -41,7 +44,8 @@
 	FORMAT_MOD = 3,
 	FORMAT_S3M = 4,
 	FORMAT_STM = 5,
-	FORMAT_DIGI = 6
+	FORMAT_DIGI = 6,
+	FORMAT_BEM = 7
 };
 
 // file extensions accepted by Disk Op. in module mode
@@ -48,7 +52,7 @@
 char *supportedModExtensions[] =
 {
 	"xm", "ft", "nst", "stk", "mod", "s3m", "stm", "fst",
-	"digi",
+	"digi", "bem",
 
 	// IMPORTANT: Remember comma after last entry above
 	"END_OF_LIST" // do NOT move, remove or edit this line!
@@ -84,6 +88,10 @@
 	fread(I, 1, 4, f);
 	rewind(f);
 
+	// BEM ("UN05", from XM only, MikMod)
+	if (detectBEM(f))
+		return FORMAT_BEM;
+
 	// DIGI Booster (non-Pro)
 	if (!memcmp("DIGI Booster module", &D[0x00], 19+1) && D[0x19] >= 1 && D[0x19] <= 8)
 		return FORMAT_DIGI;
@@ -193,6 +201,7 @@
 		case FORMAT_MOD: moduleLoaded = loadMOD(f, filesize); break;
 		case FORMAT_POSSIBLY_STK: moduleLoaded = loadSTK(f, filesize); break;
 		case FORMAT_DIGI: moduleLoaded = loadDIGI(f, filesize); break;
+		case FORMAT_BEM: moduleLoaded = loadBEM(f, filesize); break;
 
 		default:
 			loaderMsgBox("This file is not a supported module!");
--- a/src/ft2_mouse.c
+++ b/src/ft2_mouse.c
@@ -31,6 +31,21 @@
 static int32_t mouseModeGfxOffs, mouseBusyGfxFrame;
 static SDL_Cursor *cursors[NUM_CURSORS];
 
+#if defined __APPLE__ && defined __aarch64__
+void armMacGhostMouseCursorFix(void)
+{
+	/* M E G A K L U D G E:
+	** The mouse cursor can sometimes change back to OS stock
+	** (or show both stock and custom mouse) on Macs with a notch
+	** (ARM based) in fullscreen mode. Weird, right?!
+	**
+	** XXX: Can this cause stuttering or performance issues?
+	*/
+	if (video.fullscreen)
+		SDL_SetCursor(NULL); // forces redraw
+}
+#endif
+
 static bool setSystemCursor(SDL_Cursor *cur)
 {
 	if (config.specialFlags2 & USE_OS_MOUSE_POINTER)
@@ -78,7 +93,7 @@
 
 	for (int32_t i = 0; i < NUM_CURSORS; i++)
 	{
-		int32_t scaleFactor = video.yScale;
+		int32_t scaleFactor = video.mouseCursorUpscaleFactor;
 		if (scaleFactor > 8) // just in case
 			scaleFactor = 8;
 
@@ -158,8 +173,8 @@
 
 		if (i == 3) // text edit cursor bias
 		{
-			hotX = 2 * video.xScale;
-			hotY = 6 * video.yScale;
+			hotX = 2 * video.mouseCursorUpscaleFactor;
+			hotY = 6 * video.mouseCursorUpscaleFactor;
 		}
 
 		cursors[i] = SDL_CreateColorCursor(surface, hotX, hotY);
@@ -821,8 +836,8 @@
 
 void updateMouseScaling(void)
 {
-	if (video.renderW > 0.0) video.fMouseXMul = (float)SCREEN_W / video.renderW;
-	if (video.renderH > 0.0) video.fMouseYMul = (float)SCREEN_H / video.renderH;
+	if (video.renderW > 0) video.dMouseXMul = (double)SCREEN_W / video.renderW;
+	if (video.renderH > 0) video.dMouseYMul = (double)SCREEN_H / video.renderH;
 }
 
 void readMouseXY(void)
@@ -838,8 +853,15 @@
 		return;
 	}
 
-	if (video.useDesktopMouseCoords)
+	if (video.fullscreen)
 	{
+		mouse.buttonState = SDL_GetMouseState(&mx, &my);
+
+		mouse.absX = mx;
+		mouse.absY = my;
+	}
+	else
+	{
 		mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my);
 
 		mouse.absX = mx;
@@ -851,63 +873,55 @@
 		mx -= windowX;
 		my -= windowY;
 	}
-	else
-	{
-		// special mode for KMSDRM (XXX: Confirm that this still works...)
-		mouse.buttonState = SDL_GetMouseState(&mx, &my);
 
-		mouse.absX = mx;
-		mouse.absY = my;
-	}
-
 	mouse.rawX = mx;
 	mouse.rawY = my;
 
 	if (video.fullscreen)
 	{
-		// centered fullscreen mode (not stretched) needs further coord translation
-		if (!(config.specialFlags2 & STRETCH_IMAGE))
+		// if software mouse is enabled, warp mouse inside render space
+		if (!(config.specialFlags2 & HARDWARE_MOUSE))
 		{
-			// if software mouse is enabled, warp mouse inside render space
-			if (!(config.specialFlags2 & HARDWARE_MOUSE))
+			bool warpMouse = false;
+
+			if (mx < video.renderX)
 			{
-				bool warpMouse = false;
+				mx = video.renderX;
+				warpMouse = true;
+			}
+			else if (mx >= video.renderX+video.renderW)
+			{
+				mx = (video.renderX + video.renderW) - 1;
+				warpMouse = true;
+			}
 
-				if (mx < video.renderX)
-				{
-					mx = video.renderX;
-					warpMouse = true;
-				}
-				else if (mx >= video.renderX+video.renderW)
-				{
-					mx = (video.renderX + video.renderW) - 1;
-					warpMouse = true;
-				}
-
-				if (my < video.renderY)
-				{
-					my = video.renderY;
-					warpMouse = true;
-				}
-				else if (my >= video.renderY+video.renderH)
-				{
-					my = (video.renderY + video.renderH) - 1;
-					warpMouse = true;
-				}
-
-				if (warpMouse)
-					SDL_WarpMouseInWindow(video.window, mx, my);
+			if (my < video.renderY)
+			{
+				my = video.renderY;
+				warpMouse = true;
 			}
+			else if (my >= video.renderY+video.renderH)
+			{
+				my = (video.renderY + video.renderH) - 1;
+				warpMouse = true;
+			}
 
-			// convert fullscreen coords to window (centered image) coords
-			mx -= video.renderX;
-			my -= video.renderY;
+			if (warpMouse)
+				SDL_WarpMouseInWindow(video.window, mx, my);
 		}
+
+		// convert fullscreen coords to window (centered image) coords
+		mx -= video.renderX;
+		my -= video.renderY;
 	}
 
-	// multiply coords by video upscaling factors (don't round)
-	mouse.x = (int32_t)(mx * video.fMouseXMul);
-	mouse.y = (int32_t)(my * video.fMouseYMul);
+	// kludge: this can happen and prevent buttons from pressing on the very first row of pixels
+	if (mx == -1) mx = 0;
+	if (my == -1) my = 0;
+
+	// multiply coords by video upscaling factors
+	mouse.x = (int32_t)floor(mx * video.dMouseXMul);
+	mouse.y = (int32_t)floor(my * video.dMouseYMul);
 
 	if (config.specialFlags2 & HARDWARE_MOUSE)
 	{
--- a/src/ft2_mouse.h
+++ b/src/ft2_mouse.h
@@ -34,6 +34,10 @@
 #define MOUSE_GLASS_ANI_FRAMES 22
 #define MOUSE_CLOCK_ANI_FRAMES 5
 
+#if defined __APPLE__ && defined __aarch64__
+void armMacGhostMouseCursorFix(void);
+#endif
+
 void freeMouseCursors(void);
 bool createMouseCursors(void);
 void setMousePosToCenter(void);
--- a/src/ft2_radiobuttons.c
+++ b/src/ft2_radiobuttons.c
@@ -96,9 +96,7 @@
 	//x,   y,  w,  group,                      funcOnUp
 	{ 509, 16, 66, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio44kHz },
 	{ 509, 30, 66, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio48kHz },
-#if CPU_64BIT
 	{ 509, 44, 66, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio96kHz },
-#endif
 
 	// audio input frequency
 	//x,   y,   w,  group,                            funcOnUp
--- a/src/ft2_radiobuttons.h
+++ b/src/ft2_radiobuttons.h
@@ -3,7 +3,6 @@
 
 #include <stdint.h>
 #include <stdbool.h>
-#include "ft2_cpu.h"
 
 enum // RADIOBUTTONS
 {
@@ -66,9 +65,7 @@
 	// AUDIO FREQUENCY
 	RB_CONFIG_AUDIO_44KHZ,
 	RB_CONFIG_AUDIO_48KHZ,
-#if CPU_64BIT
 	RB_CONFIG_AUDIO_96KHZ,
-#endif
 
 	// AUDIO INPUT FREQUENCY
 	RB_CONFIG_AUDIO_INPUT_44KHZ,
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -6,8 +6,6 @@
 #include "ft2_unicode.h"
 #include "mixer/ft2_cubic_spline.h"
 #include "mixer/ft2_windowed_sinc.h"
-#include "ft2_cpu.h"
-
 enum
 {
 	// voice flags
@@ -199,7 +197,7 @@
 	uint8_t status, pianoNoteNum, smpNum, instrNum;
 	int32_t smpStartPos;
 	uint8_t scopeVolume;
-	uintCPUWord_t scopeDelta;
+	uint64_t scopeDelta;
 }
 #ifdef __GNUC__
 __attribute__ ((packed))
@@ -219,9 +217,9 @@
 	int32_t length, loopStart, loopLength;
 
 	// fix for resampling interpolation taps
-	int8_t leftEdgeTapSamples8[32];
-	int16_t leftEdgeTapSamples16[32];
-	int16_t fixedSmp[32];
+	int8_t leftEdgeTapSamples8[MAX_TAPS*2];
+	int16_t leftEdgeTapSamples16[MAX_TAPS*2];
+	int16_t fixedSmp[MAX_TAPS*2];
 	int32_t fixedPos;
 } sample_t;
 
--- a/src/ft2_sample_loader.c
+++ b/src/ft2_sample_loader.c
@@ -86,7 +86,7 @@
 	if (editor.tmpFilenameU == NULL)
 	{
 		loaderMsgBox("General I/O error during loading!");
-		return false;
+		goto loadError;
 	}
 
 	FILE *f = UNICHAR_FOPEN(editor.tmpFilenameU, "rb");
@@ -93,7 +93,7 @@
 	if (f == NULL)
 	{
 		loaderMsgBox("General I/O error during loading! Is the file in use?");
-		return false;
+		goto loadError;
 	}
 
 	int8_t format = detectSample(f);
@@ -104,7 +104,7 @@
 	{
 		fclose(f);
 		loaderMsgBox("Error loading sample: The file is empty!");
-		return false;
+		goto loadError;
 	}
 
 	bool sampleLoaded = false;
@@ -232,7 +232,7 @@
 
 	if (editor.curInstr == 0)
 	{
-		loaderMsgBox("The zero-instrument cannot hold intrument data.");
+		loaderMsgBox("The zero-instrument cannot hold instrument data!");
 		return false;
 	}
 
--- a/src/ft2_sample_saver.c
+++ b/src/ft2_sample_saver.c
@@ -82,7 +82,6 @@
 
 		if (samplesToWrite < 0 || samplesToWrite > MAX_RIGHT_TAPS || sampleFixPos < 0 || sampleFixOffset < 0 || sampleFixOffset >= MAX_RIGHT_TAPS)
 			return;
-
 	}
 
 	FILE* f = UNICHAR_FOPEN(filenameU, "r+"); // open in read+update mode
--- a/src/ft2_sysreqs.c
+++ b/src/ft2_sysreqs.c
@@ -164,6 +164,10 @@
 
 static bool mouseButtonUpLogic(uint8_t mouseButton)
 {
+#if defined __APPLE__ && defined __aarch64__
+	armMacGhostMouseCursorFix();
+#endif
+
 	if (mouseButton == SDL_BUTTON_LEFT)
 		mouse.leftButtonPressed = false;
 	else if (mouseButton == SDL_BUTTON_RIGHT)
@@ -334,7 +338,12 @@
 					if (testCheckBoxMouseDown()) continue;
 				}
 			}
-
+#if defined __APPLE__ && defined __aarch64__
+			else if (inputEvent.type == SDL_MOUSEMOTION)
+			{
+				armMacGhostMouseCursorFix();
+			}
+#endif
 			if (!ui.sysReqShown)
 				break;
 		}
@@ -572,7 +581,12 @@
 					if (testPushButtonMouseDown()) continue;
 				}
 			}
-
+#if defined __APPLE__ && defined __aarch64__
+			else if (inputEvent.type == SDL_MOUSEMOTION)
+			{
+				armMacGhostMouseCursorFix();
+			}
+#endif
 			if (!ui.sysReqShown)
 				break;
 		}
--- a/src/ft2_video.c
+++ b/src/ft2_video.c
@@ -34,7 +34,6 @@
 #include "ft2_midi.h"
 #include "ft2_bmp.h"
 #include "ft2_structs.h"
-#include "ft2_cpu.h"
 
 static const uint8_t textCursorData[12] =
 {
@@ -127,8 +126,8 @@
 	             "Audio latency: %.1fms (expected %.1fms)\n" \
 	             "Render size: %dx%d (offset %d,%d)\n" \
 	             "Disp. size: %dx%d (window: %dx%d)\n" \
-	             "Render scaling: x=%.2f, y=%.2f\n" \
-	             "Mouse to render space muls: x=%.2f, y=%.2f\n" \
+	             "Render scaling: x=%.4f, y=%.4f\n" \
+	             "Mouse pixel-space muls: x=%.4f, y=%.4f\n" \
 	             "Relative mouse coords: %d,%d\n" \
 	             "Absolute mouse coords: %d,%d\n" \
 	             "Press CTRL+SHIFT+F to close this box.\n",
@@ -142,8 +141,8 @@
 	             dAudLatency, ((audio.wantSamples * 1000.0) / audio.wantFreq),
 	             video.renderW, video.renderH, video.renderX, video.renderY,
 	             video.displayW, video.displayH, video.windowW, video.windowH,
-	             video.renderW / (float)SCREEN_W, video.renderH / (float)SCREEN_H,
-	             video.fMouseXMul, video.fMouseYMul,
+	             (double)video.renderW / SCREEN_W, (double)video.renderH / SCREEN_H,
+	             video.dMouseXMul, video.dMouseYMul,
 	             mouse.x, mouse.y,
 	             mouse.absX, mouse.absY);
 
@@ -207,7 +206,11 @@
 	if (!minimized)
 		SDL_RenderClear(video.renderer);
 
-	SDL_RenderCopy(video.renderer, video.texture, NULL, NULL);
+	if (video.useCustomRenderRect)
+		SDL_RenderCopy(video.renderer, video.texture, NULL, &video.renderRect);
+	else
+		SDL_RenderCopy(video.renderer, video.texture, NULL, NULL);
+
 	SDL_RenderPresent(video.renderer);
 
 	eraseSprites();
@@ -266,75 +269,63 @@
 
 static void updateRenderSizeVars(void)
 {
-	float fXScale, fYScale;
+	SDL_DisplayMode dm;
 
-	if (video.useDesktopMouseCoords)
-	{
-		SDL_DisplayMode dm;
-		int32_t di = SDL_GetWindowDisplayIndex(video.window);
-		if (di < 0)
-			di = 0; // return display index 0 (default) on error
+	int32_t di = SDL_GetWindowDisplayIndex(video.window);
+	if (di < 0)
+		di = 0; // return display index 0 (default) on error
 
-		SDL_GetDesktopDisplayMode(di, &dm);
-		video.displayW = dm.w;
-		video.displayH = dm.h;
-	}
-	else
-	{
-		SDL_GetWindowSize(video.window, &video.displayW, &video.displayH);
-	}
+	SDL_GetDesktopDisplayMode(di, &dm);
+	video.displayW = dm.w;
+	video.displayH = dm.h;
 
 	SDL_GetWindowSize(video.window, &video.windowW, &video.windowH);
+	video.renderX = 0;
+	video.renderY = 0;
 
+	video.useCustomRenderRect = false;
+
 	if (video.fullscreen)
 	{
 		if (config.specialFlags2 & STRETCH_IMAGE)
 		{
-			video.renderW = video.displayW;
-			video.renderH = video.displayH;
-			video.renderX = 0;
-			video.renderY = 0;
+			// "streched out" windowed fullscreen
+
+			video.renderW = video.windowW;
+			video.renderH = video.windowH;
 		}
 		else
 		{
-			SDL_RenderGetScale(video.renderer, &fXScale, &fYScale);
+			// centered windowed fullscreen, with pixel-perfect integer upscaling
 
-			video.renderW = (int32_t)(SCREEN_W * fXScale);
-			video.renderH = (int32_t)(SCREEN_H * fYScale);
+			const int32_t maxUpscaleFactor = MIN(video.windowW / SCREEN_W, video.windowH / SCREEN_H);
+			video.renderW = SCREEN_W * maxUpscaleFactor;
+			video.renderH = SCREEN_H * maxUpscaleFactor;
+			video.renderX = (video.windowW - video.renderW) / 2;
+			video.renderY = (video.windowH - video.renderH) / 2;
 
-			// high-DPI hackery:
-			//  On high-DPI systems, the display w/h are given in logical pixels,
-			//  but the renderer size is given in physical pixels. Since our internal
-			//  render{X,Y,W,H} variables need to be in logical coordinates, as that's
-			//  what mouse input uses, scale them by the screen's DPI scale factor,
-			//  which is the physical (renderer) size / the logical (window) size.
-			//  On non high-DPI systems, this is effectively a no-op.
-			int32_t actualScreenW, actualScreenH;
-			SDL_GetRendererOutputSize(video.renderer, &actualScreenW, &actualScreenH);
+			// get hi-DPI upscale factors (returns 1.0 if no hi-DPI upscaling)
+			int32_t widthInPixels, heightInPixels;
+			SDL_GL_GetDrawableSize(video.window, &widthInPixels, &heightInPixels);
+			double dHiDPIScaleX = (double)widthInPixels / video.windowW;
+			double dHiDPIScaleY = (double)heightInPixels / video.windowH;
 
-			const double dXUpscale = (const double)actualScreenW / video.displayW;
-			const double dYUpscale = (const double)actualScreenH / video.displayH;
-
-			// downscale back to correct sizes
-			if (dXUpscale != 0.0) video.renderW = (int32_t)(video.renderW / dXUpscale);
-			if (dYUpscale != 0.0) video.renderH = (int32_t)(video.renderH / dYUpscale);
-
-			video.renderX = (video.displayW - video.renderW) / 2;
-			video.renderY = (video.displayH - video.renderH) / 2;
+			video.renderRect.x = (int32_t)floor(video.renderX * dHiDPIScaleX);
+			video.renderRect.y = (int32_t)floor(video.renderY * dHiDPIScaleY);
+			video.renderRect.w = (int32_t)floor(video.renderW * dHiDPIScaleX);
+			video.renderRect.h = (int32_t)floor(video.renderH * dHiDPIScaleY);
+			video.useCustomRenderRect = true; // use the destination coordinates above in SDL_RenderCopy()
 		}
 	}
 	else
 	{
-		SDL_GetWindowSize(video.window, &video.renderW, &video.renderH);
+		// windowed mode
 
-		video.renderX = 0;
-		video.renderY = 0;
+		SDL_GetWindowSize(video.window, &video.renderW, &video.renderH);
 	}
 
-	// for mouse cursor creation
-	video.xScale = (uint32_t)round(video.renderW / (double)SCREEN_W);
-	video.yScale = (uint32_t)round(video.renderH / (double)SCREEN_H);
-
+	// "hardware mouse" calculations
+	video.mouseCursorUpscaleFactor = MIN(video.renderW / SCREEN_W, video.renderH / SCREEN_H);
 	createMouseCursors();
 }
 
@@ -341,30 +332,8 @@
 void enterFullscreen(void)
 {
 	SDL_SetWindowFullscreen(video.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+	SDL_Delay(15); // fixes possible issues
 
-	if (config.specialFlags2 & STRETCH_IMAGE)
-	{
-		SDL_DisplayMode dm;
-
-		int32_t di = SDL_GetWindowDisplayIndex(video.window);
-		if (di < 0)
-			di = 0; // return display index 0 (default) on error
-
-		SDL_GetDesktopDisplayMode(di, &dm);
-
-		SDL_RenderSetLogicalSize(video.renderer, dm.w, dm.h);
-	}
-	else
-	{
-		SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H);
-	}
-
-	SDL_SetWindowSize(video.window, SCREEN_W, SCREEN_H);
-
-#ifndef __unix__ // can be severely buggy on Linux... (at least when used like this)
-	SDL_SetWindowGrab(video.window, SDL_TRUE);
-#endif
-
 	updateRenderSizeVars();
 	updateMouseScaling();
 	setMousePosToCenter();
@@ -373,16 +342,11 @@
 void leaveFullscreen(void)
 {
 	SDL_SetWindowFullscreen(video.window, 0);
-	SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H);
+	SDL_Delay(15); // fixes possible issues
 
-	setWindowSizeFromConfig(false);
+	setWindowSizeFromConfig(false); // false = do not change actual window size, only update variables
+	SDL_SetWindowSize(video.window, SCREEN_W * video.windowModeUpscaleFactor, SCREEN_H * video.windowModeUpscaleFactor);
 
-	SDL_SetWindowSize(video.window, SCREEN_W * video.upscaleFactor, SCREEN_H * video.upscaleFactor);
-
-#ifndef __unix__
-	SDL_SetWindowGrab(video.window, SDL_FALSE);
-#endif
-
 	updateRenderSizeVars();
 	updateMouseScaling();
 	setMousePosToCenter();
@@ -820,7 +784,7 @@
 	uint8_t i;
 	SDL_DisplayMode dm;
 
-	uint8_t oldUpscaleFactor = video.upscaleFactor;
+	uint8_t oldUpscaleFactor = video.windowModeUpscaleFactor;
 	if (config.windowFlags & WINSIZE_AUTO)
 	{
 		int32_t di = SDL_GetWindowDisplayIndex(video.window);
@@ -835,30 +799,30 @@
 				// height test is slightly taller because of window title, window borders and taskbar/menu/dock
 				if (dm.w >= SCREEN_W*i && dm.h >= (SCREEN_H+64)*i)
 				{
-					video.upscaleFactor = i;
+					video.windowModeUpscaleFactor = i;
 					break;
 				}
 			}
 
 			if (i == 0)
-				video.upscaleFactor = 1; // 1x is not going to fit, but use 1x anyways...
+				video.windowModeUpscaleFactor = 1; // 1x is not going to fit, but use 1x anyways...
 		}
 		else
 		{
 			// couldn't get screen resolution, set to 1x
-			video.upscaleFactor = 1;
+			video.windowModeUpscaleFactor = 1;
 		}
 	}
-	else if (config.windowFlags & WINSIZE_1X) video.upscaleFactor = 1;
-	else if (config.windowFlags & WINSIZE_2X) video.upscaleFactor = 2;
-	else if (config.windowFlags & WINSIZE_3X) video.upscaleFactor = 3;
-	else if (config.windowFlags & WINSIZE_4X) video.upscaleFactor = 4;
+	else if (config.windowFlags & WINSIZE_1X) video.windowModeUpscaleFactor = 1;
+	else if (config.windowFlags & WINSIZE_2X) video.windowModeUpscaleFactor = 2;
+	else if (config.windowFlags & WINSIZE_3X) video.windowModeUpscaleFactor = 3;
+	else if (config.windowFlags & WINSIZE_4X) video.windowModeUpscaleFactor = 4;
 
 	if (updateRenderer)
 	{
-		SDL_SetWindowSize(video.window, SCREEN_W * video.upscaleFactor, SCREEN_H * video.upscaleFactor);
+		SDL_SetWindowSize(video.window, SCREEN_W * video.windowModeUpscaleFactor, SCREEN_H * video.windowModeUpscaleFactor);
 
-		if (oldUpscaleFactor != video.upscaleFactor)
+		if (oldUpscaleFactor != video.windowModeUpscaleFactor)
 			SDL_SetWindowPosition(video.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
 
 		updateRenderSizeVars();
@@ -879,31 +843,17 @@
 		strncpy(songTitleTrunc, songTitle, sizeof (songTitleTrunc)-1);
 		songTitleTrunc[sizeof (songTitleTrunc)-1] = '\0';
 
-#if CPU_BITS==32
 			if (song.isModified)
-				sprintf(wndTitle, "Fasttracker II clone v%s (32-bit) - \"%s\" (unsaved)", PROG_VER_STR, songTitleTrunc);
-			else
-				sprintf(wndTitle, "Fasttracker II clone v%s (32-bit) - \"%s\"", PROG_VER_STR, songTitleTrunc);
-#else
-			if (song.isModified)
 				sprintf(wndTitle, "Fasttracker II clone v%s - \"%s\" (unsaved)", PROG_VER_STR, songTitleTrunc);
 			else
 				sprintf(wndTitle, "Fasttracker II clone v%s - \"%s\"", PROG_VER_STR, songTitleTrunc);
-#endif
 	}
 	else
 	{
-#if CPU_BITS==32
 		if (song.isModified)
-			sprintf(wndTitle, "Fasttracker II clone v%s (32-bit) - \"untitled\" (unsaved)", PROG_VER_STR);
-		else
-			sprintf(wndTitle, "Fasttracker II clone v%s (32-bit) - \"untitled\"", PROG_VER_STR);
-#else
-		if (song.isModified)
 			sprintf(wndTitle, "Fasttracker II clone v%s - \"untitled\" (unsaved)", PROG_VER_STR);
 		else
 			sprintf(wndTitle, "Fasttracker II clone v%s - \"untitled\"", PROG_VER_STR);
-#endif
 	}
 
 	SDL_SetWindowTitle(video.window, wndTitle);
@@ -961,7 +911,7 @@
 		video.vsync60HzPresent = false;
 
 	video.window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
-		SCREEN_W * video.upscaleFactor, SCREEN_H * video.upscaleFactor,
+		SCREEN_W * video.windowModeUpscaleFactor, SCREEN_H * video.windowModeUpscaleFactor,
 		windowFlags);
 
 	if (video.window == NULL)
@@ -1005,12 +955,6 @@
 		}
 	}
 
-	SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H);
-
-#if SDL_MINOR_VERSION >= 24 || (SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL >= 5)
-	SDL_RenderSetIntegerScale(video.renderer, SDL_TRUE);
-#endif
-
 	SDL_SetRenderDrawBlendMode(video.renderer, SDL_BLENDMODE_NONE);
 
 	if (!recreateTexture())
@@ -1021,7 +965,7 @@
 	}
 
 	// framebuffer used by SDL (for texture)
-	video.frameBuffer = (uint32_t *)malloc(SCREEN_W * SCREEN_H * sizeof (int32_t));
+	video.frameBuffer = (uint32_t *)malloc(SCREEN_W * SCREEN_H * sizeof (uint32_t));
 	if (video.frameBuffer == NULL)
 	{
 		showErrorMsgBox("Not enough memory!");
@@ -1031,12 +975,6 @@
 	if (!setupSprites())
 		return false;
 
-	// Workaround: SDL_GetGlobalMouseState() doesn't work with KMSDRM/Wayland
-	video.useDesktopMouseCoords = true;
-	const char *videoDriver = SDL_GetCurrentVideoDriver();
-	if (videoDriver != NULL && (strcmp("KMSDRM", videoDriver) == 0 || strcmp("wayland", videoDriver) == 0))
-		video.useDesktopMouseCoords = false;
-
 	updateRenderSizeVars();
 	updateMouseScaling();
 
@@ -1055,7 +993,7 @@
 	{
 		if (ui.aboutScreenShown)
 		{
-			aboutFrame();
+			renderAboutScreenFrame();
 		}
 		else if (ui.nibblesShown)
 		{
--- a/src/ft2_video.h
+++ b/src/ft2_video.h
@@ -20,19 +20,17 @@
 
 typedef struct video_t
 {
-	bool fullscreen, showFPSCounter, useDesktopMouseCoords;
-	uint32_t xScale, yScale;
-	uint32_t *frameBuffer, palette[PAL_NUM];
+	bool fullscreen, showFPSCounter, useCustomRenderRect, vsync60HzPresent, windowHidden;
+	uint8_t windowModeUpscaleFactor;
+	int32_t renderX, renderY, renderW, renderH, displayW, displayH, windowW, windowH;
+	uint32_t mouseCursorUpscaleFactor, *frameBuffer, palette[PAL_NUM];
+	double dMonitorRefreshRate, dMouseXMul, dMouseYMul;
 #ifdef _WIN32
 	HWND hWnd;
 #endif
 	hpc_t vblankHpc;
 	SDL_Window *window;
-	double dMonitorRefreshRate;
-	float fMouseXMul, fMouseYMul;
-	uint8_t upscaleFactor;
-	bool vsync60HzPresent, windowHidden;
-	int32_t renderX, renderY, renderW, renderH, displayW, displayH, windowW, windowH;
+	SDL_Rect renderRect;
 	SDL_Renderer *renderer;
 	SDL_Texture *texture;
 	SDL_Surface *iconSurface;
--- a/src/ft2_wav_renderer.c
+++ b/src/ft2_wav_renderer.c
@@ -484,11 +484,10 @@
 	if (WDFrequency < MAX_WAV_RENDER_FREQ)
 	{
 		     if (WDFrequency ==  44100) WDFrequency = 48000;
-#if CPU_64BIT
 		else if (WDFrequency ==  48000) WDFrequency = 96000;
 		else if (WDFrequency ==  96000) WDFrequency = 192000;
 		else if (WDFrequency == 192000) WDFrequency = 384000;
-#endif
+
 		updateWavRenderer();
 	}
 }
@@ -497,14 +496,11 @@
 {
 	if (WDFrequency > MIN_WAV_RENDER_FREQ)
 	{
-#if CPU_64BIT
 		     if (WDFrequency == 384000) WDFrequency = 192000;
 		else if (WDFrequency == 192000) WDFrequency = 96000;
 		else if (WDFrequency ==  96000) WDFrequency = 48000;
 		else if (WDFrequency ==  48000) WDFrequency = 44100;
-#else
-		if (WDFrequency == 48000) WDFrequency = 44100;
-#endif
+
 		updateWavRenderer();
 	}
 }
--- a/src/ft2_wav_renderer.h
+++ b/src/ft2_wav_renderer.h
@@ -3,15 +3,9 @@
 
 #include <stdint.h>
 #include "ft2_header.h"
-#include "ft2_cpu.h"
 
 #define MIN_WAV_RENDER_FREQ 44100
-
-#if CPU_64BIT
 #define MAX_WAV_RENDER_FREQ 384000
-#else
-#define MAX_WAV_RENDER_FREQ 48000
-#endif
 
 void cbToggleWavRenderBPMMode(void);
 void setWavRenderFrequency(int32_t freq);
--- a/src/helpdata/FT2.HLP
+++ b/src/helpdata/FT2.HLP
@@ -804,7 +804,11 @@
 >@X060@C002
 Selects what type of resampling interpolation to use.
 If you want to have an authentic FT2 sound, select "linear".
-Sinc will give the best interpolation, but it may sound too filtered on lo-fi samples.
+If you want a good trade-off between quality and muddiness for more lo-fi samples,
+select "Cubic spline".
+However, if you mainly use hi-fi samples (or play XMs with hi-fi samples), then pick
+any of the two sinc options for the most clear sound. Keep in mind that these will
+make XMs with lo-fi samples sound very muddy, though! 
 Tip: Play around with the different options...
 
 >@X040@C001Volume ramping:
@@ -848,8 +852,8 @@
 
 >@X040@C001Stretched:
 >@X060@C002
-Makes fullscreen mode completely stretch out the image. This can result in
-aliasing (uneven pixel widths) if the aspect ratio of the screen is not 16:10.
+Makes fullscreen mode completely stretch out the image.
+This can and will result in uneven pixel sizes, making the image look quite bad.
 The "Pixel filter" setting can help with this, but it makes the image look blurry.
  
 >@X040@C001Pixel filter:
@@ -937,8 +941,8 @@
 >
 >@X010@C001Video:
 >@C002
->@X010- Fullscreen mode can be unbearably slow on a Raspberry Pi (even on RPi 4)
+>@X010- Fullscreen mode can have issues with the mouse pixel mapping on some
+>@X021Linux systems.
 >@X010- Fullscreen mode can have several problems on multi-monitor systems
->@X010- Fullscreen mode can have several problems on some Linux systems
 
 END
--- a/src/helpdata/ft2_help_data.h
+++ b/src/helpdata/ft2_help_data.h
@@ -3,9 +3,9 @@
 
 #include <stdint.h>
 
-#define HELP_DATA_LEN 27755
+#define HELP_DATA_LEN 27925
 
-const uint8_t helpData[27755] =
+const uint8_t helpData[27925] =
 {
 	0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
@@ -1848,478 +1848,493 @@
 	0x6E,0x20,0x61,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x20,
 	0x46,0x54,0x32,0x20,0x73,0x6F,0x75,0x6E,0x64,0x2C,0x20,0x73,
 	0x65,0x6C,0x65,0x63,0x74,0x20,0x22,0x6C,0x69,0x6E,0x65,0x61,
-	0x72,0x22,0x2E,0x56,0x53,0x69,0x6E,0x63,0x20,0x77,0x69,0x6C,
-	0x6C,0x20,0x67,0x69,0x76,0x65,0x20,0x74,0x68,0x65,0x20,0x62,
-	0x65,0x73,0x74,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C,
-	0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x62,0x75,0x74,0x20,0x69,
-	0x74,0x20,0x6D,0x61,0x79,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,
-	0x74,0x6F,0x6F,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x65,0x64,
-	0x20,0x6F,0x6E,0x20,0x6C,0x6F,0x2D,0x66,0x69,0x20,0x73,0x61,
-	0x6D,0x70,0x6C,0x65,0x73,0x2E,0x2E,0x54,0x69,0x70,0x3A,0x20,
-	0x50,0x6C,0x61,0x79,0x20,0x61,0x72,0x6F,0x75,0x6E,0x64,0x20,
-	0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x66,
-	0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x6F,0x70,0x74,0x69,0x6F,
-	0x6E,0x73,0x2E,0x2E,0x2E,0x00,0x1A,0x3E,0x40,0x58,0x30,0x34,
-	0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x6F,0x6C,0x75,0x6D,0x65,
-	0x20,0x72,0x61,0x6D,0x70,0x69,0x6E,0x67,0x3A,0x0B,0x3E,0x40,
-	0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3B,0x45,0x6E,
-	0x61,0x62,0x6C,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x61,0x6E,
-	0x74,0x69,0x2D,0x63,0x6C,0x69,0x63,0x6B,0x20,0x73,0x79,0x73,
-	0x74,0x65,0x6D,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x61,
-	0x75,0x64,0x69,0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,0x20,0x28,
-	0x46,0x54,0x32,0x2E,0x30,0x38,0x2B,0x29,0x2E,0x3B,0x50,0x6C,
-	0x65,0x61,0x73,0x65,0x20,0x6E,0x6F,0x74,0x65,0x20,0x74,0x68,
-	0x61,0x74,0x20,0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x20,
-	0x46,0x54,0x32,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6C,0x6F,
-	0x61,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x6F,0x6E,0x66,
-	0x69,0x67,0x20,0x65,0x6E,0x74,0x72,0x79,0x2C,0x0B,0x63,0x6C,
-	0x6F,0x6E,0x65,0x20,0x6F,0x6E,0x6C,0x79,0x2E,0x00,0x19,0x3E,
-	0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x41,0x6D,
-	0x70,0x6C,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x3A,
-	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
-	0x46,0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x65,0x73,0x20,0x74,
-	0x68,0x65,0x20,0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x77,0x68,
-	0x65,0x6E,0x20,0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,0x20,0x49,
-	0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x65,0x74,0x20,0x74,0x68,
-	0x69,0x73,0x20,0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,0x20,0x68,
-	0x69,0x67,0x68,0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,0x6C,0x3A,
-	0x67,0x65,0x74,0x20,0x64,0x69,0x73,0x74,0x6F,0x72,0x74,0x69,
-	0x6F,0x6E,0x2E,0x20,0x33,0x32,0x58,0x20,0x65,0x71,0x75,0x61,
-	0x6C,0x73,0x20,0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,0x70,0x6C,
-	0x69,0x74,0x75,0x64,0x65,0x20,0x66,0x6F,0x72,0x20,0x6F,0x6E,
-	0x65,0x20,0x63,0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,0x00,0x1C,
-	0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x46,
-	0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x73,0x6C,0x69,
-	0x64,0x65,0x73,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,
-	0x43,0x30,0x30,0x32,0x39,0x4C,0x69,0x6E,0x65,0x61,0x72,0x20,
-	0x6D,0x6F,0x64,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,0x61,
-	0x6C,0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x73,0x6C,0x69,
-	0x64,0x65,0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x63,
-	0x6F,0x6E,0x73,0x74,0x61,0x6E,0x74,0x20,0x73,0x70,0x65,0x65,
-	0x64,0x2C,0x38,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,0x64,0x65,
-	0x6E,0x74,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x75,
-	0x72,0x72,0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,0x75,0x65,
-	0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,
-	0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,0x73,0x40,
-	0x6F,0x6E,0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,0x66,0x69,
-	0x6E,0x69,0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,0x67,0x2C,
-	0x20,0x69,0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,0x73,0x6F,
-	0x75,0x6E,0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,0x65,0x20,
-	0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x6E,0x67,0x20,
-	0x75,0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,0x6D,0x65,
-	0x6E,0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,0x30,0x32,
-	0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,
-	0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,0x61,0x79,
-	0x6F,0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,0x30,0x34,
-	0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,0x65,0x72,
-	0x6E,0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,0x68,0x65,
-	0x78,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,0x67,0x3A,
-	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
-	0x41,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,0x65,0x20,
-	0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,0x68,0x61,
-	0x74,0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,0x65,0x72,
-	0x20,0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,0x69,0x6E,
-	0x65,0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,0x6F,0x75,
-	0x6C,0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,0x20,0x63,
-	0x6F,0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,0x6E,0x63,
-	0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,
-	0x6F,0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,0x69,0x74,
-	0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,0x69,0x6E,
-	0x65,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,0x6F,0x6C,
-	0x75,0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,0x34,0x30,
-	0x40,0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,0x73,0x3A,
-	0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
-	0x43,0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,0x74,0x61,
-	0x6E,0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,0x6C,0x20,
-	0x73,0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,
-	0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x20,0x61,
-	0x73,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,0x6C,0x69,
-	0x6B,0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x3D,0x22,0x4C,0x69,
-	0x6E,0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,0x64,0x72,
-	0x61,0x77,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C,0x61,
-	0x74,0x65,0x64,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x73,0x20,
-	0x28,0x6C,0x69,0x6E,0x65,0x61,0x72,0x20,0x69,0x6E,0x74,0x65,
-	0x72,0x70,0x6F,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x2E,0x00,0x27,
-	0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,
-	0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,
-	0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,
-	0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,0x58,0x30,0x34,0x30,
-	0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F,
-	0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,
-	0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,0x73,0x20,0x74,0x68,
-	0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x74,0x6F,
-	0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,0x20,0x56,0x53,0x79,
-	0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,0x69,0x64,0x65,0x6F,
-	0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,
-	0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,0x72,0x65,0x66,0x72,
-	0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20,
-	0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x28,0x6F,0x72,
-	0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,0x74,0x68,0x65,0x6E,
-	0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,0x73,0x20,0x61,0x6C,
-	0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,0x20,0x66,0x6F,0x72,
-	0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,
-	0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,0x61,0x76,0x69,0x6E,
-	0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C,0x6C,
-	0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x20,0x6C,
-	0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,0x74,0x2F,0x76,0x69,
-	0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,0x79,0x2C,0x1E,0x62,
-	0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,0x70,0x6F,0x74,0x65,
-	0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,0x74,0x65,
-	0x72,0x69,0x6E,0x67,0x2E,0x00,0x15,0x3E,0x40,0x58,0x30,0x34,
-	0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x74,0x72,0x65,0x74,0x63,
-	0x68,0x65,0x64,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,
-	0x43,0x30,0x30,0x32,0x4A,0x4D,0x61,0x6B,0x65,0x73,0x20,0x66,
-	0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,
-	0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x6C,
-	0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75,
-	0x74,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x2E,
-	0x20,0x54,0x68,0x69,0x73,0x20,0x63,0x61,0x6E,0x20,0x72,0x65,
-	0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x4E,0x61,0x6C,0x69,0x61,
-	0x73,0x69,0x6E,0x67,0x20,0x28,0x75,0x6E,0x65,0x76,0x65,0x6E,
-	0x20,0x70,0x69,0x78,0x65,0x6C,0x20,0x77,0x69,0x64,0x74,0x68,
-	0x73,0x29,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x61,0x73,
-	0x70,0x65,0x63,0x74,0x20,0x72,0x61,0x74,0x69,0x6F,0x20,0x6F,
-	0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x63,0x72,0x65,0x65,0x6E,
-	0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x31,0x36,0x3A,0x31,
-	0x30,0x2E,0x52,0x54,0x68,0x65,0x20,0x22,0x50,0x69,0x78,0x65,
-	0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x73,0x65,
-	0x74,0x74,0x69,0x6E,0x67,0x20,0x63,0x61,0x6E,0x20,0x68,0x65,
-	0x6C,0x70,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,
-	0x2C,0x20,0x62,0x75,0x74,0x20,0x69,0x74,0x20,0x6D,0x61,0x6B,
-	0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,
-	0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,
-	0x2E,0x01,0x20,0x18,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,
-	0x30,0x30,0x31,0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,
-	0x74,0x65,0x72,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,
-	0x43,0x30,0x30,0x32,0x52,0x41,0x70,0x70,0x6C,0x69,0x65,0x73,
-	0x20,0x61,0x6E,0x20,0x61,0x6E,0x74,0x69,0x2D,0x61,0x6C,0x69,
-	0x61,0x73,0x69,0x6E,0x67,0x20,0x73,0x75,0x62,0x70,0x69,0x78,
-	0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x20,0x74,0x68,
-	0x61,0x74,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x77,
-	0x68,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,0x64,
-	0x6F,0x77,0x20,0x69,0x73,0x20,0x75,0x70,0x73,0x63,0x61,0x6C,
-	0x65,0x64,0x2E,0x3B,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6B,
-	0x65,0x65,0x70,0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20,
-	0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,
-	0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78,0x65,
-	0x6C,0x73,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,
-	0x72,0x79,0x2E,0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40,0x43,
-	0x30,0x30,0x31,0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64,0x20,
-	0x65,0x64,0x69,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,
-	0x6E,0x73,0x3A,0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30,0x34,
-	0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F,0x50,
-	0x61,0x73,0x74,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,
+	0x72,0x22,0x2E,0x52,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x77,
+	0x61,0x6E,0x74,0x20,0x61,0x20,0x67,0x6F,0x6F,0x64,0x20,0x74,
+	0x72,0x61,0x64,0x65,0x2D,0x6F,0x66,0x66,0x20,0x62,0x65,0x74,
+	0x77,0x65,0x65,0x6E,0x20,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,
+	0x20,0x61,0x6E,0x64,0x20,0x6D,0x75,0x64,0x64,0x69,0x6E,0x65,
+	0x73,0x73,0x20,0x66,0x6F,0x72,0x20,0x6D,0x6F,0x72,0x65,0x20,
+	0x6C,0x6F,0x2D,0x66,0x69,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,
+	0x73,0x2C,0x16,0x73,0x65,0x6C,0x65,0x63,0x74,0x20,0x22,0x43,
+	0x75,0x62,0x69,0x63,0x20,0x73,0x70,0x6C,0x69,0x6E,0x65,0x22,
+	0x2E,0x54,0x48,0x6F,0x77,0x65,0x76,0x65,0x72,0x2C,0x20,0x69,
+	0x66,0x20,0x79,0x6F,0x75,0x20,0x6D,0x61,0x69,0x6E,0x6C,0x79,
+	0x20,0x75,0x73,0x65,0x20,0x68,0x69,0x2D,0x66,0x69,0x20,0x73,
+	0x61,0x6D,0x70,0x6C,0x65,0x73,0x20,0x28,0x6F,0x72,0x20,0x70,
+	0x6C,0x61,0x79,0x20,0x58,0x4D,0x73,0x20,0x77,0x69,0x74,0x68,
+	0x20,0x68,0x69,0x2D,0x66,0x69,0x20,0x73,0x61,0x6D,0x70,0x6C,
+	0x65,0x73,0x29,0x2C,0x20,0x74,0x68,0x65,0x6E,0x20,0x70,0x69,
+	0x63,0x6B,0x52,0x61,0x6E,0x79,0x20,0x6F,0x66,0x20,0x74,0x68,
+	0x65,0x20,0x74,0x77,0x6F,0x20,0x73,0x69,0x6E,0x63,0x20,0x6F,
+	0x70,0x74,0x69,0x6F,0x6E,0x73,0x20,0x66,0x6F,0x72,0x20,0x74,
+	0x68,0x65,0x20,0x6D,0x6F,0x73,0x74,0x20,0x63,0x6C,0x65,0x61,
+	0x72,0x20,0x73,0x6F,0x75,0x6E,0x64,0x2E,0x20,0x4B,0x65,0x65,
+	0x70,0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20,0x74,0x68,
+	0x61,0x74,0x20,0x74,0x68,0x65,0x73,0x65,0x20,0x77,0x69,0x6C,
+	0x6C,0x36,0x6D,0x61,0x6B,0x65,0x20,0x58,0x4D,0x73,0x20,0x77,
+	0x69,0x74,0x68,0x20,0x6C,0x6F,0x2D,0x66,0x69,0x20,0x73,0x61,
+	0x6D,0x70,0x6C,0x65,0x73,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,
+	0x76,0x65,0x72,0x79,0x20,0x6D,0x75,0x64,0x64,0x79,0x2C,0x20,
+	0x74,0x68,0x6F,0x75,0x67,0x68,0x21,0x20,0x2E,0x54,0x69,0x70,
+	0x3A,0x20,0x50,0x6C,0x61,0x79,0x20,0x61,0x72,0x6F,0x75,0x6E,
+	0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x65,0x20,0x64,
+	0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x6F,0x70,0x74,
+	0x69,0x6F,0x6E,0x73,0x2E,0x2E,0x2E,0x00,0x1A,0x3E,0x40,0x58,
+	0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x6F,0x6C,0x75,
+	0x6D,0x65,0x20,0x72,0x61,0x6D,0x70,0x69,0x6E,0x67,0x3A,0x0B,
+	0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3B,
+	0x45,0x6E,0x61,0x62,0x6C,0x65,0x73,0x20,0x74,0x68,0x65,0x20,
+	0x61,0x6E,0x74,0x69,0x2D,0x63,0x6C,0x69,0x63,0x6B,0x20,0x73,
+	0x79,0x73,0x74,0x65,0x6D,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,
+	0x20,0x61,0x75,0x64,0x69,0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,
+	0x20,0x28,0x46,0x54,0x32,0x2E,0x30,0x38,0x2B,0x29,0x2E,0x3B,
+	0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6E,0x6F,0x74,0x65,0x20,
+	0x74,0x68,0x61,0x74,0x20,0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,
+	0x6C,0x20,0x46,0x54,0x32,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,
+	0x6C,0x6F,0x61,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x6F,
+	0x6E,0x66,0x69,0x67,0x20,0x65,0x6E,0x74,0x72,0x79,0x2C,0x0B,
+	0x63,0x6C,0x6F,0x6E,0x65,0x20,0x6F,0x6E,0x6C,0x79,0x2E,0x00,
+	0x19,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,
+	0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,
+	0x6E,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,
+	0x30,0x32,0x46,0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x65,0x73,
+	0x20,0x74,0x68,0x65,0x20,0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,
+	0x77,0x68,0x65,0x6E,0x20,0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,
+	0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x65,0x74,0x20,
+	0x74,0x68,0x69,0x73,0x20,0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,
+	0x20,0x68,0x69,0x67,0x68,0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,
+	0x6C,0x3A,0x67,0x65,0x74,0x20,0x64,0x69,0x73,0x74,0x6F,0x72,
+	0x74,0x69,0x6F,0x6E,0x2E,0x20,0x33,0x32,0x58,0x20,0x65,0x71,
+	0x75,0x61,0x6C,0x73,0x20,0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,
+	0x70,0x6C,0x69,0x74,0x75,0x64,0x65,0x20,0x66,0x6F,0x72,0x20,
+	0x6F,0x6E,0x65,0x20,0x63,0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,
+	0x00,0x1C,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,
+	0x31,0x46,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x73,
+	0x6C,0x69,0x64,0x65,0x73,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,
+	0x30,0x40,0x43,0x30,0x30,0x32,0x39,0x4C,0x69,0x6E,0x65,0x61,
+	0x72,0x20,0x6D,0x6F,0x64,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,
+	0x20,0x61,0x6C,0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x73,
+	0x6C,0x69,0x64,0x65,0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,
+	0x20,0x63,0x6F,0x6E,0x73,0x74,0x61,0x6E,0x74,0x20,0x73,0x70,
+	0x65,0x65,0x64,0x2C,0x38,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,
+	0x64,0x65,0x6E,0x74,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,
+	0x63,0x75,0x72,0x72,0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,
+	0x75,0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,
+	0x75,0x20,0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,
+	0x73,0x40,0x6F,0x6E,0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,
+	0x66,0x69,0x6E,0x69,0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,
+	0x67,0x2C,0x20,0x69,0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,
+	0x73,0x6F,0x75,0x6E,0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,
+	0x65,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x6E,
+	0x67,0x20,0x75,0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,
+	0x6D,0x65,0x6E,0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,
+	0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,
+	0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,
+	0x61,0x79,0x6F,0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,
+	0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,
+	0x65,0x72,0x6E,0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,
+	0x68,0x65,0x78,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,
+	0x67,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,
+	0x30,0x32,0x41,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,
+	0x65,0x20,0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,
+	0x68,0x61,0x74,0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,
+	0x65,0x72,0x20,0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,
+	0x69,0x6E,0x65,0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,
+	0x6F,0x75,0x6C,0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,
+	0x20,0x63,0x6F,0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,
+	0x6E,0x63,0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,
+	0x65,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,
+	0x69,0x74,0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,
+	0x69,0x6E,0x65,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,
+	0x6F,0x6C,0x75,0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,
+	0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,
+	0x73,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,
+	0x30,0x32,0x43,0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,
+	0x74,0x61,0x6E,0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,
+	0x6C,0x20,0x73,0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,
+	0x61,0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,
+	0x20,0x61,0x73,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,
+	0x6C,0x69,0x6B,0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x3D,0x22,
+	0x4C,0x69,0x6E,0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,
+	0x64,0x72,0x61,0x77,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,
+	0x6C,0x61,0x74,0x65,0x64,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,
+	0x73,0x20,0x28,0x6C,0x69,0x6E,0x65,0x61,0x72,0x20,0x69,0x6E,
+	0x74,0x65,0x72,0x70,0x6F,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x2E,
+	0x00,0x27,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,
+	0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,
+	0x6E,0x2C,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,
+	0x65,0x6F,0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,0x58,0x30,
+	0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,0x6E,0x63,
+	0x20,0x6F,0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,
+	0x40,0x43,0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,0x73,0x20,
+	0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,
+	0x74,0x6F,0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,0x20,0x56,
+	0x53,0x79,0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,0x69,0x64,
+	0x65,0x6F,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,
+	0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,0x72,0x65,
+	0x66,0x72,0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,
+	0x73,0x20,0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x28,
+	0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,0x74,0x68,
+	0x65,0x6E,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,0x73,0x20,
+	0x61,0x6C,0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,0x20,0x66,
+	0x6F,0x72,0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,
+	0x72,0x61,0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,0x61,0x76,
+	0x69,0x6E,0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,
+	0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,
+	0x20,0x6C,0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,0x74,0x2F,
+	0x76,0x69,0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,0x79,0x2C,
+	0x1E,0x62,0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,0x70,0x6F,
+	0x74,0x65,0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,
+	0x74,0x65,0x72,0x69,0x6E,0x67,0x2E,0x00,0x15,0x3E,0x40,0x58,
+	0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x74,0x72,0x65,
+	0x74,0x63,0x68,0x65,0x64,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,
+	0x30,0x40,0x43,0x30,0x30,0x32,0x37,0x4D,0x61,0x6B,0x65,0x73,
+	0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,
+	0x6D,0x6F,0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,
+	0x65,0x6C,0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,
+	0x6F,0x75,0x74,0x20,0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,
+	0x65,0x2E,0x50,0x54,0x68,0x69,0x73,0x20,0x63,0x61,0x6E,0x20,
+	0x61,0x6E,0x64,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,
+	0x75,0x6C,0x74,0x20,0x69,0x6E,0x20,0x75,0x6E,0x65,0x76,0x65,
+	0x6E,0x20,0x70,0x69,0x78,0x65,0x6C,0x20,0x73,0x69,0x7A,0x65,
+	0x73,0x2C,0x20,0x6D,0x61,0x6B,0x69,0x6E,0x67,0x20,0x74,0x68,
+	0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x20,0x6C,0x6F,0x6F,0x6B,
+	0x20,0x71,0x75,0x69,0x74,0x65,0x20,0x62,0x61,0x64,0x2E,0x52,
+	0x54,0x68,0x65,0x20,0x22,0x50,0x69,0x78,0x65,0x6C,0x20,0x66,
+	0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x73,0x65,0x74,0x74,0x69,
+	0x6E,0x67,0x20,0x63,0x61,0x6E,0x20,0x68,0x65,0x6C,0x70,0x20,
+	0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x2C,0x20,0x62,
+	0x75,0x74,0x20,0x69,0x74,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,
+	0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x20,0x6C,0x6F,
+	0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x2E,0x01,0x20,
+	0x18,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,
+	0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,
 	0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,
-	0x32,0x37,0x54,0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,
-	0x67,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66,0x6F,
-	0x72,0x20,0x63,0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70,0x61,
-	0x73,0x74,0x69,0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x70,
-	0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22,0x6E,
-	0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20,0x54,
-	0x68,0x65,0x20,0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74,
-	0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x20,
-	0x22,0x6E,0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x20,
-	0x69,0x73,0x20,0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E,0x73,
-	0x74,0x72,0x2E,0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F,0x6C,
-	0x75,0x6D,0x65,0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,
-	0x6E,0x72,0x20,0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,
-	0x64,0x61,0x74,0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79,0x6F,
-	0x75,0x20,0x63,0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69,0x6E,
+	0x32,0x52,0x41,0x70,0x70,0x6C,0x69,0x65,0x73,0x20,0x61,0x6E,
+	0x20,0x61,0x6E,0x74,0x69,0x2D,0x61,0x6C,0x69,0x61,0x73,0x69,
+	0x6E,0x67,0x20,0x73,0x75,0x62,0x70,0x69,0x78,0x65,0x6C,0x20,
+	0x66,0x69,0x6C,0x74,0x65,0x72,0x20,0x74,0x68,0x61,0x74,0x20,
+	0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x77,0x68,0x65,0x6E,
 	0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,
-	0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33,0x20,
-	0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D,0x22,
-	0x65,0x6E,0x61,0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61,0x62,
-	0x6C,0x65,0x20,0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22,0x20,
-	0x77,0x68,0x69,0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74,0x68,
-	0x65,0x20,0x6C,0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43,0x2C,
-	0x50,0x20,0x26,0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,
-	0x45,0x3E,0x43,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63,0x6F,
-	0x70,0x79,0x2C,0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74,0x72,
-	0x6F,0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,
-	0x72,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,
-	0x73,0x20,0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,
-	0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E,0x3E,
-	0x50,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73,0x74,
-	0x65,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,
-	0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,
-	0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,
-	0x20,0x6F,0x75,0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74,0x68,
-	0x65,0x0B,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,
-	0x2E,0x45,0x3E,0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x74,
-	0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x2E,
-	0x20,0x49,0x66,0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E,0x61,
-	0x62,0x6C,0x65,0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70,0x61,
-	0x73,0x74,0x69,0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E,0x27,
-	0x74,0x20,0x6F,0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65,0x3D,
-	0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E,0x69,
-	0x6C,0x2D,0x69,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F,
-	0x6E,0x2C,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74,0x68,
-	0x20,0x61,0x20,0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20,0x61,
-	0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20,0x30,
-	0x2E,0x01,0x3E,0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75,0x74,
-	0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20,0x77,
-	0x6F,0x72,0x6B,0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70,0x61,
-	0x73,0x74,0x69,0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20,0x7A,
-	0x65,0x72,0x6F,0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54,0x68,
-	0x69,0x73,0x20,0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68,0x61,
-	0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69,0x6E,
-	0x67,0x20,0x69,0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,
-	0x6C,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D,0x63,
-	0x6F,0x6C,0x75,0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54,0x2D,
-	0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57,0x68,
-	0x65,0x6E,0x20,0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79,0x20,
-	0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D,0x61,
-	0x73,0x6B,0x69,0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20,0x64,
-	0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72,0x74,
-	0x73,0x20,0x61,0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63,0x6C,
-	0x65,0x61,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,
-	0x20,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,
-	0x20,0x28,0x4D,0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74,0x20,
-	0x70,0x6F,0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F,0x20,
-	0x63,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61,
-	0x20,0x66,0x72,0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72,0x61,
-	0x6C,0x20,0x6C,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20,
-	0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,
-	0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03,0x45,
-	0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x69,0x73,0x20,0x75,0x70,0x73,0x63,0x61,0x6C,0x65,0x64,0x2E,
+	0x3B,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6B,0x65,0x65,0x70,
+	0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20,0x74,0x68,0x61,
+	0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,
+	0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,
+	0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x2E,
+	0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,
+	0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64,0x20,0x65,0x64,0x69,
+	0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x3A,
+	0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,
+	0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F,0x50,0x61,0x73,0x74,
+	0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x3A,0x0B,0x3E,
+	0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x37,0x54,
+	0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x20,0x69,
+	0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66,0x6F,0x72,0x20,0x63,
+	0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70,0x61,0x73,0x74,0x69,
+	0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x70,0x61,0x72,0x74,
+	0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22,0x6E,0x6F,0x74,0x65,
+	0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20,0x54,0x68,0x65,0x20,
+	0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x70,0x61,
+	0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x20,0x22,0x6E,0x6F,
+	0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x20,0x69,0x73,0x20,
+	0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E,0x73,0x74,0x72,0x2E,
+	0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F,0x6C,0x75,0x6D,0x65,
+	0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,0x6E,0x72,0x20,
+	0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,0x64,0x61,0x74,
+	0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79,0x6F,0x75,0x20,0x63,
+	0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69,0x6E,0x20,0x74,0x68,
+	0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,0x74,0x68,0x65,
+	0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33,0x20,0x63,0x6F,0x6C,
+	0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D,0x22,0x65,0x6E,0x61,
+	0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x20,
+	0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22,0x20,0x77,0x68,0x69,
+	0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74,0x68,0x65,0x20,0x6C,
+	0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43,0x2C,0x50,0x20,0x26,
+	0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,0x45,0x3E,0x43,
+	0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63,0x6F,0x70,0x79,0x2C,
+	0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,
+	0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,0x74,0x73,
+	0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x69,
+	0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,
+	0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E,0x3E,0x50,0x20,0x6D,
+	0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73,0x74,0x65,0x20,0x61,
+	0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,0x20,
+	0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,0x74,0x73,0x20,
+	0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x6F,0x75,
+	0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74,0x68,0x65,0x0B,0x63,
+	0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x45,0x3E,
+	0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x74,0x72,0x61,0x6E,
+	0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,
+	0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,
+	0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x73,0x74,0x69,
+	0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E,0x27,0x74,0x20,0x6F,
+	0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65,0x3D,0x64,0x61,0x74,
+	0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E,0x69,0x6C,0x2D,0x69,
+	0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,
+	0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,
+	0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20,0x61,0x20,0x6E,0x75,
+	0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20,0x30,0x2E,0x01,0x3E,
+	0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75,0x74,0x20,0x66,0x75,
+	0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20,0x77,0x6F,0x72,0x6B,
+	0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70,0x61,0x73,0x74,0x69,
+	0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20,0x7A,0x65,0x72,0x6F,
+	0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,
+	0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68,0x61,0x74,0x20,0x74,
+	0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69,0x6E,0x67,0x20,0x69,
+	0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x6C,0x65,0x64,
+	0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D,0x63,0x6F,0x6C,0x75,
+	0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54,0x2D,0x63,0x6F,0x6C,
+	0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57,0x68,0x65,0x6E,0x20,
+	0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79,0x20,0x64,0x61,0x74,
+	0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D,0x61,0x73,0x6B,0x69,
+	0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x73,0x61,
+	0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x61,
+	0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63,0x6C,0x65,0x61,0x72,
+	0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,
+	0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x20,0x28,0x4D,
+	0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74,0x20,0x70,0x6F,0x73,
+	0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F,0x20,0x63,0x6F,0x6C,
+	0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61,0x20,0x66,0x72,
+	0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x6C,
+	0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20,0x69,0x6E,0x74,
+	0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,0x62,0x75,
+	0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03,0x45,0x4E,0x44,0x4C,
+	0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,
+	0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0E,0x40,0x4C,
+	0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x2F,0x46,0x41,0x51,
+	0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2A,0x3E,0x40,0x43,0x30,
+	0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77,0x20,0x63,0x61,0x6E,
+	0x20,0x49,0x20,0x74,0x6F,0x67,0x67,0x6C,0x65,0x20,0x66,0x75,
+	0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,
+	0x65,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,
+	0x50,0x72,0x65,0x73,0x73,0x20,0x41,0x6C,0x74,0x2B,0x45,0x6E,
+	0x74,0x65,0x72,0x20,0x28,0x43,0x74,0x72,0x6C,0x2B,0x43,0x6D,
+	0x64,0x2B,0x46,0x20,0x61,0x6C,0x73,0x6F,0x20,0x77,0x6F,0x72,
+	0x6B,0x73,0x20,0x6F,0x6E,0x20,0x4D,0x61,0x63,0x29,0x06,0x3E,
+	0x40,0x58,0x30,0x32,0x30,0x45,0x3E,0x40,0x43,0x30,0x30,0x31,
+	0x51,0x3A,0x20,0x48,0x6F,0x77,0x20,0x63,0x61,0x6E,0x20,0x49,
+	0x20,0x6D,0x61,0x6B,0x65,0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,
+	0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x73,0x74,
+	0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75,0x74,0x20,0x74,0x68,
+	0x65,0x20,0x77,0x68,0x6F,0x6C,0x65,0x20,0x73,0x63,0x72,0x65,
+	0x65,0x6E,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
+	0x20,0x45,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x53,0x74,0x72,
+	0x65,0x74,0x63,0x68,0x65,0x64,0x22,0x20,0x69,0x6E,0x20,0x43,
+	0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,
+	0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,0x4E,
+	0x3E,0x40,0x58,0x30,0x33,0x35,0x54,0x68,0x69,0x73,0x20,0x77,
+	0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,
+	0x6E,0x20,0x75,0x6E,0x65,0x76,0x65,0x6E,0x20,0x70,0x69,0x78,
+	0x65,0x6C,0x20,0x77,0x69,0x64,0x74,0x68,0x73,0x2E,0x20,0x49,
+	0x66,0x20,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x20,0x74,
+	0x6F,0x20,0x66,0x69,0x78,0x20,0x74,0x68,0x69,0x73,0x2C,0x20,
+	0x65,0x6E,0x61,0x62,0x6C,0x65,0x3D,0x22,0x50,0x69,0x78,0x65,
+	0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,0x28,0x74,
+	0x68,0x6F,0x75,0x67,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x77,
+	0x69,0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20,0x74,0x68,0x65,
+	0x20,0x69,0x6D,0x61,0x67,0x65,0x20,0x6C,0x6F,0x6F,0x6B,0x20,
+	0x62,0x6C,0x75,0x72,0x72,0x79,0x29,0x2E,0x06,0x3E,0x40,0x58,
+	0x30,0x32,0x30,0x27,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,
+	0x20,0x49,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x75,0x73,0x65,
+	0x20,0x41,0x6C,0x74,0x2B,0x46,0x34,0x20,0x61,0x6E,0x64,0x20,
+	0x41,0x6C,0x74,0x2B,0x46,0x35,0x21,0x4E,0x3E,0x40,0x43,0x30,
+	0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,
+	0x3A,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x68,0x61,0x76,
+	0x65,0x20,0x47,0x65,0x46,0x6F,0x72,0x63,0x65,0x20,0x45,0x78,
+	0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20,0x69,0x6E,0x73,
+	0x74,0x61,0x6C,0x6C,0x65,0x64,0x2C,0x20,0x79,0x6F,0x75,0x20,
+	0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x63,0x68,0x61,0x6E,
+	0x67,0x65,0x2B,0x3E,0x40,0x58,0x30,0x33,0x35,0x74,0x68,0x65,
+	0x20,0x6B,0x65,0x79,0x62,0x69,0x6E,0x64,0x69,0x6E,0x67,0x73,
+	0x20,0x69,0x6E,0x20,0x69,0x74,0x73,0x20,0x73,0x65,0x74,0x74,
+	0x69,0x6E,0x67,0x73,0x20,0x70,0x61,0x67,0x65,0x2E,0x57,0x3E,
+	0x6D,0x61,0x63,0x4F,0x53,0x2F,0x4F,0x53,0x20,0x58,0x3A,0x20,
+	0x43,0x68,0x61,0x6E,0x67,0x65,0x20,0x41,0x6C,0x74,0x2B,0x46,
+	0x34,0x2F,0x41,0x6C,0x74,0x2B,0x46,0x35,0x20,0x6B,0x65,0x79,
+	0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,
+	0x74,0x6F,0x20,0x73,0x6F,0x6D,0x65,0x74,0x68,0x69,0x6E,0x67,
+	0x20,0x65,0x6C,0x73,0x65,0x2E,0x20,0x41,0x6C,0x73,0x6F,0x20,
+	0x66,0x6F,0x72,0x20,0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,
+	0x78,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2B,0x3E,0x40,
+	0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,
+	0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,
+	0x69,0x73,0x20,0x64,0x65,0x6C,0x61,0x79,0x65,0x64,0x2F,0x6C,
+	0x61,0x67,0x67,0x79,0x21,0x44,0x3E,0x40,0x43,0x30,0x30,0x32,
+	0x41,0x3A,0x20,0x4D,0x61,0x6B,0x65,0x20,0x73,0x75,0x72,0x65,
+	0x20,0x22,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x6D,
+	0x6F,0x75,0x73,0x65,0x22,0x20,0x69,0x73,0x20,0x64,0x69,0x73,
+	0x61,0x62,0x6C,0x65,0x64,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,
+	0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4C,0x61,0x79,0x6F,0x75,
+	0x74,0x2E,0x4B,0x3E,0x40,0x58,0x30,0x33,0x35,0x41,0x6C,0x74,
+	0x65,0x72,0x6E,0x61,0x74,0x69,0x76,0x65,0x6C,0x79,0x2C,0x20,
+	0x79,0x6F,0x75,0x20,0x63,0x61,0x6E,0x20,0x65,0x6E,0x61,0x62,
+	0x6C,0x65,0x20,0x22,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F,0x66,
+	0x66,0x22,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,
+	0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,
+	0x6E,0x65,0x6F,0x75,0x73,0x2E,0x46,0x3E,0x54,0x68,0x69,0x73,
+	0x20,0x68,0x6F,0x77,0x65,0x76,0x65,0x72,0x2C,0x20,0x77,0x69,
+	0x6C,0x6C,0x20,0x69,0x6E,0x74,0x72,0x6F,0x64,0x75,0x63,0x65,
+	0x20,0x73,0x74,0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x20,
+	0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,
+	0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,0x67,0x20,0x72,0x61,
+	0x74,0x65,0x20,0x69,0x73,0x22,0x3E,0x6E,0x6F,0x74,0x20,0x65,
+	0x78,0x61,0x63,0x74,0x20,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72,
+	0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x20,0x72,
+	0x61,0x74,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x33,
+	0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x69,0x6C,
+	0x6C,0x20,0x79,0x6F,0x75,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,
+	0x65,0x6E,0x74,0x20,0x4D,0x49,0x44,0x49,0x20,0x6F,0x75,0x74,
+	0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x61,0x6C,0x69,
+	0x74,0x79,0x3F,0x4D,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
+	0x20,0x4E,0x6F,0x2C,0x20,0x73,0x6F,0x72,0x72,0x79,0x2E,0x20,
+	0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x76,0x65,0x72,0x79,
+	0x20,0x64,0x69,0x66,0x66,0x69,0x63,0x75,0x6C,0x74,0x20,0x74,
+	0x6F,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,
+	0x63,0x6F,0x72,0x72,0x65,0x63,0x74,0x6C,0x79,0x20,0x77,0x68,
+	0x65,0x6E,0x20,0x68,0x61,0x76,0x69,0x6E,0x67,0x3C,0x3E,0x40,
+	0x58,0x30,0x33,0x35,0x68,0x69,0x67,0x68,0x65,0x72,0x20,0x61,
+	0x75,0x64,0x69,0x6F,0x20,0x62,0x75,0x66,0x66,0x65,0x72,0x20,
+	0x73,0x69,0x7A,0x65,0x73,0x20,0x28,0x62,0x75,0x66,0x66,0x65,
+	0x72,0x65,0x64,0x20,0x72,0x65,0x70,0x6C,0x61,0x79,0x65,0x72,
+	0x20,0x74,0x69,0x63,0x6B,0x73,0x29,0x2E,0x2E,0x2E,0x06,0x3E,
+	0x40,0x58,0x30,0x32,0x30,0x30,0x3E,0x40,0x43,0x30,0x30,0x31,
+	0x51,0x3A,0x20,0x57,0x68,0x65,0x72,0x65,0x20,0x69,0x73,0x20,
+	0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,
+	0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x73,
+	0x74,0x6F,0x72,0x65,0x64,0x3F,0x3F,0x3E,0x40,0x43,0x30,0x30,
+	0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,
+	0x20,0x5C,0x55,0x73,0x65,0x72,0x73,0x5C,0x55,0x53,0x45,0x52,
+	0x5C,0x41,0x70,0x70,0x44,0x61,0x74,0x61,0x5C,0x52,0x6F,0x61,
+	0x6D,0x69,0x6E,0x67,0x5C,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,
+	0x6E,0x65,0x5C,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x45,0x3E,
+	0x40,0x58,0x30,0x33,0x35,0x4F,0x53,0x20,0x58,0x3A,0x20,0x2F,
+	0x55,0x73,0x65,0x72,0x73,0x2F,0x55,0x53,0x45,0x52,0x2F,0x4C,
+	0x69,0x62,0x72,0x61,0x72,0x79,0x2F,0x41,0x70,0x70,0x6C,0x69,
+	0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x75,0x70,0x70,0x6F,
+	0x72,0x74,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,
+	0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x2F,0x47,0x4E,0x55,
+	0x2F,0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20,0x2F,0x68,0x6F,0x6D,
+	0x65,0x2F,0x55,0x53,0x45,0x52,0x2F,0x2E,0x63,0x6F,0x6E,0x66,
+	0x69,0x67,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,
+	0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x01,0x3E,0x48,0x49,
+	0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x62,0x65,0x20,0x73,0x74,
+	0x6F,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,
+	0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,
+	0x63,0x74,0x6F,0x72,0x79,0x20,0x69,0x66,0x20,0x74,0x68,0x65,
+	0x20,0x70,0x61,0x74,0x68,0x20,0x63,0x6F,0x75,0x6C,0x64,0x6E,
+	0x27,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x2E,0x4D,
+	0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x70,0x75,0x74,0x20,0x74,
+	0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,
+	0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x69,0x6E,
+	0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,
+	0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x2C,0x20,
+	0x69,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x61,0x64,
+	0x20,0x74,0x68,0x61,0x74,0x4A,0x6F,0x6E,0x65,0x20,0x61,0x6E,
+	0x64,0x20,0x6E,0x6F,0x74,0x20,0x61,0x74,0x74,0x65,0x6D,0x70,
+	0x74,0x20,0x74,0x6F,0x20,0x63,0x72,0x65,0x61,0x74,0x65,0x20,
+	0x63,0x6F,0x6E,0x66,0x69,0x67,0x20,0x64,0x69,0x72,0x73,0x20,
+	0x66,0x6F,0x72,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,0x75,
+	0x73,0x65,0x72,0x2E,0x20,0x28,0x70,0x6F,0x72,0x74,0x61,0x62,
+	0x6C,0x65,0x20,0x6D,0x6F,0x64,0x65,0x29,0x06,0x3E,0x40,0x58,
+	0x30,0x32,0x30,0x42,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,
+	0x20,0x43,0x61,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6C,0x6F,
+	0x6E,0x65,0x20,0x72,0x65,0x61,0x64,0x20,0x46,0x54,0x32,0x2E,
+	0x43,0x46,0x47,0x20,0x66,0x72,0x6F,0x6D,0x20,0x72,0x65,0x61,
+	0x6C,0x20,0x46,0x54,0x32,0x2C,0x20,0x61,0x6E,0x64,0x20,0x76,
+	0x69,0x63,0x65,0x20,0x76,0x65,0x72,0x73,0x61,0x3F,0x4C,0x3E,
+	0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x59,0x65,0x73,0x2C,
+	0x20,0x69,0x74,0x20,0x73,0x68,0x6F,0x75,0x6C,0x64,0x20,0x77,
+	0x6F,0x72,0x6B,0x20,0x6A,0x75,0x73,0x74,0x20,0x66,0x69,0x6E,
+	0x65,0x2E,0x20,0x50,0x75,0x74,0x20,0x69,0x74,0x20,0x69,0x6E,
+	0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,
+	0x72,0x79,0x20,0x73,0x68,0x6F,0x77,0x6E,0x20,0x61,0x62,0x6F,
+	0x76,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x51,0x3E,
+	0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x53,0x6D,0x70,0x2E,
+	0x20,0x45,0x64,0x2E,0x3A,0x20,0x57,0x68,0x69,0x6C,0x65,0x20,
+	0x7A,0x6F,0x6F,0x6D,0x65,0x64,0x20,0x69,0x6E,0x2C,0x20,0x49,
+	0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,0x73,0x20,0x63,
+	0x61,0x6E,0x27,0x74,0x20,0x6D,0x61,0x72,0x6B,0x20,0x74,0x68,
+	0x65,0x20,0x6C,0x61,0x73,0x74,0x20,0x73,0x61,0x6D,0x70,0x6C,
+	0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x21,0x47,0x3E,0x40,0x43,
+	0x30,0x30,0x32,0x41,0x3A,0x20,0x54,0x68,0x69,0x73,0x20,0x69,
+	0x73,0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E,0x20,0x54,0x68,
+	0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x6C,0x69,0x6D,0x69,
+	0x74,0x61,0x74,0x69,0x6F,0x6E,0x20,0x69,0x6E,0x20,0x74,0x68,
+	0x65,0x20,0x6E,0x61,0x74,0x75,0x72,0x65,0x20,0x6F,0x66,0x20,
+	0x73,0x63,0x61,0x6C,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,
+	0x30,0x32,0x30,0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,
+	0x20,0x49,0x20,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x20,0x62,
+	0x75,0x67,0x21,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
+	0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6E,0x64,
+	0x20,0x6D,0x65,0x20,0x61,0x20,0x6D,0x61,0x69,0x6C,0x20,0x28,
+	0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x74,0x20,0x31,0x36,0x2D,
+	0x62,0x69,0x74,0x73,0x2E,0x6F,0x72,0x67,0x29,0x20,0x61,0x6E,
+	0x64,0x20,0x74,0x72,0x79,0x20,0x74,0x6F,0x20,0x65,0x78,0x70,
+	0x6C,0x61,0x69,0x6E,0x20,0x69,0x74,0x2E,0x00,0x03,0x45,0x4E,
+	0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x0E,0x40,0x4C,0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x2F,
-	0x46,0x41,0x51,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2A,0x3E,
-	0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77,0x20,
-	0x63,0x61,0x6E,0x20,0x49,0x20,0x74,0x6F,0x67,0x67,0x6C,0x65,
-	0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,
-	0x6D,0x6F,0x64,0x65,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30,0x32,
-	0x41,0x3A,0x20,0x50,0x72,0x65,0x73,0x73,0x20,0x41,0x6C,0x74,
-	0x2B,0x45,0x6E,0x74,0x65,0x72,0x20,0x28,0x43,0x74,0x72,0x6C,
-	0x2B,0x43,0x6D,0x64,0x2B,0x46,0x20,0x61,0x6C,0x73,0x6F,0x20,
-	0x77,0x6F,0x72,0x6B,0x73,0x20,0x6F,0x6E,0x20,0x4D,0x61,0x63,
-	0x29,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x45,0x3E,0x40,0x43,
-	0x30,0x30,0x31,0x51,0x3A,0x20,0x48,0x6F,0x77,0x20,0x63,0x61,
-	0x6E,0x20,0x49,0x20,0x6D,0x61,0x6B,0x65,0x20,0x66,0x75,0x6C,
-	0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,
-	0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75,0x74,
-	0x20,0x74,0x68,0x65,0x20,0x77,0x68,0x6F,0x6C,0x65,0x20,0x73,
-	0x63,0x72,0x65,0x65,0x6E,0x3F,0x37,0x3E,0x40,0x43,0x30,0x30,
-	0x32,0x41,0x3A,0x20,0x45,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,
-	0x53,0x74,0x72,0x65,0x74,0x63,0x68,0x65,0x64,0x22,0x20,0x69,
-	0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,
-	0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,
-	0x73,0x2E,0x4E,0x3E,0x40,0x58,0x30,0x33,0x35,0x54,0x68,0x69,
-	0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,
-	0x74,0x20,0x69,0x6E,0x20,0x75,0x6E,0x65,0x76,0x65,0x6E,0x20,
-	0x70,0x69,0x78,0x65,0x6C,0x20,0x77,0x69,0x64,0x74,0x68,0x73,
-	0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,
-	0x74,0x20,0x74,0x6F,0x20,0x66,0x69,0x78,0x20,0x74,0x68,0x69,
-	0x73,0x2C,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,0x3D,0x22,0x50,
-	0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,
-	0x20,0x28,0x74,0x68,0x6F,0x75,0x67,0x68,0x20,0x74,0x68,0x69,
-	0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20,
-	0x74,0x68,0x65,0x20,0x69,0x6D,0x61,0x67,0x65,0x20,0x6C,0x6F,
-	0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x29,0x2E,0x06,
-	0x3E,0x40,0x58,0x30,0x32,0x30,0x27,0x3E,0x40,0x43,0x30,0x30,
-	0x31,0x51,0x3A,0x20,0x49,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,
-	0x75,0x73,0x65,0x20,0x41,0x6C,0x74,0x2B,0x46,0x34,0x20,0x61,
-	0x6E,0x64,0x20,0x41,0x6C,0x74,0x2B,0x46,0x35,0x21,0x4E,0x3E,
-	0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,
-	0x6F,0x77,0x73,0x3A,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,
-	0x68,0x61,0x76,0x65,0x20,0x47,0x65,0x46,0x6F,0x72,0x63,0x65,
-	0x20,0x45,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20,
-	0x69,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x65,0x64,0x2C,0x20,0x79,
-	0x6F,0x75,0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x63,
-	0x68,0x61,0x6E,0x67,0x65,0x2B,0x3E,0x40,0x58,0x30,0x33,0x35,
-	0x74,0x68,0x65,0x20,0x6B,0x65,0x79,0x62,0x69,0x6E,0x64,0x69,
-	0x6E,0x67,0x73,0x20,0x69,0x6E,0x20,0x69,0x74,0x73,0x20,0x73,
-	0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x70,0x61,0x67,0x65,
-	0x2E,0x57,0x3E,0x6D,0x61,0x63,0x4F,0x53,0x2F,0x4F,0x53,0x20,
-	0x58,0x3A,0x20,0x43,0x68,0x61,0x6E,0x67,0x65,0x20,0x41,0x6C,
-	0x74,0x2B,0x46,0x34,0x2F,0x41,0x6C,0x74,0x2B,0x46,0x35,0x20,
-	0x6B,0x65,0x79,0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,
-	0x4F,0x53,0x20,0x74,0x6F,0x20,0x73,0x6F,0x6D,0x65,0x74,0x68,
-	0x69,0x6E,0x67,0x20,0x65,0x6C,0x73,0x65,0x2E,0x20,0x41,0x6C,
-	0x73,0x6F,0x20,0x66,0x6F,0x72,0x20,0x47,0x4E,0x55,0x2F,0x4C,
-	0x69,0x6E,0x75,0x78,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,
-	0x2B,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x54,0x68,
-	0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73,
-	0x6F,0x72,0x20,0x69,0x73,0x20,0x64,0x65,0x6C,0x61,0x79,0x65,
-	0x64,0x2F,0x6C,0x61,0x67,0x67,0x79,0x21,0x44,0x3E,0x40,0x43,
-	0x30,0x30,0x32,0x41,0x3A,0x20,0x4D,0x61,0x6B,0x65,0x20,0x73,
-	0x75,0x72,0x65,0x20,0x22,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,
-	0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x22,0x20,0x69,0x73,0x20,
-	0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x69,0x6E,0x20,
-	0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4C,0x61,
-	0x79,0x6F,0x75,0x74,0x2E,0x4B,0x3E,0x40,0x58,0x30,0x33,0x35,
-	0x41,0x6C,0x74,0x65,0x72,0x6E,0x61,0x74,0x69,0x76,0x65,0x6C,
-	0x79,0x2C,0x20,0x79,0x6F,0x75,0x20,0x63,0x61,0x6E,0x20,0x65,
-	0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x56,0x53,0x79,0x6E,0x63,
-	0x20,0x6F,0x66,0x66,0x22,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,
-	0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,0x63,0x65,
-	0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,0x46,0x3E,0x54,
-	0x68,0x69,0x73,0x20,0x68,0x6F,0x77,0x65,0x76,0x65,0x72,0x2C,
-	0x20,0x77,0x69,0x6C,0x6C,0x20,0x69,0x6E,0x74,0x72,0x6F,0x64,
-	0x75,0x63,0x65,0x20,0x73,0x74,0x75,0x74,0x74,0x65,0x72,0x69,
-	0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x74,
-	0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,0x67,
-	0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x22,0x3E,0x6E,0x6F,
-	0x74,0x20,0x65,0x78,0x61,0x63,0x74,0x20,0x74,0x6F,0x20,0x79,
-	0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,
-	0x73,0x20,0x72,0x61,0x74,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,
-	0x32,0x30,0x33,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,
-	0x57,0x69,0x6C,0x6C,0x20,0x79,0x6F,0x75,0x20,0x69,0x6D,0x70,
-	0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,0x4D,0x49,0x44,0x49,0x20,
-	0x6F,0x75,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,
-	0x61,0x6C,0x69,0x74,0x79,0x3F,0x4D,0x3E,0x40,0x43,0x30,0x30,
-	0x32,0x41,0x3A,0x20,0x4E,0x6F,0x2C,0x20,0x73,0x6F,0x72,0x72,
-	0x79,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x76,
-	0x65,0x72,0x79,0x20,0x64,0x69,0x66,0x66,0x69,0x63,0x75,0x6C,
-	0x74,0x20,0x74,0x6F,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,
-	0x6E,0x74,0x20,0x63,0x6F,0x72,0x72,0x65,0x63,0x74,0x6C,0x79,
-	0x20,0x77,0x68,0x65,0x6E,0x20,0x68,0x61,0x76,0x69,0x6E,0x67,
-	0x3C,0x3E,0x40,0x58,0x30,0x33,0x35,0x68,0x69,0x67,0x68,0x65,
-	0x72,0x20,0x61,0x75,0x64,0x69,0x6F,0x20,0x62,0x75,0x66,0x66,
-	0x65,0x72,0x20,0x73,0x69,0x7A,0x65,0x73,0x20,0x28,0x62,0x75,
-	0x66,0x66,0x65,0x72,0x65,0x64,0x20,0x72,0x65,0x70,0x6C,0x61,
-	0x79,0x65,0x72,0x20,0x74,0x69,0x63,0x6B,0x73,0x29,0x2E,0x2E,
-	0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x30,0x3E,0x40,0x43,
-	0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x68,0x65,0x72,0x65,0x20,
-	0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,
-	0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,
-	0x65,0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x3F,0x3F,0x3E,0x40,
-	0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,
-	0x77,0x73,0x3A,0x20,0x5C,0x55,0x73,0x65,0x72,0x73,0x5C,0x55,
-	0x53,0x45,0x52,0x5C,0x41,0x70,0x70,0x44,0x61,0x74,0x61,0x5C,
-	0x52,0x6F,0x61,0x6D,0x69,0x6E,0x67,0x5C,0x46,0x54,0x32,0x20,
-	0x63,0x6C,0x6F,0x6E,0x65,0x5C,0x46,0x54,0x32,0x2E,0x43,0x46,
-	0x47,0x45,0x3E,0x40,0x58,0x30,0x33,0x35,0x4F,0x53,0x20,0x58,
-	0x3A,0x20,0x2F,0x55,0x73,0x65,0x72,0x73,0x2F,0x55,0x53,0x45,
-	0x52,0x2F,0x4C,0x69,0x62,0x72,0x61,0x72,0x79,0x2F,0x41,0x70,
-	0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x75,
-	0x70,0x70,0x6F,0x72,0x74,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,
-	0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x2F,
-	0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20,0x2F,
-	0x68,0x6F,0x6D,0x65,0x2F,0x55,0x53,0x45,0x52,0x2F,0x2E,0x63,
-	0x6F,0x6E,0x66,0x69,0x67,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,
-	0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x01,
-	0x3E,0x48,0x49,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x62,0x65,
-	0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,
-	0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,
-	0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,0x69,0x66,0x20,
-	0x74,0x68,0x65,0x20,0x70,0x61,0x74,0x68,0x20,0x63,0x6F,0x75,
-	0x6C,0x64,0x6E,0x27,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65,
-	0x64,0x2E,0x4D,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x70,0x75,
-	0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,
-	0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,
-	0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,
-	0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,
-	0x79,0x2C,0x20,0x69,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,
-	0x65,0x61,0x64,0x20,0x74,0x68,0x61,0x74,0x4A,0x6F,0x6E,0x65,
-	0x20,0x61,0x6E,0x64,0x20,0x6E,0x6F,0x74,0x20,0x61,0x74,0x74,
-	0x65,0x6D,0x70,0x74,0x20,0x74,0x6F,0x20,0x63,0x72,0x65,0x61,
-	0x74,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x20,0x64,0x69,
-	0x72,0x73,0x20,0x66,0x6F,0x72,0x20,0x74,0x68,0x65,0x20,0x4F,
-	0x53,0x20,0x75,0x73,0x65,0x72,0x2E,0x20,0x28,0x70,0x6F,0x72,
-	0x74,0x61,0x62,0x6C,0x65,0x20,0x6D,0x6F,0x64,0x65,0x29,0x06,
-	0x3E,0x40,0x58,0x30,0x32,0x30,0x42,0x3E,0x40,0x43,0x30,0x30,
-	0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,0x74,0x68,0x65,0x20,
-	0x63,0x6C,0x6F,0x6E,0x65,0x20,0x72,0x65,0x61,0x64,0x20,0x46,
-	0x54,0x32,0x2E,0x43,0x46,0x47,0x20,0x66,0x72,0x6F,0x6D,0x20,
-	0x72,0x65,0x61,0x6C,0x20,0x46,0x54,0x32,0x2C,0x20,0x61,0x6E,
-	0x64,0x20,0x76,0x69,0x63,0x65,0x20,0x76,0x65,0x72,0x73,0x61,
-	0x3F,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x59,
-	0x65,0x73,0x2C,0x20,0x69,0x74,0x20,0x73,0x68,0x6F,0x75,0x6C,
-	0x64,0x20,0x77,0x6F,0x72,0x6B,0x20,0x6A,0x75,0x73,0x74,0x20,
-	0x66,0x69,0x6E,0x65,0x2E,0x20,0x50,0x75,0x74,0x20,0x69,0x74,
-	0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x72,0x65,
-	0x63,0x74,0x6F,0x72,0x79,0x20,0x73,0x68,0x6F,0x77,0x6E,0x20,
-	0x61,0x62,0x6F,0x76,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,
-	0x30,0x51,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x53,
-	0x6D,0x70,0x2E,0x20,0x45,0x64,0x2E,0x3A,0x20,0x57,0x68,0x69,
-	0x6C,0x65,0x20,0x7A,0x6F,0x6F,0x6D,0x65,0x64,0x20,0x69,0x6E,
-	0x2C,0x20,0x49,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,
-	0x73,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x6D,0x61,0x72,0x6B,
-	0x20,0x74,0x68,0x65,0x20,0x6C,0x61,0x73,0x74,0x20,0x73,0x61,
-	0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x21,0x47,
-	0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x54,0x68,0x69,
-	0x73,0x20,0x69,0x73,0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E,
-	0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x6C,
-	0x69,0x6D,0x69,0x74,0x61,0x74,0x69,0x6F,0x6E,0x20,0x69,0x6E,
-	0x20,0x74,0x68,0x65,0x20,0x6E,0x61,0x74,0x75,0x72,0x65,0x20,
-	0x6F,0x66,0x20,0x73,0x63,0x61,0x6C,0x69,0x6E,0x67,0x2E,0x06,
-	0x3E,0x40,0x58,0x30,0x32,0x30,0x17,0x3E,0x40,0x43,0x30,0x30,
-	0x31,0x51,0x3A,0x20,0x49,0x20,0x66,0x6F,0x75,0x6E,0x64,0x20,
-	0x61,0x20,0x62,0x75,0x67,0x21,0x4C,0x3E,0x40,0x43,0x30,0x30,
-	0x32,0x41,0x3A,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x73,
-	0x65,0x6E,0x64,0x20,0x6D,0x65,0x20,0x61,0x20,0x6D,0x61,0x69,
-	0x6C,0x20,0x28,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x74,0x20,
-	0x31,0x36,0x2D,0x62,0x69,0x74,0x73,0x2E,0x6F,0x72,0x67,0x29,
-	0x20,0x61,0x6E,0x64,0x20,0x74,0x72,0x79,0x20,0x74,0x6F,0x20,
-	0x65,0x78,0x70,0x6C,0x61,0x69,0x6E,0x20,0x69,0x74,0x2E,0x00,
-	0x03,0x45,0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
 	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
-	0x2A,0x2A,0x0C,0x40,0x4C,0x4B,0x6E,0x6F,0x77,0x6E,0x20,0x62,
-	0x75,0x67,0x73,0x01,0x3E,0x31,0x3E,0x40,0x58,0x30,0x31,0x30,
-	0x40,0x43,0x30,0x30,0x31,0x57,0x41,0x56,0x20,0x65,0x78,0x70,
-	0x6F,0x72,0x74,0x69,0x6E,0x67,0x20,0x28,0x72,0x65,0x6E,0x64,
-	0x65,0x72,0x69,0x6E,0x67,0x20,0x73,0x6F,0x6E,0x67,0x20,0x74,
-	0x6F,0x20,0x57,0x41,0x56,0x29,0x3A,0x01,0x3E,0x55,0x3E,0x40,
-	0x58,0x30,0x31,0x30,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x53,
-	0x6F,0x6E,0x67,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x6A,0x75,
-	0x6D,0x70,0x20,0x62,0x61,0x63,0x6B,0x20,0x74,0x6F,0x20,0x61,
-	0x20,0x70,0x72,0x65,0x76,0x69,0x6F,0x75,0x73,0x20,0x70,0x61,
-	0x74,0x74,0x65,0x72,0x6E,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,
-	0x65,0x6E,0x64,0x65,0x72,0x20,0x66,0x6F,0x72,0x65,0x76,0x65,
-	0x72,0x20,0x61,0x6E,0x64,0x20,0x65,0x76,0x65,0x72,0x2C,0x4D,
-	0x3E,0x40,0x58,0x30,0x32,0x31,0x61,0x6E,0x64,0x20,0x79,0x6F,
-	0x75,0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x70,0x72,
-	0x65,0x73,0x73,0x20,0x61,0x20,0x6B,0x65,0x79,0x20,0x6F,0x72,
-	0x20,0x63,0x6C,0x69,0x63,0x6B,0x20,0x74,0x68,0x65,0x20,0x6D,
-	0x6F,0x75,0x73,0x65,0x20,0x74,0x6F,0x20,0x61,0x62,0x6F,0x72,
-	0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,
-	0x20,0x77,0x68,0x65,0x6E,0x15,0x3E,0x40,0x58,0x30,0x32,0x31,
-	0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x20,0x69,0x74,0x20,
-	0x74,0x6F,0x2E,0x01,0x3E,0x11,0x3E,0x40,0x58,0x30,0x31,0x30,
-	0x40,0x43,0x30,0x30,0x31,0x56,0x69,0x64,0x65,0x6F,0x3A,0x06,
-	0x3E,0x40,0x43,0x30,0x30,0x32,0x50,0x3E,0x40,0x58,0x30,0x31,
-	0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,
-	0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x62,
-	0x65,0x20,0x75,0x6E,0x62,0x65,0x61,0x72,0x61,0x62,0x6C,0x79,
-	0x20,0x73,0x6C,0x6F,0x77,0x20,0x6F,0x6E,0x20,0x61,0x20,0x52,
-	0x61,0x73,0x70,0x62,0x65,0x72,0x72,0x79,0x20,0x50,0x69,0x20,
-	0x28,0x65,0x76,0x65,0x6E,0x20,0x6F,0x6E,0x20,0x52,0x50,0x69,
-	0x20,0x34,0x29,0x4A,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,
+	0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0C,
+	0x40,0x4C,0x4B,0x6E,0x6F,0x77,0x6E,0x20,0x62,0x75,0x67,0x73,
+	0x01,0x3E,0x31,0x3E,0x40,0x58,0x30,0x31,0x30,0x40,0x43,0x30,
+	0x30,0x31,0x57,0x41,0x56,0x20,0x65,0x78,0x70,0x6F,0x72,0x74,
+	0x69,0x6E,0x67,0x20,0x28,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,
+	0x6E,0x67,0x20,0x73,0x6F,0x6E,0x67,0x20,0x74,0x6F,0x20,0x57,
+	0x41,0x56,0x29,0x3A,0x01,0x3E,0x55,0x3E,0x40,0x58,0x30,0x31,
+	0x30,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x53,0x6F,0x6E,0x67,
+	0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x6A,0x75,0x6D,0x70,0x20,
+	0x62,0x61,0x63,0x6B,0x20,0x74,0x6F,0x20,0x61,0x20,0x70,0x72,
+	0x65,0x76,0x69,0x6F,0x75,0x73,0x20,0x70,0x61,0x74,0x74,0x65,
+	0x72,0x6E,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x6E,0x64,
+	0x65,0x72,0x20,0x66,0x6F,0x72,0x65,0x76,0x65,0x72,0x20,0x61,
+	0x6E,0x64,0x20,0x65,0x76,0x65,0x72,0x2C,0x4D,0x3E,0x40,0x58,
+	0x30,0x32,0x31,0x61,0x6E,0x64,0x20,0x79,0x6F,0x75,0x20,0x6E,
+	0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x70,0x72,0x65,0x73,0x73,
+	0x20,0x61,0x20,0x6B,0x65,0x79,0x20,0x6F,0x72,0x20,0x63,0x6C,
+	0x69,0x63,0x6B,0x20,0x74,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,
+	0x65,0x20,0x74,0x6F,0x20,0x61,0x62,0x6F,0x72,0x74,0x20,0x74,
+	0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x77,0x68,
+	0x65,0x6E,0x15,0x3E,0x40,0x58,0x30,0x32,0x31,0x79,0x6F,0x75,
+	0x20,0x77,0x61,0x6E,0x74,0x20,0x69,0x74,0x20,0x74,0x6F,0x2E,
+	0x01,0x3E,0x11,0x3E,0x40,0x58,0x30,0x31,0x30,0x40,0x43,0x30,
+	0x30,0x31,0x56,0x69,0x64,0x65,0x6F,0x3A,0x06,0x3E,0x40,0x43,
+	0x30,0x30,0x32,0x4C,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,
 	0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,
 	0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x68,0x61,0x76,0x65,
-	0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x70,0x72,0x6F,
-	0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E,0x20,0x6D,0x75,0x6C,
-	0x74,0x69,0x2D,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x20,0x73,
-	0x79,0x73,0x74,0x65,0x6D,0x73,0x47,0x3E,0x40,0x58,0x30,0x31,
-	0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,
-	0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x68,
-	0x61,0x76,0x65,0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,
-	0x70,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E,0x20,
-	0x73,0x6F,0x6D,0x65,0x20,0x4C,0x69,0x6E,0x75,0x78,0x20,0x73,
-	0x79,0x73,0x74,0x65,0x6D,0x73,0x00,0x03,0x45,0x4E,0x44
+	0x20,0x69,0x73,0x73,0x75,0x65,0x73,0x20,0x77,0x69,0x74,0x68,
+	0x20,0x74,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x20,0x70,
+	0x69,0x78,0x65,0x6C,0x20,0x6D,0x61,0x70,0x70,0x69,0x6E,0x67,
+	0x20,0x6F,0x6E,0x20,0x73,0x6F,0x6D,0x65,0x14,0x3E,0x40,0x58,
+	0x30,0x32,0x31,0x4C,0x69,0x6E,0x75,0x78,0x20,0x73,0x79,0x73,
+	0x74,0x65,0x6D,0x73,0x2E,0x4A,0x3E,0x40,0x58,0x30,0x31,0x30,
+	0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,
+	0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,0x68,0x61,
+	0x76,0x65,0x20,0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x70,
+	0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x20,0x6F,0x6E,0x20,0x6D,
+	0x75,0x6C,0x74,0x69,0x2D,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,
+	0x20,0x73,0x79,0x73,0x74,0x65,0x6D,0x73,0x00,0x03,0x45,0x4E,
+	0x44
 };
 
 #endif
--- a/src/mixer/ft2_cubic_spline.c
+++ b/src/mixer/ft2_cubic_spline.c
@@ -18,13 +18,13 @@
 	float *fPtr = fCubicSplineLUT;
 	for (int32_t i = 0; i < CUBIC_SPLINE_PHASES; i++)
 	{
-		const double x  = i * (1.0 / CUBIC_SPLINE_PHASES); // x = i / CUBIC_SPLINE_PHASES
-		const double x2 = x * x;  // x^2
-		const double x3 = x2 * x; // x^3
+		const double x1 = i * (1.0 / (double)CUBIC_SPLINE_PHASES); // i / CUBIC_SPLINE_PHASES
+		const double x2 = x1 * x1; // x^2
+		const double x3 = x2 * x1; // x^3
 
-		*fPtr++ = (float)(-0.5 * x3 + 1.0 * x2 - 0.5 * x);
+		*fPtr++ = (float)(-0.5 * x3 + 1.0 * x2 - 0.5 * x1);
 		*fPtr++ = (float)( 1.5 * x3 - 2.5 * x2 + 1.0);
-		*fPtr++ = (float)(-1.5 * x3 + 2.0 * x2 + 0.5 * x);
+		*fPtr++ = (float)(-1.5 * x3 + 2.0 * x2 + 0.5 * x1);
 		*fPtr++ = (float)( 0.5 * x3 - 0.5 * x2);
 	}
 
--- a/src/mixer/ft2_cubic_spline.h
+++ b/src/mixer/ft2_cubic_spline.h
@@ -6,7 +6,7 @@
 #include "ft2_mix.h" // MIXER_FRAC_BITS
 
 #define CUBIC_SPLINE_TAPS 4
-#define CUBIC_WIDTH_BITS 2
+#define CUBIC_WIDTH_BITS 2 // log2(CUBIC_SPLINE_TAPS)
 
 // 8192 is a good compromise
 #define CUBIC_SPLINE_PHASES 8192
--- a/src/mixer/ft2_mix.c
+++ b/src/mixer/ft2_mix.c
@@ -2,7 +2,6 @@
 #include <stdbool.h>
 #include "ft2_mix.h"
 #include "ft2_mix_macros.h"
-#include "../ft2_cpu.h"
 
 /*
 ** ------------ 32-bit floating-point audio channel mixer ------------
@@ -11,7 +10,7 @@
 ** Specifications:
 ** - Interpolation: None, 2-tap linear, 4-tap cubic spline, 8-tap windowed-sinc, 16-tap windowed-sinc
 ** - FT2-styled linear volume ramping (can be turned off)
-** - 32.32 (16.16 if 32-bit CPU) fixed-point precision for resampling delta/position
+** - 32.32 fixed-point precision for resampling delta/position
 ** - 32-bit floating-point precision for mixing and interpolation
 **
 ** This file has separate routines for EVERY possible sampling variation:
@@ -37,7 +36,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -79,7 +78,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -121,7 +120,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -164,7 +163,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -207,7 +206,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -274,7 +273,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -342,7 +341,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -384,7 +383,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -426,7 +425,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -464,13 +463,13 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -506,7 +505,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
 	int8_t *smpTapPtr;
@@ -513,7 +512,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -573,7 +572,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
 	int8_t *smpTapPtr;
@@ -580,7 +579,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -648,7 +647,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -691,7 +690,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -758,7 +757,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -827,7 +826,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -877,7 +876,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -927,7 +926,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -979,7 +978,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1030,7 +1029,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1110,7 +1109,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1191,7 +1190,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1241,7 +1240,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1291,7 +1290,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1336,7 +1335,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bRampNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bRampNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
 	float fSample, *fMixBufferL, *fMixBufferR;
@@ -1343,7 +1342,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1386,7 +1385,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bRampLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bRampLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int8_t *base, *smpPtr;
 	int8_t *smpTapPtr;
@@ -1394,7 +1393,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1466,7 +1465,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix8bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bRampBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int8_t *base, *revBase, *smpPtr;
 	int8_t *smpTapPtr;
@@ -1474,7 +1473,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1555,7 +1554,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1606,7 +1605,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1686,7 +1685,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -1770,7 +1769,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -1812,7 +1811,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -1854,7 +1853,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -1898,7 +1897,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -1941,7 +1940,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2008,7 +2007,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2076,7 +2075,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2118,7 +2117,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2160,7 +2159,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2198,13 +2197,13 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2240,7 +2239,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
 	int16_t *smpTapPtr;
@@ -2247,7 +2246,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2307,7 +2306,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
 	int16_t *smpTapPtr;
@@ -2314,7 +2313,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2382,7 +2381,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2425,7 +2424,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2492,7 +2491,7 @@
 	float fSample, *fMixBufferL, *fMixBufferR;
 	int32_t position;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL
 	GET_MIXER_VARS
@@ -2561,7 +2560,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2611,7 +2610,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2661,7 +2660,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2713,7 +2712,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2764,7 +2763,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2844,7 +2843,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2925,7 +2924,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -2975,7 +2974,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3025,7 +3024,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3070,7 +3069,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bRampNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bRampNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
 	float fSample, *fMixBufferL, *fMixBufferR;
@@ -3077,7 +3076,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3120,7 +3119,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bRampLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bRampLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int16_t *base, *smpPtr;
 	int16_t *smpTapPtr;
@@ -3128,7 +3127,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3200,7 +3199,7 @@
 	SET_BACK_MIXER_POS
 }
 
-static void mix16bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bRampBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
 {
 	const int16_t *base, *revBase, *smpPtr;
 	int16_t *smpTapPtr;
@@ -3208,7 +3207,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3289,7 +3288,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3340,7 +3339,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac;
+	uint64_t positionFrac;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3420,7 +3419,7 @@
 	int32_t position;
 	float fVolumeLDelta, fVolumeRDelta, fVolumeL, fVolumeR;
 	uint32_t i, samplesToMix, samplesLeft;
-	uintCPUWord_t positionFrac, tmpDelta;
+	uint64_t positionFrac, tmpDelta;
 
 	GET_VOL_RAMP
 	GET_MIXER_VARS_RAMP
@@ -3510,9 +3509,9 @@
 	(mixFunc)mix8bNoLoopLIntrp,
 	(mixFunc)mix8bLoopLIntrp,
 	(mixFunc)mix8bBidiLoopLIntrp,
-	(mixFunc)mix8bNoLoopS16Intrp,
-	(mixFunc)mix8bLoopS16Intrp,
-	(mixFunc)mix8bBidiLoopS16Intrp,
+	(mixFunc)mix8bNoLoopS32Intrp,
+	(mixFunc)mix8bLoopS32Intrp,
+	(mixFunc)mix8bBidiLoopS32Intrp,
 	(mixFunc)mix8bNoLoopCIntrp,
 	(mixFunc)mix8bLoopCIntrp,
 	(mixFunc)mix8bBidiLoopCIntrp,
@@ -3527,9 +3526,9 @@
 	(mixFunc)mix16bNoLoopLIntrp,
 	(mixFunc)mix16bLoopLIntrp,
 	(mixFunc)mix16bBidiLoopLIntrp,
-	(mixFunc)mix16bNoLoopS16Intrp,
-	(mixFunc)mix16bLoopS16Intrp,
-	(mixFunc)mix16bBidiLoopS16Intrp,
+	(mixFunc)mix16bNoLoopS32Intrp,
+	(mixFunc)mix16bLoopS32Intrp,
+	(mixFunc)mix16bBidiLoopS32Intrp,
 	(mixFunc)mix16bNoLoopCIntrp,
 	(mixFunc)mix16bLoopCIntrp,
 	(mixFunc)mix16bBidiLoopCIntrp,
@@ -3546,9 +3545,9 @@
 	(mixFunc)mix8bRampNoLoopLIntrp,
 	(mixFunc)mix8bRampLoopLIntrp,
 	(mixFunc)mix8bRampBidiLoopLIntrp,
-	(mixFunc)mix8bRampNoLoopS16Intrp,
-	(mixFunc)mix8bRampLoopS16Intrp,
-	(mixFunc)mix8bRampBidiLoopS16Intrp,
+	(mixFunc)mix8bRampNoLoopS32Intrp,
+	(mixFunc)mix8bRampLoopS32Intrp,
+	(mixFunc)mix8bRampBidiLoopS32Intrp,
 	(mixFunc)mix8bRampNoLoopCIntrp,
 	(mixFunc)mix8bRampLoopCIntrp,
 	(mixFunc)mix8bRampBidiLoopCIntrp,
@@ -3563,9 +3562,9 @@
 	(mixFunc)mix16bRampNoLoopLIntrp,
 	(mixFunc)mix16bRampLoopLIntrp,
 	(mixFunc)mix16bRampBidiLoopLIntrp,
-	(mixFunc)mix16bRampNoLoopS16Intrp,
-	(mixFunc)mix16bRampLoopS16Intrp,
-	(mixFunc)mix16bRampBidiLoopS16Intrp,
+	(mixFunc)mix16bRampNoLoopS32Intrp,
+	(mixFunc)mix16bRampLoopS32Intrp,
+	(mixFunc)mix16bRampBidiLoopS32Intrp,
 	(mixFunc)mix16bRampNoLoopCIntrp,
 	(mixFunc)mix16bRampLoopCIntrp,
 	(mixFunc)mix16bRampBidiLoopCIntrp
--- a/src/mixer/ft2_mix.h
+++ b/src/mixer/ft2_mix.h
@@ -2,20 +2,15 @@
 #define _ft2_mix_h_
 
 #include <stdint.h>
-#include "../ft2_cpu.h"
 
-#define MAX_TAPS 16
+#define MAX_TAPS 32
 #define MAX_LEFT_TAPS ((MAX_TAPS/2)-1)
 #define MAX_RIGHT_TAPS (MAX_TAPS/2)
 
 // the fractional bits are hardcoded, changing these will break things!
-#if CPU_64BIT
 #define MIXER_FRAC_BITS 32
-#else
-#define MIXER_FRAC_BITS 16
-#endif
 
-#define MIXER_FRAC_SCALE ((intCPUWord_t)1 << MIXER_FRAC_BITS)
+#define MIXER_FRAC_SCALE ((int64_t)1 << MIXER_FRAC_BITS)
 #define MIXER_FRAC_MASK (MIXER_FRAC_SCALE-1)
 
 typedef void (*mixFunc)(void *, uint32_t, uint32_t);
--- a/src/mixer/ft2_mix_macros.h
+++ b/src/mixer/ft2_mix_macros.h
@@ -21,7 +21,7 @@
 	v->fCurrVolumeR = fVolumeR;
 
 #define GET_MIXER_VARS \
-	const uintCPUWord_t delta = v->delta; \
+	const uint64_t delta = v->delta; \
 	fMixBufferL = audio.fMixBufferL + bufferPos; \
 	fMixBufferR = audio.fMixBufferR + bufferPos; \
 	position = v->position; \
@@ -28,7 +28,7 @@
 	positionFrac = v->positionFrac;
 
 #define GET_MIXER_VARS_RAMP \
-	const uintCPUWord_t delta = v->delta; \
+	const uint64_t delta = v->delta; \
 	fMixBufferL = audio.fMixBufferL + bufferPos; \
 	fMixBufferR = audio.fMixBufferR + bufferPos; \
 	fVolumeLDelta = v->fVolumeLDelta; \
@@ -131,7 +131,6 @@
 ** There is also a second special case for the left edge (negative taps) after the sample has looped once.
 */
 
-#if CUBIC_FSHIFT>=0
 #define CUBIC_SPLINE_INTERPOLATION(s, f, scale) \
 { \
 	const float *t = fCubicSplineLUT + (((uint32_t)(f) >> CUBIC_SPLINE_FSHIFT) & CUBIC_SPLINE_FMASK); \
@@ -140,16 +139,6 @@
 	           ( s[1] * t[2]) + \
 	           ( s[2] * t[3])) * (1.0f / scale); \
 }
-#else
-#define CUBIC_SPLINE_INTERPOLATION(s, f, scale) \
-{ \
-	const float *t = fCubicSplineLUT + (((uint32_t)(f) << -CUBIC_SPLINE_FSHIFT) & CUBIC_SPLINE_FMASK); \
-	fSample = ((s[-1] * t[0]) + \
-	           ( s[0] * t[1]) + \
-	           ( s[1] * t[2]) + \
-	           ( s[2] * t[3])) * (1.0f / scale); \
-}
-#endif
 
 #define RENDER_8BIT_SMP_CINTRP \
 	CUBIC_SPLINE_INTERPOLATION(smpPtr, positionFrac, 128) \
@@ -191,7 +180,6 @@
 ** There is also a second special case for the left edge (negative taps) after the sample has looped once.
 */
 
-#if SINC8_FSHIFT>=0
 #define WINDOWED_SINC8_INTERPOLATION(s, f, scale) \
 { \
 	const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC8_FSHIFT) & SINC8_FMASK); \
@@ -204,22 +192,7 @@
 	           ( s[3] * t[6]) + \
 	           ( s[4] * t[7])) * (1.0f / scale); \
 }
-#else
-#define WINDOWED_SINC8_INTERPOLATION(s, f, scale) \
-{ \
-	const float *t = v->fSincLUT + (((uint32_t)(f) << -SINC8_FSHIFT) & SINC8_FMASK); \
-	fSample = ((s[-3] * t[0]) + \
-	           (s[-2] * t[1]) + \
-	           (s[-1] * t[2]) + \
-	           ( s[0] * t[3]) + \
-	           ( s[1] * t[4]) + \
-	           ( s[2] * t[5]) + \
-	           ( s[3] * t[6]) + \
-	           ( s[4] * t[7])) * (1.0f / scale); \
-}
-#endif
 
-#if SINC16_FSHIFT>=0
 #define WINDOWED_SINC16_INTERPOLATION(s, f, scale) \
 { \
 	const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC16_FSHIFT) & SINC16_FMASK); \
@@ -315,20 +288,13 @@
 /*                      SAMPLES-TO-MIX LIMITING MACROS                     */
 /* ----------------------------------------------------------------------- */
 
-#if CPU_64BIT
-#define LIMIT_NUM
-#else
-#define LIMIT_NUM if (i > (1<<(32-MIXER_FRAC_BITS))-1) i = (1<<(32-MIXER_FRAC_BITS))-1;
-#endif
-
 #define LIMIT_MIX_NUM \
 	samplesToMix = INT32_MAX; \
 	if (v->delta != 0) \
 	{ \
 		i = (v->sampleEnd - 1) - position; \
-		LIMIT_NUM \
-		const uintCPUWord_t dividend = ((uintCPUWord_t)i << MIXER_FRAC_BITS) | ((uint32_t)positionFrac ^ MIXER_FRAC_MASK); \
-		samplesToMix = (uint32_t)(dividend / (uintCPUWord_t)v->delta) + 1; \
+		const uint64_t dividend = ((uint64_t)i << MIXER_FRAC_BITS) | ((uint32_t)positionFrac ^ MIXER_FRAC_MASK); \
+		samplesToMix = (uint32_t)(dividend / (uint64_t)v->delta) + 1; \
 	} \
 	\
 	if (samplesToMix > samplesLeft) \
@@ -348,7 +314,7 @@
 		smpPtr = base + position; \
 	} \
 	\
-	const int32_t deltaHi = (intCPUWord_t)tmpDelta >> MIXER_FRAC_BITS; \
+	const int32_t deltaHi = (int64_t)tmpDelta >> MIXER_FRAC_BITS; \
 	const uint32_t deltaLo = tmpDelta & MIXER_FRAC_MASK;
 
 #define LIMIT_MIX_NUM_RAMP \
--- a/src/mixer/ft2_silence_mix.c
+++ b/src/mixer/ft2_silence_mix.c
@@ -1,6 +1,5 @@
 #include <stdint.h>
 #include "../ft2_audio.h"
-#include "../ft2_cpu.h"
 
 // used for the audio channel mixer when voice volume is zero
 
@@ -9,12 +8,12 @@
 	const uint64_t samplesToMix = (uint64_t)v->delta * (uint32_t)numSamples; // fixed-point
 
 	const uint32_t samples = (uint32_t)(samplesToMix >> MIXER_FRAC_BITS);
-	const uintCPUWord_t samplesFrac = (samplesToMix & MIXER_FRAC_MASK) + v->positionFrac;
+	const uint64_t samplesFrac = (samplesToMix & MIXER_FRAC_MASK) + v->positionFrac;
 
 	uint32_t position = v->position + samples + (uint32_t)(samplesFrac >> MIXER_FRAC_BITS);
-	uintCPUWord_t positionFrac = samplesFrac & MIXER_FRAC_MASK;
+	uint64_t positionFrac = samplesFrac & MIXER_FRAC_MASK;
 
-	if (position < (unsigned)v->sampleEnd) // we haven't reached the sample's end yet
+	if (position < (uint32_t)v->sampleEnd) // we haven't reached the sample's end yet
 	{
 		v->positionFrac = positionFrac;
 		v->position = position;
--- a/src/mixer/ft2_windowed_sinc.c
+++ b/src/mixer/ft2_windowed_sinc.c
@@ -1,7 +1,5 @@
-/* Code taken from the OpenMPT project, which has a BSD license which is
-** compatible with this project.
-**
-** The code has been slightly modified.
+/* The code in this file is based on code from the OpenMPT project,
+** which shares the same coding license as this project.
 */
 
 #include <stdint.h>
@@ -16,23 +14,23 @@
 // globalized
 float *fKaiserSinc_8 = NULL, *fDownSample1_8 = NULL, *fDownSample2_8 = NULL;
 float *fKaiserSinc_16 = NULL, *fDownSample1_16 = NULL, *fDownSample2_16 = NULL;
+uint64_t sincDownsample1Ratio, sincDownsample2Ratio;
 
 // set based on selected sinc interpolator (8 point or 16 point)
 float *fKaiserSinc = NULL, *fDownSample1 = NULL, *fDownSample2 = NULL;
 
-static double Izero(double y) // Compute Bessel function Izero(y) using a series approximation
+// zeroth-order modified Bessel function of the first kind (series approximation)
+static double besselI0(double z)
 {
-	double s = 1.0, ds = 1.0, d = 0.0;
+	double s = 1.0, ds = 1.0, d = 2.0;
 
-	const double epsilon = 1E-9; // 8bitbubsy: 1E-7 -> 1E-9 for added precision (still fast to calculate)
-
 	do
 	{
-		d = d + 2.0;
-		ds = ds * (y * y) / (d * d);
-		s = s + ds;
+		ds *= (z * z) / (d * d);
+		s += ds;
+		d += 2.0;
 	}
-	while (ds > epsilon * s);
+	while (ds > s*1E-15);
 
 	return s;
 }
@@ -39,7 +37,7 @@
 
 static void getSinc(uint32_t numTaps, float *fLUTPtr, const double beta, const double cutoff)
 {
-	const double izeroBeta = Izero(beta);
+	const double I0Beta = besselI0(beta);
 	const double kPi = MY_PI * cutoff;
 
 	const uint32_t length = numTaps * SINC_PHASES;
@@ -50,18 +48,16 @@
 
 	for (uint32_t i = 0; i < length; i++)
 	{
-		const int32_t ix = ((tapsMinus1 - (i & tapsMinus1)) * SINC_PHASES) + (i >> tapBits);
+		const int32_t ix = ((tapsMinus1 - (i & tapsMinus1)) << SINC_PHASES_BITS) + (i >> tapBits);
 
-		double dSinc;
-		if (ix == midTap)
+		double dSinc = 1.0;
+		if (ix != midTap)
 		{
-			dSinc = 1.0;
-		}
-		else
-		{
 			const double x = (ix - midTap) * (1.0 / SINC_PHASES);
 			const double xPi = x * kPi;
-			dSinc = sin(xPi) * Izero(beta * sqrt(1.0 - x * x * xMul)) / (izeroBeta * xPi); // Kaiser window
+
+			// sinc with Kaiser window
+			dSinc = (sin(xPi) * besselI0(beta * sqrt(1.0 - (x * x * xMul)))) / (I0Beta * xPi);
 		}
 
 		fLUTPtr[i] = (float)(dSinc * cutoff);
@@ -68,15 +64,25 @@
 	}
 }
 
+static double dBToKaiserBeta(double dB)
+{
+	if (dB < 21.0)
+		return 0.0;
+	else if (dB <= 50.0)
+		return 0.5842 * pow(dB - 21.0, 0.4) + 0.07886 * (dB - 21.0);
+	else
+		return 0.1102 * (dB - 8.7);
+}
+
 bool calcWindowedSincTables(void)
-{ 
-	fKaiserSinc_8  = (float *)malloc(8*SINC_PHASES * sizeof (float));
-	fDownSample1_8 = (float *)malloc(8*SINC_PHASES * sizeof (float));
-	fDownSample2_8 = (float *)malloc(8*SINC_PHASES * sizeof (float));
+{
+	fKaiserSinc_8  = (float *)malloc(SINC1_TAPS*SINC_PHASES * sizeof (float));
+	fDownSample1_8 = (float *)malloc(SINC1_TAPS*SINC_PHASES * sizeof (float));
+	fDownSample2_8 = (float *)malloc(SINC1_TAPS*SINC_PHASES * sizeof (float));
 
-	fKaiserSinc_16  = (float *)malloc(16*SINC_PHASES * sizeof (float));
-	fDownSample1_16 = (float *)malloc(16*SINC_PHASES * sizeof (float));
-	fDownSample2_16 = (float *)malloc(16*SINC_PHASES * sizeof (float));
+	fKaiserSinc_16  = (float *)malloc(SINC2_TAPS*SINC_PHASES * sizeof (float));
+	fDownSample1_16 = (float *)malloc(SINC2_TAPS*SINC_PHASES * sizeof (float));
+	fDownSample2_16 = (float *)malloc(SINC2_TAPS*SINC_PHASES * sizeof (float));
 
 	if (fKaiserSinc_8  == NULL || fDownSample1_8  == NULL || fDownSample2_8  == NULL ||
 		fKaiserSinc_16 == NULL || fDownSample1_16 == NULL || fDownSample2_16 == NULL)
@@ -85,13 +91,23 @@
 		return false;
 	}
 
-	getSinc(8, fKaiserSinc_8, 9.6377, 1.0);
-	getSinc(8, fDownSample1_8, 8.5, 0.5);
-	getSinc(8, fDownSample2_8, 7.3, 0.425);
+	sincDownsample1Ratio = (uint64_t)(1.1875 * MIXER_FRAC_SCALE);
+	sincDownsample2Ratio = (uint64_t)(1.5    * MIXER_FRAC_SCALE);
 
-	getSinc(16, fKaiserSinc_16, 9.6377, 1.0);
-	getSinc(16, fDownSample1_16, 8.5, 0.5);
-	getSinc(16, fDownSample2_16, 7.3, 0.425);
+	// sidelobe attenuation (Kaiser beta)
+	const double b0 = dBToKaiserBeta(96.15645);
+	const double b1 = dBToKaiserBeta(85.83249);
+	const double b2 = dBToKaiserBeta(72.22088);
+
+	// 8 point
+	getSinc(SINC1_TAPS, fKaiserSinc_8,  b0, 1.0);
+	getSinc(SINC1_TAPS, fDownSample1_8, b1, 0.5);
+	getSinc(SINC1_TAPS, fDownSample2_8, b2, 0.425);
+
+	// 16 point
+	getSinc(SINC2_TAPS, fKaiserSinc_16,  b0, 1.0);
+	getSinc(SINC2_TAPS, fDownSample1_16, b1, 0.5);
+	getSinc(SINC2_TAPS, fDownSample2_16, b2, 0.425);
 
 	return true;
 }
--- a/src/mixer/ft2_windowed_sinc.h
+++ b/src/mixer/ft2_windowed_sinc.h
@@ -10,17 +10,22 @@
 #define SINC_PHASES_BITS 13 // log2(SINC_PHASES)
 
 // do not change these!
-#define SINC8_WIDTH_BITS 3 // log2(8)
+
+#define SINC1_TAPS 8
+#define SINC8_WIDTH_BITS 3 // log2(SINC1_TAPS)
 #define SINC8_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC8_WIDTH_BITS))
-#define SINC8_FMASK ((8*SINC_PHASES)-8)
-#define SINC16_WIDTH_BITS 4 // log2(16)
+#define SINC8_FMASK ((SINC1_TAPS*SINC_PHASES)-SINC1_TAPS)
+
+#define SINC2_TAPS 16
+#define SINC16_WIDTH_BITS 4 // log2(SINC2_TAPS)
 #define SINC16_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC16_WIDTH_BITS))
-#define SINC16_FMASK ((16*SINC_PHASES)-16)
+#define SINC16_FMASK ((SINC2_TAPS*SINC_PHASES)-SINC2_TAPS)
 
 extern float *fKaiserSinc_8, *fDownSample1_8, *fDownSample2_8;
 extern float *fKaiserSinc_16, *fDownSample1_16, *fDownSample2_16;
 
 extern float *fKaiserSinc, *fDownSample1, *fDownSample2;
+extern uint64_t sincDownsample1Ratio, sincDownsample2Ratio;
 
 bool calcWindowedSincTables(void);
 void freeWindowedSincTables(void);
--- /dev/null
+++ b/src/modloaders/ft2_load_bem.c
@@ -1,0 +1,404 @@
+/* BEM (UN05, MikMod) loader. Supports modules converted from XM only!
+**
+** Note: Data sanitation is done in the last stage
+** of module loading, so you don't need to do that here.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "../ft2_header.h"
+#include "../ft2_module_loader.h"
+#include "../ft2_sample_ed.h"
+#include "../ft2_sysreqs.h"
+
+#define MAX_TRACKS (256*32)
+
+#define FLAG_XMPERIODS 1
+#define FLAG_LINEARSLIDES 2
+
+#ifdef _MSC_VER // please don't mess with these structs!
+#pragma pack(push)
+#pragma pack(1)
+#endif
+typedef struct bemHdr_t
+{
+	char id[4];
+	uint8_t numchn;
+	uint16_t numpos;
+	uint16_t reppos;
+	uint16_t numpat;
+	uint16_t numtrk;
+	uint16_t numins;
+	uint8_t initspeed;
+	uint8_t inittempo;
+	uint8_t positions[256];
+	uint8_t panning[32];
+	uint8_t flags;
+}
+#ifdef __GNUC__
+__attribute__((packed))
+#endif
+bemHdr_t;
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+
+enum
+{
+	UNI_NOTE = 1,
+	UNI_INSTRUMENT,
+	UNI_PTEFFECT0,
+	UNI_PTEFFECT1,
+	UNI_PTEFFECT2,
+	UNI_PTEFFECT3,
+	UNI_PTEFFECT4,
+	UNI_PTEFFECT5,
+	UNI_PTEFFECT6,
+	UNI_PTEFFECT7,
+	UNI_PTEFFECT8,
+	UNI_PTEFFECT9,
+	UNI_PTEFFECTA,
+	UNI_PTEFFECTB,
+	UNI_PTEFFECTC,
+	UNI_PTEFFECTD,
+	UNI_PTEFFECTE,
+	UNI_PTEFFECTF,
+	UNI_S3MEFFECTA,
+	UNI_S3MEFFECTD,
+	UNI_S3MEFFECTE,
+	UNI_S3MEFFECTF,
+	UNI_S3MEFFECTI,
+	UNI_S3MEFFECTQ,
+	UNI_S3MEFFECTT,
+	UNI_XMEFFECTA,
+	UNI_XMEFFECTG,
+	UNI_XMEFFECTH,
+	UNI_XMEFFECTP,
+
+	UNI_LAST
+};
+
+static const uint8_t xmEfxTab[] = { 10, 16, 17, 25 }; // A, G, H, P
+
+static char *readString(FILE *f)
+{
+	uint16_t length;
+	fread(&length, 2, 1, f);
+
+	char *out = (char *)malloc(length+1);
+	if (out == NULL)
+		return NULL;
+
+	fread(out, 1, length, f);
+	out[length] = '\0';
+
+	return out;
+}
+
+bool detectBEM(FILE *f)
+{
+	if (f == NULL) return false;
+
+	uint32_t oldPos = (uint32_t)ftell(f);
+
+	fseek(f, 0, SEEK_SET);
+	char ID[64];
+	memset(ID, 0, sizeof (ID));
+	fread(ID, 1, 4, f);
+	if (memcmp(ID, "UN05", 4) != 0)
+		goto error;
+
+	fseek(f, 0x131, SEEK_SET);
+	if (feof(f))
+		goto error;
+
+	uint8_t flags = (uint8_t)fgetc(f);
+	if ((flags & FLAG_XMPERIODS) == 0)
+		goto error;
+
+	fseek(f, 0x132, SEEK_SET);
+	if (feof(f))
+		goto error;
+
+	uint16_t strLength = 0;
+	fread(&strLength, 2, 1, f);
+	if (strLength == 0 || strLength > 512)
+		goto error;
+
+	fseek(f, strLength+2, SEEK_CUR);
+	if (feof(f))
+		goto error;
+
+	fread(ID, 1, 64, f);
+	if (memcmp(ID, "FastTracker v2.00", 17) != 0)
+		goto error;
+
+	fseek(f, oldPos, SEEK_SET);
+	return true;
+
+error:
+	fseek(f, oldPos, SEEK_SET);
+	return false;
+}
+
+bool loadBEM(FILE *f, uint32_t filesize)
+{
+	bemHdr_t h;
+
+	if (filesize < sizeof (h))
+	{
+		loaderMsgBox("Error: This file is either not a module, or is not supported.");
+		return false;
+	}
+
+	fread(&h, 1, sizeof (bemHdr_t), f);
+
+	char *songName = readString(f);
+	if (songName == NULL)
+		return false;
+
+	strcpy(songTmp.name, songName);
+	free(songName);
+	uint16_t strLength;
+	fread(&strLength, 2, 1, f);
+	fseek(f, strLength, SEEK_CUR);
+	fread(&strLength, 2, 1, f);
+	fseek(f, strLength, SEEK_CUR);
+
+	if (h.numpos > 256 || h.numpat > 256 || h.numchn > 32 || h.numtrk > MAX_TRACKS)
+	{
+		loaderMsgBox("Error loading BEM: The module is corrupt!");
+		return false;
+	}
+
+	tmpLinearPeriodsFlag = !!(h.flags & FLAG_LINEARSLIDES);
+
+	songTmp.numChannels = h.numchn;
+	songTmp.songLength = h.numpos;
+	songTmp.songLoopStart = h.reppos;
+	songTmp.BPM = h.inittempo;
+	songTmp.speed = h.initspeed;
+	
+	memcpy(songTmp.orders, h.positions, 256);
+
+	// load instruments
+	for (int16_t i = 0; i < h.numins; i++)
+	{
+		if (!allocateTmpInstr(1 + i))
+		{
+			loaderMsgBox("Not enough memory!");
+			return false;
+		}
+
+		instr_t *ins = instrTmp[1 + i];
+
+		ins->numSamples = (uint8_t)fgetc(f);
+		fread(ins->note2SampleLUT, 1, 96, f);
+
+		ins->volEnvFlags = (uint8_t)fgetc(f);
+		ins->volEnvLength = (uint8_t)fgetc(f);
+		ins->volEnvSustain = (uint8_t)fgetc(f);
+		ins->volEnvLoopStart = (uint8_t)fgetc(f);
+		ins->volEnvLoopEnd = (uint8_t)fgetc(f);
+		fread(ins->volEnvPoints, 2, 12*2, f);
+
+		ins->panEnvFlags = (uint8_t)fgetc(f);
+		ins->panEnvLength = (uint8_t)fgetc(f);
+		ins->panEnvSustain = (uint8_t)fgetc(f);
+		ins->panEnvLoopStart = (uint8_t)fgetc(f);
+		ins->panEnvLoopEnd = (uint8_t)fgetc(f);
+		fread(ins->panEnvPoints, 2, 12*2, f);
+
+		ins->autoVibType = (uint8_t)fgetc(f);
+		ins->autoVibSweep = (uint8_t)fgetc(f);
+		ins->autoVibDepth = (uint8_t)fgetc(f);
+		ins->autoVibRate = (uint8_t)fgetc(f);
+		fread(&ins->fadeout, 2, 1, f);
+
+		char *insName = readString(f);
+		if (insName == NULL)
+			return false;
+
+		uint32_t insNameLen = (uint32_t)strlen(insName);
+		if (insNameLen > 22)
+			insNameLen = 22;
+
+		memcpy(songTmp.instrName[1+i], insName, insNameLen);
+		free(insName);
+
+		for (int32_t j = 0; j < ins->numSamples; j++)
+		{
+			sample_t *s = &ins->smp[j];
+
+			s->finetune = (int8_t)fgetc(f) ^ 0x80;
+			fseek(f, 1, SEEK_CUR);
+			s->relativeNote = (int8_t)fgetc(f);
+			s->volume = (uint8_t)fgetc(f);
+			s->panning = (uint8_t)fgetc(f);
+			fread(&s->length, 4, 1, f);
+			fread(&s->loopStart, 4, 1, f);
+			uint32_t loopEnd;
+			fread(&loopEnd, 4, 1, f);
+			s->loopLength = loopEnd - s->loopStart;
+
+			uint16_t flags;
+			fread(&flags, 2, 1, f);
+			if (flags &  1) s->flags |= SAMPLE_16BIT;
+			if (flags & 16) s->flags |= LOOP_FWD;
+			if (flags & 32) s->flags |= LOOP_BIDI;
+
+			char *smpName = readString(f);
+			if (smpName == NULL)
+				return false;
+			
+			uint32_t smpNameLen = (uint32_t)strlen(smpName);
+			if (smpNameLen > 22)
+				smpNameLen = 22;
+
+			memcpy(s->name, smpName, smpNameLen);
+			free(smpName);
+		}
+	}
+
+	// load tracks
+
+	uint16_t rowsInPattern[256];
+	uint16_t trackList[256*32];
+	fread(rowsInPattern, 2, h.numpat, f);
+	fread(trackList, 2, h.numpat * h.numchn, f);
+
+	note_t *decodedTrack[MAX_TRACKS];
+	for (int32_t i = 0; i < h.numtrk; i++)
+	{
+		uint16_t trackBytesInFile;
+		fread(&trackBytesInFile, 2, 1, f);
+		if (trackBytesInFile == 0)
+		{
+			loaderMsgBox("Error loading BEM: This module is corrupt!");
+trackError:
+			for (int32_t j = 0; j < i; j++)
+				free(decodedTrack[j]);
+
+			return false;
+		}
+
+		decodedTrack[i] = (note_t *)calloc(rowsInPattern[i], sizeof (note_t));
+		if (decodedTrack[i] == NULL)
+		{
+			loaderMsgBox("Not enough memory!");
+			goto trackError;
+		}
+
+		note_t *out = decodedTrack[i];
+
+		// decode track
+
+		uint32_t trackPosInFile = (uint32_t)ftell(f);
+		while ((uint32_t)ftell(f) < trackPosInFile+trackBytesInFile)
+		{
+			uint8_t byte = (uint8_t)fgetc(f);
+			if (byte == 0)
+				break; // end of track
+
+			uint8_t repeat = byte >> 5;
+			uint8_t opcodeBytes = (byte & 0x1F) - 1;
+
+			uint32_t opcodeStart = (uint32_t)ftell(f);
+			uint32_t opcodeEnd = opcodeStart + opcodeBytes;
+
+			for (int32_t j = 0; j <= repeat; j++, out++)
+			{
+				fseek(f, opcodeStart, SEEK_SET);
+				while ((uint32_t)ftell(f) < opcodeEnd)
+				{
+					uint8_t opcode = (uint8_t)fgetc(f);
+
+					if (opcode == 0)
+						break;
+
+					if (opcode == UNI_NOTE)
+					{
+						out->note = 1 + (uint8_t)fgetc(f);
+					}
+					else if (opcode == UNI_INSTRUMENT)
+					{
+						out->instr = 1 + (uint8_t)fgetc(f);
+					}
+					else if (opcode >= UNI_PTEFFECT0 && opcode <= UNI_PTEFFECTF) // PT effects
+					{
+						out->efx = opcode - UNI_PTEFFECT0;
+						out->efxData = (uint8_t)fgetc(f);
+					}
+					else if (opcode >= UNI_XMEFFECTA && opcode <= UNI_XMEFFECTP) // XM effects
+					{
+						out->efx = xmEfxTab[opcode-UNI_XMEFFECTA];
+						out->efxData = (uint8_t)fgetc(f);
+					}
+					else
+					{
+						if (opcode >= UNI_LAST) // illegal opcode
+						{
+							loaderMsgBox("Error loading BEM: illegal pattern opcode!");
+							goto trackError;
+						}
+
+						// unsupported opcode, skip it
+						if (opcode > 0)
+							fseek(f, 1, SEEK_CUR);
+					}
+				}
+			}
+		}
+	}
+
+	// create patterns from tracks
+	for (int32_t i = 0; i < h.numpat; i++)
+	{
+		uint16_t numRows = rowsInPattern[i];
+		if (numRows == 0 || numRows > 256)
+			continue;
+
+		if (!allocateTmpPatt(i, numRows))
+		{
+			loaderMsgBox("Not enough memory!");
+			return false;
+		}
+
+		note_t *dst = patternTmp[i];
+		for (int32_t j = 0; j < h.numchn; j++)
+		{
+			note_t *src = (note_t *)decodedTrack[trackList[(i * h.numchn) + j]];
+			if (src != NULL)
+			{
+				for (int32_t k = 0; k < numRows; k++)
+					dst[(k * MAX_CHANNELS) + j] = src[k];
+			}
+		}
+	}
+
+	// load sample data
+	for (int32_t i = 0; i < h.numins; i++)
+	{
+		instr_t *ins = instrTmp[1 + i];
+		if (ins == NULL)
+			continue;
+
+		for (int32_t j = 0; j < ins->numSamples; j++)
+		{
+			sample_t *s = &ins->smp[j];
+
+			bool sampleIs16Bit = !!(s->flags & SAMPLE_16BIT);
+			if (!allocateSmpData(s, s->length, sampleIs16Bit))
+			{
+				loaderMsgBox("Not enough memory!");
+				return false;
+			}
+
+			fread(s->dataPtr, 1 + sampleIs16Bit, s->length, f);
+			delta2Samp(s->dataPtr, s->length, s->flags);
+		}
+	}
+
+	return true;
+}
--- a/src/scopes/ft2_scopedraw.c
+++ b/src/scopes/ft2_scopedraw.c
@@ -3,7 +3,6 @@
 #include "ft2_scopes.h"
 #include "ft2_scopedraw.h"
 #include "ft2_scope_macros.h"
-#include "../ft2_cpu.h"
 
 static void scopeLine(int32_t x1, int32_t y1, int32_t y2);
 
--- a/src/scopes/ft2_scopes.h
+++ b/src/scopes/ft2_scopes.h
@@ -5,21 +5,11 @@
 #include <stdbool.h>
 #include "../ft2_header.h"
 #include "../ft2_audio.h"
-#include "../ft2_cpu.h"
 
 #define SCOPE_HEIGHT 36
 
-#if CPU_64BIT
 #define SCOPE_FRAC_BITS 32
-#else
-/* Max safe amount of fracbits for uint32_t on scopes @ 64Hz.
-** Since the scopes deltas are always high'ish, 13-bit
-** fractional precision is OK.
-*/
-#define SCOPE_FRAC_BITS 13
-#endif
-
-#define SCOPE_FRAC_SCALE ((intCPUWord_t)1 << SCOPE_FRAC_BITS)
+#define SCOPE_FRAC_SCALE ((int64_t)1 << SCOPE_FRAC_BITS)
 #define SCOPE_FRAC_MASK (SCOPE_FRAC_SCALE-1)
 
 int32_t getSamplePosition(uint8_t ch);
@@ -39,7 +29,7 @@
 	bool wasCleared, sample16Bit;
 	uint8_t loopType;
 	int32_t volume, direction, loopStart, loopLength, sampleEnd, position;
-	uintCPUWord_t delta, positionFrac;
+	uint64_t delta, positionFrac;
 } scope_t;
 
 typedef struct lastChInstr_t
--- a/vs2019_project/ft2-clone/ft2-clone.vcxproj
+++ b/vs2019_project/ft2-clone/ft2-clone.vcxproj
@@ -361,6 +361,7 @@
     <ClCompile Include="..\..\src\modloaders\ft2_load_s3m.c" />
     <ClCompile Include="..\..\src\modloaders\ft2_load_stk.c" />
     <ClCompile Include="..\..\src\modloaders\ft2_load_stm.c" />
+    <ClCompile Include="..\..\src\modloaders\ft2_load_bem.c" />
     <ClCompile Include="..\..\src\modloaders\ft2_load_xm.c" />
     <ClCompile Include="..\..\src\rtmidi\RtMidi.cpp">
       <ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Sync</ExceptionHandling>
@@ -389,7 +390,6 @@
     <ClInclude Include="..\..\src\ft2_bmp.h" />
     <ClInclude Include="..\..\src\ft2_checkboxes.h" />
     <ClInclude Include="..\..\src\ft2_config.h" />
-    <ClInclude Include="..\..\src\ft2_cpu.h" />
     <ClInclude Include="..\..\src\ft2_diskop.h" />
     <ClInclude Include="..\..\src\ft2_edit.h" />
     <ClInclude Include="..\..\src\ft2_events.h" />
--- a/vs2019_project/ft2-clone/ft2-clone.vcxproj.filters
+++ b/vs2019_project/ft2-clone/ft2-clone.vcxproj.filters
@@ -164,6 +164,9 @@
     <ClCompile Include="..\..\src\mixer\ft2_cubic_spline.c">
       <Filter>mixer</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\modloaders\ft2_load_bem.c">
+      <Filter>modloaders</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\src\rtmidi\RtMidi.h">
@@ -315,9 +318,6 @@
     </ClInclude>
     <ClInclude Include="..\..\src\scopes\ft2_scopes.h">
       <Filter>scopes</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\src\ft2_cpu.h">
-      <Filter>headers</Filter>
     </ClInclude>
     <ClInclude Include="..\..\src\ft2_hpc.h">
       <Filter>headers</Filter>
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_assert.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_assert.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_atomic.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_atomic.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -209,7 +209,7 @@
 #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_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__)
 #ifdef __thumb__
 /* The mcr instruction isn't available in thumb mode, use real functions */
 #define SDL_MEMORY_BARRIER_USES_FUNCTION
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_audio.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_audio.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_bits.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_bits.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_blendmode.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_blendmode.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -65,8 +65,8 @@
 typedef enum
 {
     SDL_BLENDOPERATION_ADD              = 0x1,  /**< dst + src: supported by all renderers */
-    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
-    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
     SDL_BLENDOPERATION_MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D9, D3D11 */
     SDL_BLENDOPERATION_MAXIMUM          = 0x5   /**< max(dst, src) : supported by D3D9, D3D11 */
 } SDL_BlendOperation;
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_clipboard.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_clipboard.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_config.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_config.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_cpuinfo.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_cpuinfo.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_egl.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_egl.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_endian.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_endian.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_error.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_error.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_events.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_events.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -131,6 +131,8 @@
     SDL_CONTROLLERTOUCHPADMOTION,      /**< Game controller touchpad finger was moved */
     SDL_CONTROLLERTOUCHPADUP,          /**< Game controller touchpad finger was lifted */
     SDL_CONTROLLERSENSORUPDATE,        /**< Game controller sensor was updated */
+    SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3,
+    SDL_CONTROLLERSTEAMHANDLEUPDATED,  /**< Game controller Steam handle has changed */
 
     /* Touch events */
     SDL_FINGERDOWN      = 0x700,
@@ -446,7 +448,7 @@
  */
 typedef struct SDL_ControllerDeviceEvent
 {
-    Uint32 type;        /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
+    Uint32 type;        /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */
     Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
     Sint32 which;       /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
 } SDL_ControllerDeviceEvent;
@@ -579,15 +581,6 @@
     Uint32 type;        /**< ::SDL_QUIT */
     Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
 } SDL_QuitEvent;
-
-/**
- *  \brief OS Specific event
- */
-typedef struct SDL_OSEvent
-{
-    Uint32 type;        /**< ::SDL_QUIT */
-    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
-} SDL_OSEvent;
 
 /**
  *  \brief A user-defined event type (event.user.*)
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_filesystem.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_filesystem.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -64,7 +64,7 @@
  * directory of the application as it is uncommon to store resources outside
  * the executable. As such it is not a writable directory.
  *
- * The returned path is guaranteed to end with a path separator ('\' on
+ * The returned path is guaranteed to end with a path separator ('\\' on
  * Windows, '/' on most other platforms).
  *
  * The pointer returned is owned by the caller. Please call SDL_free() on the
@@ -120,7 +120,7 @@
  * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
  *   Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
  *
- * The returned path is guaranteed to end with a path separator ('\' on
+ * The returned path is guaranteed to end with a path separator ('\\' on
  * Windows, '/' on most other platforms).
  *
  * The pointer returned is owned by the caller. Please call SDL_free() on the
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_gamecontroller.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_gamecontroller.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -73,7 +73,8 @@
     SDL_CONTROLLER_TYPE_NVIDIA_SHIELD,
     SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT,
     SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT,
-    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
+    SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR,
+    SDL_CONTROLLER_TYPE_MAX
 } SDL_GameControllerType;
 
 typedef enum
@@ -524,6 +525,20 @@
 extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
 
 /**
+ * Get the Steam Input handle of an opened controller, if available.
+ *
+ * Returns an InputHandle_t for the controller that can be used with Steam Input API:
+ * https://partner.steamgames.com/doc/api/ISteamInput
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the gamepad handle, or 0 if unavailable.
+ *
+ * \since This function is available since SDL 2.30.0.
+ */
+extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller);
+
+
+/**
  * Check if a controller has been opened and is currently connected.
  *
  * \param gamecontroller a game controller identifier previously returned by
@@ -598,7 +613,9 @@
  *  and are centered within ~8000 of zero, though advanced UI will allow users to set
  *  or autodetect the dead zone, which varies between controllers.
  *
- *  Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX.
+ *  Trigger axis values range from 0 (released) to SDL_JOYSTICK_AXIS_MAX
+ *  (fully pressed) when reported by SDL_GameControllerGetAxis(). Note that this is not the
+ *  same range that will be reported by the lower-level SDL_GetJoystickAxis().
  */
 typedef enum
 {
@@ -687,8 +704,13 @@
  *
  * The axis indices start at index 0.
  *
- * The state is a value ranging from -32768 to 32767. Triggers, however, range
- * from 0 to 32767 (they never return a negative value).
+ * For thumbsticks, the state is a value ranging from -32768 (up/left)
+ * to 32767 (down/right).
+ *
+ * Triggers range from 0 when released to 32767 when fully pressed, and
+ * never return a negative value. Note that this differs from the value
+ * reported by the lower-level SDL_GetJoystickAxis(), which normally uses
+ * the full range.
  *
  * \param gamecontroller a game controller
  * \param axis an axis index (one of the SDL_GameControllerAxis values)
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_gesture.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_gesture.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_guid.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_guid.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_haptic.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_haptic.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_hidapi.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_hidapi.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_hints.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_hints.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -632,6 +632,110 @@
 #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
 
 /**
+ *  A variable containing a list of arcade stick style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of devices that should not be considerd joysticks.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES"
+
+/**
+ *  A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of flightstick style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of devices known to have a GameCube form factor.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES"
+
+/**
+ *  A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED"
+
+/**
  *  \brief  A variable controlling whether the HIDAPI joystick drivers should be used.
  *
  *  This variable can be set to the following values:
@@ -840,6 +944,17 @@
 #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM"
 
 /**
+ *  \brief  A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller 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_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK"
+
+/**
  *  \brief  A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used.
  *
  *  This variable can be set to the following values:
@@ -966,6 +1081,24 @@
 #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED"
 
 /**
+  *  A variable controlling whether IOKit should be used for controller handling.
+  *
+  *  This variable can be set to the following values:
+  *    "0"       - IOKit is not used
+  *    "1"       - IOKit is used (the default)
+  */
+#define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT"
+
+/**
+  *  A variable controlling whether GCController should be used for controller handling.
+  *
+  *  This variable can be set to the following values:
+  *    "0"       - GCController is not used
+  *    "1"       - GCController is used (the default)
+  */
+#define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI"
+
+/**
   *  \brief  A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices.
   *
   *  This variable can be set to the following values:
@@ -1008,6 +1141,32 @@
 #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
 
 /**
+ *  A variable containing a list of throttle style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED"
+
+/**
   *  \brief  A variable controlling whether Windows.Gaming.Input should be used for controller handling.
   *
   *  This variable can be set to the following values:
@@ -1017,6 +1176,45 @@
 #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI"
 
 /**
+ *  A variable containing a list of wheel style controllers.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES"
+
+/**
+ *  A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED"
+
+/**
+ *  A variable containing a list of devices known to have all axes centered at zero.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES"
+
+/**
  * \brief Determines whether SDL enforces that DRM master is required in order
  *        to initialize the KMSDRM video backend.
  *
@@ -1085,6 +1283,22 @@
 #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES"
 
 /**
+ *  \brief A variable controlling the default SDL log levels.
+ *
+ *  This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications.
+ *
+ *  The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category.
+ *
+ *  The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category.
+ *
+ *  You can omit the category if you want to set the logging level for all categories.
+ *
+ *  If this hint isn't set, the default log levels are equivalent to:
+ *  "app=info,assert=warn,test=verbose,*=error"
+ */
+#define SDL_HINT_LOGGING   "SDL_LOGGING"
+
+/**
 *  \brief  When set don't force the SDL app to become a foreground process
 *
 *  This hint only applies to Mac OS X.
@@ -1486,6 +1700,32 @@
 #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"
 
 /**
+ *  A variable containing a list of ROG gamepad capable mice.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE"
+
+/**
+ *  A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list.
+ *
+ *  The format of the string is a comma separated list of USB VID/PID pairs
+ *  in hexadecimal form, e.g.
+ *
+ *      0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ *  The variable can also take the form of @file, in which case the named
+ *  file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED"
+
+/**
  *  \brief  A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
  *
  *  This variable can be set to the following values:
@@ -2441,6 +2681,22 @@
  *  This hint is available since SDL 2.24.0.
  */
 #define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY"
+
+/**
+ * Cause SDL to call dbus_shutdown() on quit.
+ *
+ * This is useful as a debug tool to validate memory leaks, but shouldn't ever
+ * be set in production applications, as other libraries used by the application
+ * might use dbus under the hood and this cause cause crashes if they continue
+ * after SDL_Quit().
+ *
+ * This variable can be set to the following values:
+ *   "0"       - SDL will not call dbus_shutdown() on quit (default)
+ *   "1"       - SDL will call dbus_shutdown() on quit
+ *
+ * This hint is available since SDL 2.30.0.
+ */
+#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT"
 
 
 /**
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_joystick.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_joystick.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_keyboard.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_keyboard.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -298,8 +298,10 @@
 extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputShown(void);
 
 /**
- * Set the rectangle used to type Unicode text inputs.
- *
+ * Set the rectangle used to type Unicode text inputs. Native input methods
+ * will place a window with word suggestions near it, without covering the
+ * text being inputted.
+ * 
  * To start text input in a given location, this function is intended to be
  * called before SDL_StartTextInput, although some platforms support moving
  * the rectangle even while text input (and a composition) is active.
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_keycode.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_keycode.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_loadso.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_loadso.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_locale.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_locale.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_log.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_log.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -59,7 +59,7 @@
  *  By default the application category is enabled at the INFO level,
  *  the assert category is enabled at the WARN level, test is enabled
  *  at the VERBOSE level and all other categories are enabled at the
- *  CRITICAL level.
+ *  ERROR level.
  */
 typedef enum
 {
@@ -352,7 +352,7 @@
  */
 extern DECLSPEC void SDLCALL SDL_LogMessageV(int category,
                                              SDL_LogPriority priority,
-                                             const char *fmt, va_list ap);
+                                             SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3);
 
 /**
  * The prototype for the log output callback function.
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_main.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_main.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_messagebox.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_messagebox.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_metal.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_metal.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_misc.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_misc.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_mouse.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_mouse.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_mutex.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_mutex.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_name.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_name.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_opengl.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_opengl.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_opengles.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_opengles.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_opengles2.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_opengles2.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_pixels.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_pixels.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -61,7 +61,10 @@
     SDL_PIXELTYPE_ARRAYU16,
     SDL_PIXELTYPE_ARRAYU32,
     SDL_PIXELTYPE_ARRAYF16,
-    SDL_PIXELTYPE_ARRAYF32
+    SDL_PIXELTYPE_ARRAYF32,
+
+    /* This must be at the end of the list to avoid breaking the existing ABI */
+    SDL_PIXELTYPE_INDEX2
 } SDL_PixelType;
 
 /** Bitmap pixel order, high bit -> low bit. */
@@ -134,6 +137,7 @@
 #define SDL_ISPIXELFORMAT_INDEXED(format)   \
     (!SDL_ISPIXELFORMAT_FOURCC(format) && \
      ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \
+      (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \
       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
 
@@ -177,6 +181,12 @@
     SDL_PIXELFORMAT_INDEX1MSB =
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,
                                1, 0),
+    SDL_PIXELFORMAT_INDEX2LSB =
+        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0,
+                               2, 0),
+    SDL_PIXELFORMAT_INDEX2MSB =
+        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0,
+                               2, 0),
     SDL_PIXELFORMAT_INDEX4LSB =
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,
                                4, 0),
@@ -276,11 +286,19 @@
     SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888,
     SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888,
     SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888,
+    SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_RGBX8888,
+    SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_XRGB8888,
+    SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_BGRX8888,
+    SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888,
 #else
     SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888,
     SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888,
     SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888,
     SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888,
+    SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_XBGR8888,
+    SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_BGRX8888,
+    SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_XRGB8888,
+    SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888,
 #endif
 
     SDL_PIXELFORMAT_YV12 =      /**< Planar mode: Y + V + U  (3 planes) */
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_platform.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_platform.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -165,6 +165,12 @@
 #else
 #define WINAPI_FAMILY_WINRT 0
 #endif /* HAVE_WINAPIFAMILY_H */
+
+#if (HAVE_WINAPIFAMILY_H) && defined(WINAPI_FAMILY_PHONE_APP)
+#define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+#else
+#define SDL_WINAPI_FAMILY_PHONE 0
+#endif
 
 #if WINAPI_FAMILY_WINRT
 #undef __WINRT__
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_power.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_power.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_quit.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_quit.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_rect.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_rect.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_render.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_render.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -42,7 +42,7 @@
  *  of the many good 3D engines.
  *
  *  These functions must be called from the main thread.
- *  See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995
+ *  See this bug for details: https://github.com/libsdl-org/SDL/issues/986
  */
 
 #ifndef SDL_render_h_
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_revision.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_revision.h
@@ -1,7 +1,7 @@
 /* Generated by updaterev.sh, do not edit */
 #ifdef SDL_VENDOR_INFO
-#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40 (" SDL_VENDOR_INFO ")"
+#define SDL_REVISION "SDL-release-2.30.1-0-g5adbf3765 (" SDL_VENDOR_INFO ")"
 #else
-#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40"
+#define SDL_REVISION "SDL-release-2.30.1-0-g5adbf3765"
 #endif
 #define SDL_REVISION_NUMBER 0
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_rwops.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_rwops.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_scancode.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_scancode.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_sensor.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_sensor.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_shape.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_shape.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_stdinc.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_stdinc.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -244,7 +244,7 @@
 #ifdef FLT_EPSILON
 #define SDL_FLT_EPSILON FLT_EPSILON
 #else
-#define SDL_FLT_EPSILON 0.0000001f /* 8bitbubsy: had to modify this for MSVC... */
+#define SDL_FLT_EPSILON 0.00000011920928955078125f /* 8bitbubsy: had to modify this for MSVC... */
 #endif
 
 /* @} *//* Floating-point constants */
@@ -257,7 +257,7 @@
 #define SDL_PRIs64 PRIs64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIs64 "I64d"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIs64 "ld"
 #else
 #define SDL_PRIs64 "lld"
@@ -268,7 +268,7 @@
 #define SDL_PRIu64 PRIu64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIu64 "I64u"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIu64 "lu"
 #else
 #define SDL_PRIu64 "llu"
@@ -279,7 +279,7 @@
 #define SDL_PRIx64 PRIx64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIx64 "I64x"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIx64 "lx"
 #else
 #define SDL_PRIx64 "llx"
@@ -290,7 +290,7 @@
 #define SDL_PRIX64 PRIX64
 #elif defined(__WIN32__) || defined(__GDK__)
 #define SDL_PRIX64 "I64X"
-#elif defined(__LINUX__) && defined(__LP64__)
+#elif defined(__LP64__) && !defined(__APPLE__)
 #define SDL_PRIX64 "lX"
 #else
 #define SDL_PRIX64 "llX"
@@ -336,7 +336,9 @@
 #define SDL_PRINTF_FORMAT_STRING
 #define SDL_SCANF_FORMAT_STRING
 #define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber )
 #define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNCV( fmtargnumber )
 #else
 #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
 #include <sal.h>
@@ -362,10 +364,14 @@
 #endif
 #if defined(__GNUC__)
 #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 )))
+#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __printf__, fmtargnumber, 0 )))
 #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 )))
+#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 )))
 #else
 #define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber )
 #define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNCV( fmtargnumber )
 #endif
 #endif /* SDL_DISABLE_ANALYZE_MACROS */
 
@@ -603,11 +609,11 @@
 extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len);
 
 extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2);
-extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2);
 extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3);
-extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3);
 extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
-extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2);
 
 #ifndef HAVE_M_PI
 #ifndef M_PI
@@ -688,8 +694,8 @@
                                          size_t * outbytesleft);
 
 /**
- * This function converts a buffer or string between encodings in one pass, returning a
- * string that must be freed with SDL_free() or NULL on error.
+ * This function converts a buffer or string between encodings in one pass,
+ * returning a string that must be freed with SDL_free() or NULL on error.
  *
  * \since This function is available since SDL 2.0.0.
  */
@@ -698,8 +704,8 @@
                                                const char *inbuf,
                                                size_t inbytesleft);
 #define SDL_iconv_utf8_locale(S)    SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1)
-#define SDL_iconv_utf8_ucs2(S)      (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
-#define SDL_iconv_utf8_ucs4(S)      (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs2(S)      (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs4(S)      (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)
 #define SDL_iconv_wchar_utf8(S)     SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t))
 
 /* force builds using Clang's static analysis tools to use literal C runtime
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_surface.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_surface.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_system.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_system.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -593,7 +593,8 @@
 
 /* Functions used only by GDK */
 #if defined(__GDK__)
-typedef struct XTaskQueueObject * XTaskQueueHandle;
+typedef struct XTaskQueueObject *XTaskQueueHandle;
+typedef struct XUser *XUserHandle;
 
 /**
  * Gets a reference to the global async task queue handle for GDK,
@@ -609,6 +610,20 @@
  * \since This function is available since SDL 2.24.0.
  */
 extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue);
+
+/**
+ * Gets a reference to the default user handle for GDK.
+ *
+ * This is effectively a synchronous version of XUserAddAsync, which always
+ * prefers the default user and allows a sign-in UI.
+ *
+ * \param outUserHandle a pointer to be filled in with the default user
+ *                      handle.
+ * \returns 0 if success, -1 if any error occurs.
+ *
+ * \since This function is available since SDL 2.28.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(XUserHandle * outUserHandle);
 
 #endif
 
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_syswm.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_syswm.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_assert.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_assert.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_common.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_common.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_compare.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_compare.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_crc32.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_crc32.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_font.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_font.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_fuzzer.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_fuzzer.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_harness.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_harness.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_images.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_images.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_log.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_log.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_md5.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_md5.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_memory.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_memory.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_random.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_test_random.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_thread.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_thread.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_timer.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_timer.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_touch.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_touch.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_types.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_types.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_version.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_version.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -58,8 +58,8 @@
 /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
 */
 #define SDL_MAJOR_VERSION   2
-#define SDL_MINOR_VERSION   28
-#define SDL_PATCHLEVEL      5
+#define SDL_MINOR_VERSION   30
+#define SDL_PATCHLEVEL      1
 
 /**
  * Macro to determine SDL version program was compiled against.
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_video.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/SDL_video.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -1278,7 +1278,8 @@
 /**
  * Return whether the window has a surface associated with it.
  *
- * \returns SDL_TRUE if there is a surface associated with the window, or SDL_FALSE otherwise.
+ * \returns SDL_TRUE if there is a surface associated with the window, or
+ *          SDL_FALSE otherwise.
  *
  * \since This function is available since SDL 2.28.0.
  *
@@ -1339,6 +1340,11 @@
  * on the screen.
  *
  * This function is equivalent to the SDL 1.2 API SDL_UpdateRects().
+ *
+ * Note that this function will update _at least_ the rectangles specified,
+ * but this is only intended as an optimization; in practice, this might
+ * update more of the screen (or all of the screen!), depending on what
+ * method SDL uses to send pixels to the system.
  *
  * \param window the window to update
  * \param rects an array of SDL_Rect structures representing areas of the
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/begin_code.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/begin_code.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -36,6 +36,8 @@
 #ifndef SDL_DEPRECATED
 #  if defined(__GNUC__) && (__GNUC__ >= 4)  /* technically, this arrived in gcc 3.1, but oh well. */
 #    define SDL_DEPRECATED __attribute__((deprecated))
+#  elif defined(_MSC_VER)
+#    define SDL_DEPRECATED __declspec(deprecated)
 #  else
 #    define SDL_DEPRECATED
 #  endif
--- a/vs2019_project/ft2-clone/sdl/include/SDL2/close_code.h
+++ b/vs2019_project/ft2-clone/sdl/include/SDL2/close_code.h
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages