diff --git a/drivers/sdl/joypad_sdl.cpp b/drivers/sdl/joypad_sdl.cpp index e8cb47c7549..8e808a885a7 100644 --- a/drivers/sdl/joypad_sdl.cpp +++ b/drivers/sdl/joypad_sdl.cpp @@ -56,19 +56,6 @@ JoypadSDL::JoypadSDL() { singleton = this; } -#ifdef WINDOWS_ENABLED -extern "C" { -HWND SDL_HelperWindow; -} - -// Required for DInput joypads to work -// TODO: remove this workaround when we update to newer version of SDL -JoypadSDL::JoypadSDL(HWND p_helper_window) : - JoypadSDL() { - SDL_HelperWindow = p_helper_window; -} -#endif - JoypadSDL::~JoypadSDL() { // Process any remaining input events process_events(); diff --git a/drivers/sdl/joypad_sdl.h b/drivers/sdl/joypad_sdl.h index a399e11caf5..7010822675d 100644 --- a/drivers/sdl/joypad_sdl.h +++ b/drivers/sdl/joypad_sdl.h @@ -34,16 +34,12 @@ #include "core/os/thread.h" typedef uint32_t SDL_JoystickID; -typedef struct HWND__ *HWND; typedef struct SDL_Joystick SDL_Joystick; typedef struct SDL_Gamepad SDL_Gamepad; class JoypadSDL { public: JoypadSDL(); -#ifdef WINDOWS_ENABLED - JoypadSDL(HWND p_helper_window); -#endif ~JoypadSDL(); static JoypadSDL *get_singleton(); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 65770fe8958..8653ee43123 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -7439,7 +7439,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win window_set_vsync_mode(p_vsync_mode, MAIN_WINDOW_ID); #ifdef SDL_ENABLED - joypad_sdl = memnew(JoypadSDL(windows[MAIN_WINDOW_ID].hWnd)); + joypad_sdl = memnew(JoypadSDL); if (joypad_sdl->initialize() != OK) { ERR_PRINT("Couldn't initialize SDL joypad input driver."); memdelete(joypad_sdl); diff --git a/thirdparty/README.md b/thirdparty/README.md index 62fe3e0f573..bc9ca074cba 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -463,20 +463,6 @@ Files extracted from upstream source: - Except `main.cc`, `harfbuzz*.cc`, `harfrust.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, `hb-harfrust.cc`, `wasm/*`, `ms-use/*`, `rust/*` -## hidapi - -- Upstream: https://github.com/libsdl-org/SDL/tree/main/src/hidapi -- Version: 0.14.0 (8d604353a53853fa56d1bdce0363535605ca868f, 2025) -- License: BSD-3-Clause - -Files extracted from upstream source: - -- See `thirdparty/sdl/update-sdl.sh` - -The source code of this library is being bundled with SDL's source code files. -The files of hidapi are stored in `thirdparty/sdl/hidapi/` folder. - - ## icu4c - Upstream: https://github.com/unicode-org/icu @@ -972,8 +958,9 @@ Files extracted from upstream source: ## sdl - Upstream: https://github.com/libsdl-org/SDL -- Version: 3.2.14 (8d604353a53853fa56d1bdce0363535605ca868f, 2025) +- Version: 3.2.28 (7f3ae3d57459e59943a4ecfefc8f6277ec6bf540, 2025) - License: Zlib +- Vendored: hidapi 0.14.0, license BSD-3-Clause Files extracted from upstream source: @@ -982,15 +969,10 @@ Files extracted from upstream source: Patches: - `0001-remove-unnecessary-subsystems.patch` ([GH-106218](https://github.com/godotengine/godot/pull/106218)) -- `0002-msvc-constants-fpstrict.patch` ([GH-106218](https://github.com/godotengine/godot/pull/106218)) - `0003-std-include.patch` ([GH-108144](https://github.com/godotengine/godot/pull/108144)) - `0004-errno-include.patch` ([GH-108354](https://github.com/godotengine/godot/pull/108354)) - `0005-fix-libudev-dbus.patch` ([GH-108373](https://github.com/godotengine/godot/pull/108373)) - `0006-fix-cs-environ.patch` ([GH-109283](https://github.com/godotengine/godot/pull/109283)) -- `0007-macos-joypad-name.patch` ([GH-110500](https://github.com/godotengine/godot/pull/110500)) - -The SDL source code folder includes `hidapi` library inside of folder `thirdparty/sdl/hidapi/`. -Its version and license is described in this file under `hidapi`. ## spirv-cross diff --git a/thirdparty/sdl/SDL.c b/thirdparty/sdl/SDL.c index dd0b823634a..3dad7e29ba9 100644 --- a/thirdparty/sdl/SDL.c +++ b/thirdparty/sdl/SDL.c @@ -56,7 +56,7 @@ // Initialization/Cleanup routines #include "timer/SDL_timer_c.h" -#ifdef SDL_VIDEO_DRIVER_WINDOWS +#ifdef SDL_PLATFORM_WINDOWS extern bool SDL_HelperWindowCreate(void); extern void SDL_HelperWindowDestroy(void); #endif @@ -308,7 +308,7 @@ bool SDL_InitSubSystem(SDL_InitFlags flags) SDL_DBus_Init(); #endif -#ifdef SDL_VIDEO_DRIVER_WINDOWS +#ifdef SDL_PLATFORM_WINDOWS if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) { if (!SDL_HelperWindowCreate()) { goto quit_and_error; @@ -644,7 +644,7 @@ void SDL_Quit(void) SDL_bInMainQuit = true; // Quit all subsystems -#ifdef SDL_VIDEO_DRIVER_WINDOWS +#ifdef SDL_PLATFORM_WINDOWS SDL_HelperWindowDestroy(); #endif SDL_QuitSubSystem(SDL_INIT_EVERYTHING); diff --git a/thirdparty/sdl/core/windows/SDL_immdevice.c b/thirdparty/sdl/core/windows/SDL_immdevice.c index 802a412e15e..cc6945b1bcb 100644 --- a/thirdparty/sdl/core/windows/SDL_immdevice.c +++ b/thirdparty/sdl/core/windows/SDL_immdevice.c @@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device) } } -static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid) +static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid, SDL_AudioFormat force_format) { /* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever). In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for @@ -162,7 +162,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn SDL_zero(spec); spec.channels = (Uint8)fmt->Format.nChannels; spec.freq = fmt->Format.nSamplesPerSec; - spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt); + spec.format = (force_format != SDL_AUDIO_UNKNOWN) ? force_format : SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt); device = SDL_AddAudioDevice(recording, devname, &spec, handle); if (!device) { @@ -183,6 +183,7 @@ typedef struct SDLMMNotificationClient { const IMMNotificationClientVtbl *lpVtbl; SDL_AtomicInt refcount; + SDL_AudioFormat force_format; } SDLMMNotificationClient; static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_QueryInterface(IMMNotificationClient *client, REFIID iid, void **ppv) @@ -241,6 +242,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceRemoved(IMMNoti static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IMMNotificationClient *iclient, LPCWSTR pwstrDeviceId, DWORD dwNewState) { + SDLMMNotificationClient *client = (SDLMMNotificationClient *)iclient; IMMDevice *device = NULL; if (SUCCEEDED(IMMDeviceEnumerator_GetDevice(enumerator, pwstrDeviceId, &device))) { @@ -255,7 +257,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM GUID dsoundguid; GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid); if (utf8dev) { - SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid); + SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid, client->force_format); SDL_free(utf8dev); } } else { @@ -286,7 +288,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = { SDLMMNotificationClient_OnPropertyValueChanged }; -static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 } }; +static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 }, SDL_AUDIO_UNKNOWN }; bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks) { @@ -363,7 +365,7 @@ bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool reco return true; } -static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device) +static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device, SDL_AudioFormat force_format) { /* Note that WASAPI separates "adapter devices" from "audio endpoint devices" ...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */ @@ -405,7 +407,7 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de SDL_zero(dsoundguid); GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid); if (devname) { - SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid); + SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid, force_format); if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) { *default_device = sdldevice; } @@ -422,10 +424,12 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de IMMDeviceCollection_Release(collection); } -void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) +void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording, SDL_AudioFormat force_format) { - EnumerateEndpointsForFlow(false, default_playback); - EnumerateEndpointsForFlow(true, default_recording); + EnumerateEndpointsForFlow(false, default_playback, force_format); + EnumerateEndpointsForFlow(true, default_recording, force_format); + + notification_client.force_format = force_format; // if this fails, we just won't get hotplug events. Carry on anyhow. IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)¬ification_client); diff --git a/thirdparty/sdl/core/windows/SDL_immdevice.h b/thirdparty/sdl/core/windows/SDL_immdevice.h index 66fdf13b814..0582bc0deda 100644 --- a/thirdparty/sdl/core/windows/SDL_immdevice.h +++ b/thirdparty/sdl/core/windows/SDL_immdevice.h @@ -37,7 +37,7 @@ typedef struct SDL_IMMDevice_callbacks bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks); void SDL_IMMDevice_Quit(void); bool SDL_IMMDevice_Get(struct SDL_AudioDevice *device, IMMDevice **immdevice, bool recording); -void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording); +void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording, SDL_AudioFormat force_format); LPGUID SDL_IMMDevice_GetDirectSoundGUID(struct SDL_AudioDevice *device); LPCWSTR SDL_IMMDevice_GetDevID(struct SDL_AudioDevice *device); void SDL_IMMDevice_FreeDeviceHandle(struct SDL_AudioDevice *device); diff --git a/thirdparty/sdl/core/windows/SDL_windows.c b/thirdparty/sdl/core/windows/SDL_windows.c index 3259e787d4e..cf53c3c72db 100644 --- a/thirdparty/sdl/core/windows/SDL_windows.c +++ b/thirdparty/sdl/core/windows/SDL_windows.c @@ -53,6 +53,78 @@ typedef enum RO_INIT_TYPE #define WC_ERR_INVALID_CHARS 0x00000080 #endif +// Fake window to help with DirectInput events. +HWND SDL_HelperWindow = NULL; +static const TCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher"); +static const TCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow"); +static ATOM SDL_HelperWindowClass = 0; + +/* + * Creates a HelperWindow used for DirectInput. + */ +bool SDL_HelperWindowCreate(void) +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wce; + + // Make sure window isn't created twice. + if (SDL_HelperWindow != NULL) { + return true; + } + + // Create the class. + SDL_zero(wce); + wce.lpfnWndProc = DefWindowProc; + wce.lpszClassName = SDL_HelperWindowClassName; + wce.hInstance = hInstance; + + // Register the class. + SDL_HelperWindowClass = RegisterClass(&wce); + if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) { + return WIN_SetError("Unable to create Helper Window Class"); + } + + // Create the window. + SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName, + SDL_HelperWindowName, + WS_OVERLAPPED, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, HWND_MESSAGE, NULL, + hInstance, NULL); + if (!SDL_HelperWindow) { + UnregisterClass(SDL_HelperWindowClassName, hInstance); + return WIN_SetError("Unable to create Helper Window"); + } + + return true; +} + +/* + * Destroys the HelperWindow previously created with SDL_HelperWindowCreate. + */ +void SDL_HelperWindowDestroy(void) +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + + // Destroy the window. + if (SDL_HelperWindow != NULL) { + if (DestroyWindow(SDL_HelperWindow) == 0) { + WIN_SetError("Unable to destroy Helper Window"); + return; + } + SDL_HelperWindow = NULL; + } + + // Unregister the class. + if (SDL_HelperWindowClass != 0) { + if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) { + WIN_SetError("Unable to destroy Helper Window Class"); + return; + } + SDL_HelperWindowClass = 0; + } +} + // Sets an error message based on an HRESULT bool WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) { @@ -198,6 +270,24 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO return result; #endif +BOOL WIN_IsWine(void) +{ + static bool checked; + static bool is_wine; + + if (!checked) { + HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll")); + if (ntdll) { + if (GetProcAddress(ntdll, "wine_get_version") != NULL) { + is_wine = true; + } + FreeLibrary(ntdll); + } + checked = true; + } + return is_wine; +} + // this is the oldest thing we run on (and we may lose support for this in SDL3 at any time!), // so there's no "OrGreater" as that would always be TRUE. The other functions are here to // ask "can we support a specific feature?" but this function is here to ask "do we need to do diff --git a/thirdparty/sdl/core/windows/SDL_windows.h b/thirdparty/sdl/core/windows/SDL_windows.h index ef54fe379e6..fa405ade1a5 100644 --- a/thirdparty/sdl/core/windows/SDL_windows.h +++ b/thirdparty/sdl/core/windows/SDL_windows.h @@ -133,6 +133,9 @@ extern void WIN_CoUninitialize(void); extern HRESULT WIN_RoInitialize(void); extern void WIN_RoUninitialize(void); +// Returns true if we're running on Wine +extern BOOL WIN_IsWine(void); + // Returns true if we're running on Windows XP (any service pack). DOES NOT CHECK XP "OR GREATER"! extern BOOL WIN_IsWindowsXP(void); diff --git a/thirdparty/sdl/events/SDL_events.c b/thirdparty/sdl/events/SDL_events.c index 24c2c4270f4..7ca683e0eb6 100644 --- a/thirdparty/sdl/events/SDL_events.c +++ b/thirdparty/sdl/events/SDL_events.c @@ -1094,7 +1094,8 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_EventAct if (action == SDL_ADDEVENT) { if (!events) { SDL_UnlockMutex(SDL_EventQ.lock); - return SDL_InvalidParamError("events"); + SDL_InvalidParamError("events"); + return -1; } for (i = 0; i < numevents; ++i) { used += SDL_AddEvent(&events[i]); @@ -1529,6 +1530,8 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) #ifdef SDL_PLATFORM_ANDROID for (;;) { + SDL_PumpEventsInternal(true); + if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) { return true; } diff --git a/thirdparty/sdl/haptic/linux/SDL_syshaptic.c b/thirdparty/sdl/haptic/linux/SDL_syshaptic.c index 842f577cfa8..fa49e457bd4 100644 --- a/thirdparty/sdl/haptic/linux/SDL_syshaptic.c +++ b/thirdparty/sdl/haptic/linux/SDL_syshaptic.c @@ -1117,13 +1117,12 @@ bool SDL_SYS_HapticResume(SDL_Haptic *haptic) */ bool SDL_SYS_HapticStopAll(SDL_Haptic *haptic) { - int i, ret; + int i; // Linux does not support this natively so we have to loop. for (i = 0; i < haptic->neffects; i++) { if (haptic->effects[i].hweffect != NULL) { - ret = SDL_SYS_HapticStopEffect(haptic, &haptic->effects[i]); - if (ret < 0) { + if (!SDL_SYS_HapticStopEffect(haptic, &haptic->effects[i])) { return SDL_SetError("Haptic: Error while trying to stop all playing effects."); } } diff --git a/thirdparty/sdl/haptic/windows/SDL_dinputhaptic.c b/thirdparty/sdl/haptic/windows/SDL_dinputhaptic.c index 255aac015d8..79c4b3501f0 100644 --- a/thirdparty/sdl/haptic/windows/SDL_dinputhaptic.c +++ b/thirdparty/sdl/haptic/windows/SDL_dinputhaptic.c @@ -31,11 +31,7 @@ /* * External stuff. */ -#ifdef SDL_VIDEO_DRIVER_WINDOWS extern HWND SDL_HelperWindow; -#else -static const HWND SDL_HelperWindow = NULL; -#endif /* * Internal stuff. diff --git a/thirdparty/sdl/hidapi/linux/hid.c b/thirdparty/sdl/hidapi/linux/hid.c index 51a32ef892f..641477fb23c 100644 --- a/thirdparty/sdl/hidapi/linux/hid.c +++ b/thirdparty/sdl/hidapi/linux/hid.c @@ -164,7 +164,6 @@ static wchar_t *utf8_to_wchar_t(const char *utf8) * Use register_error_str(NULL) to free the error message completely. */ static void register_error_str(wchar_t **error_str, const char *msg) { - free(*error_str); #ifdef HIDAPI_USING_SDL_RUNTIME /* Thread-safe error handling */ if (msg) { @@ -173,6 +172,7 @@ static void register_error_str(wchar_t **error_str, const char *msg) SDL_ClearError(); } #else + free(*error_str); *error_str = utf8_to_wchar_t(msg); #endif } diff --git a/thirdparty/sdl/hidapi/windows/hid.c b/thirdparty/sdl/hidapi/windows/hid.c index 3376ba96e55..8a8224302e7 100644 --- a/thirdparty/sdl/hidapi/windows/hid.c +++ b/thirdparty/sdl/hidapi/windows/hid.c @@ -949,6 +949,7 @@ static int hid_blacklist(unsigned short vendor_id, unsigned short product_id) { 0x0D8C, 0x0014 }, /* Sharkoon Skiller SGH2 headset - causes deadlock asking for device details */ { 0x1532, 0x0109 }, /* Razer Lycosa Gaming keyboard - causes deadlock asking for device details */ { 0x1532, 0x010B }, /* Razer Arctosa Gaming keyboard - causes deadlock asking for device details */ + { 0x1532, 0x0227 }, /* Razer Huntsman Gaming keyboard - long delay asking for device details */ { 0x1B1C, 0x1B3D }, /* Corsair Gaming keyboard - causes deadlock asking for device details */ { 0x1CCF, 0x0000 } /* All Konami Amusement Devices - causes deadlock asking for device details */ }; @@ -1398,6 +1399,11 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char } } if (!res) { + if (GetLastError() == ERROR_OPERATION_ABORTED) { + /* The read request was issued on another thread. + This is harmless, so just ignore it. */ + return 0; + } register_winapi_error(dev, L"hid_read_timeout/GetOverlappedResult"); } diff --git a/thirdparty/sdl/include/SDL3/SDL.h b/thirdparty/sdl/include/SDL3/SDL.h index f0671c95c32..c99997044be 100644 --- a/thirdparty/sdl/include/SDL3/SDL.h +++ b/thirdparty/sdl/include/SDL3/SDL.h @@ -20,7 +20,7 @@ */ /** - * Main include header for the SDL library, version 3.2.16 + * Main include header for the SDL library, version 3.2.28 * * It is almost always best to include just this one header instead of * picking out individual headers included here. There are exceptions to diff --git a/thirdparty/sdl/include/SDL3/SDL_assert.h b/thirdparty/sdl/include/SDL3/SDL_assert.h index 6c90acc0290..3fa6bdc9366 100644 --- a/thirdparty/sdl/include/SDL3/SDL_assert.h +++ b/thirdparty/sdl/include/SDL3/SDL_assert.h @@ -126,7 +126,7 @@ extern "C" { */ #define SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner -#elif defined(_MSC_VER) && _MSC_VER >= 1310 +#elif defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1310) /* Don't include intrin.h here because it contains C++ code */ extern void __cdecl __debugbreak(void); #define SDL_TriggerBreakpoint() __debugbreak() @@ -362,7 +362,7 @@ extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData * #define SDL_enabled_assert(condition) \ do { \ while ( !(condition) ) { \ - static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \ + static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \ const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ continue; /* go again. */ \ diff --git a/thirdparty/sdl/include/SDL3/SDL_audio.h b/thirdparty/sdl/include/SDL3/SDL_audio.h index c6acf885f42..51af40e9552 100644 --- a/thirdparty/sdl/include/SDL3/SDL_audio.h +++ b/thirdparty/sdl/include/SDL3/SDL_audio.h @@ -942,7 +942,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid); * Binding a stream to a device will set its output format for playback * devices, and its input format for recording devices, so they match the * device's settings. The caller is welcome to change the other end of the - * stream's format at any time with SDL_SetAudioStreamFormat(). + * stream's format at any time with SDL_SetAudioStreamFormat(). If the other + * end of the stream's format has never been set (the audio stream was created + * with a NULL audio spec), this function will set it to match the device + * end's format. * * \param devid an audio device to bind a stream to. * \param streams an array of audio streams to bind. @@ -1021,7 +1024,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream); /** * Query an audio stream for its currently-bound device. * - * This reports the audio device that an audio stream is currently bound to. + * This reports the logical audio device that an audio stream is currently bound to. * * If not bound, or invalid, this returns zero, which is not a valid device * ID. diff --git a/thirdparty/sdl/include/SDL3/SDL_camera.h b/thirdparty/sdl/include/SDL3/SDL_camera.h index 5f3911fdf96..c0e2ee0fed4 100644 --- a/thirdparty/sdl/include/SDL3/SDL_camera.h +++ b/thirdparty/sdl/include/SDL3/SDL_camera.h @@ -119,7 +119,7 @@ typedef struct SDL_CameraSpec int width; /**< Frame width */ int height; /**< Frame height */ int framerate_numerator; /**< Frame rate numerator ((num / denom) == FPS, (denom / num) == duration in seconds) */ - int framerate_denominator; /**< Frame rate demoninator ((num / denom) == FPS, (denom / num) == duration in seconds) */ + int framerate_denominator; /**< Frame rate denominator ((num / denom) == FPS, (denom / num) == duration in seconds) */ } SDL_CameraSpec; /** diff --git a/thirdparty/sdl/include/SDL3/SDL_clipboard.h b/thirdparty/sdl/include/SDL3/SDL_clipboard.h index 0d3cbb499b1..a4b4cc9b9ef 100644 --- a/thirdparty/sdl/include/SDL3/SDL_clipboard.h +++ b/thirdparty/sdl/include/SDL3/SDL_clipboard.h @@ -106,7 +106,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardText(const char *text); /** * Get UTF-8 text from the clipboard. * - * This functions returns an empty string if there was not enough memory left + * This function returns an empty string if there is not enough memory left * for a copy of the clipboard's content. * * \returns the clipboard text on success or an empty string on failure; call @@ -155,7 +155,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetPrimarySelectionText(const char *text); /** * Get UTF-8 text from the primary selection. * - * This functions returns an empty string if there was not enough memory left + * This function returns an empty string if there is not enough memory left * for a copy of the primary selection's content. * * \returns the primary selection text on success or an empty string on @@ -194,15 +194,14 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void); * clipboard is cleared or new data is set. The clipboard is automatically * cleared in SDL_Quit(). * - * \param userdata a pointer to provided user data. + * \param userdata a pointer to the provided user data. * \param mime_type the requested mime-type. * \param size a pointer filled in with the length of the returned data. * \returns a pointer to the data for the provided mime-type. Returning NULL - * or setting length to 0 will cause no data to be sent to the - * "receiver". It is up to the receiver to handle this. Essentially - * returning no data is more or less undefined behavior and may cause - * breakage in receiving applications. The returned data will not be - * freed so it needs to be retained and dealt with internally. + * or setting the length to 0 will cause zero length data to be sent + * to the "receiver", which should be able to handle this. The + * returned data will not be freed, so it needs to be retained and + * dealt with internally. * * \since This function is available since SDL 3.2.0. * @@ -211,10 +210,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void); typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size); /** - * Callback function that will be called when the clipboard is cleared, or new + * Callback function that will be called when the clipboard is cleared, or when new * data is set. * - * \param userdata a pointer to provided user data. + * \param userdata a pointer to the provided user data. * * \since This function is available since SDL 3.2.0. * @@ -231,7 +230,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata); * respond with the data for the requested mime-type. * * The size of text data does not include any terminator, and the text does - * not need to be null terminated (e.g. you can directly copy a portion of a + * not need to be null-terminated (e.g., you can directly copy a portion of a * document). * * \param callback a function pointer to the function that provides the @@ -239,7 +238,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata); * \param cleanup a function pointer to the function that cleans up the * clipboard data. * \param userdata an opaque pointer that will be forwarded to the callbacks. - * \param mime_types a list of mime-types that are being offered. + * \param mime_types a list of mime-types that are being offered. SDL copies the given list. * \param num_mime_types the number of mime-types in the mime_types list. * \returns true on success or false on failure; call SDL_GetError() for more * information. @@ -269,10 +268,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback extern SDL_DECLSPEC bool SDLCALL SDL_ClearClipboardData(void); /** - * Get the data from clipboard for a given mime type. + * Get the data from the clipboard for a given mime type. * * The size of text data does not include the terminator, but the text is - * guaranteed to be null terminated. + * guaranteed to be null-terminated. * * \param mime_type the mime type to read from the clipboard. * \param size a pointer filled in with the length of the returned data. @@ -292,8 +291,8 @@ extern SDL_DECLSPEC void * SDLCALL SDL_GetClipboardData(const char *mime_type, s /** * Query whether there is data in the clipboard for the provided mime type. * - * \param mime_type the mime type to check for data for. - * \returns true if there exists data in clipboard for the provided mime type, + * \param mime_type the mime type to check for data. + * \returns true if data exists in the clipboard for the provided mime type, * false if it does not. * * \threadsafety This function should only be called on the main thread. @@ -310,7 +309,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardData(const char *mime_type); * * \param num_mime_types a pointer filled with the number of mime types, may * be NULL. - * \returns a null terminated array of strings with mime types, or NULL on + * \returns a null-terminated array of strings with mime types, or NULL on * failure; call SDL_GetError() for more information. This should be * freed with SDL_free() when it is no longer needed. * diff --git a/thirdparty/sdl/include/SDL3/SDL_endian.h b/thirdparty/sdl/include/SDL3/SDL_endian.h index a34e9d4b09c..f3ab18ffdc0 100644 --- a/thirdparty/sdl/include/SDL3/SDL_endian.h +++ b/thirdparty/sdl/include/SDL3/SDL_endian.h @@ -46,7 +46,7 @@ #if defined(_MSC_VER) && (_MSC_VER >= 1400) /* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version, so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */ -#ifdef __clang__ +#if defined(__clang__) && !SDL_HAS_BUILTIN(_m_prefetch) #ifndef __PRFCHWINTRIN_H #define __PRFCHWINTRIN_H static __inline__ void __attribute__((__always_inline__, __nodebug__)) @@ -128,7 +128,7 @@ _m_prefetch(void *__P) * \sa SDL_BIG_ENDIAN */ #define SDL_BYTEORDER SDL_LIL_ENDIAN___or_maybe___SDL_BIG_ENDIAN -#elif defined(SDL_PLATFORM_LINUX) +#elif defined(SDL_PLATFORM_LINUX) || defined(__GLIBC__) #include #define SDL_BYTEORDER __BYTE_ORDER #elif defined(SDL_PLATFORM_SOLARIS) @@ -486,7 +486,7 @@ SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { return x_but_byteswapped; } * * \since This function is available since SDL 3.2.0. */ -SDL_FORCE_INLINE Uint32 SDL_Swap64(Uint64 x) { return x_but_byteswapped; } +SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) { return x_but_byteswapped; } /** * Swap a 16-bit value from littleendian to native byte order. diff --git a/thirdparty/sdl/include/SDL3/SDL_events.h b/thirdparty/sdl/include/SDL3/SDL_events.h index d267f051f8d..7dc409a0cc2 100644 --- a/thirdparty/sdl/include/SDL3/SDL_events.h +++ b/thirdparty/sdl/include/SDL3/SDL_events.h @@ -1043,7 +1043,7 @@ typedef union SDL_Event } SDL_Event; /* Make sure we haven't broken binary compatibility */ -SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding)); +SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof((SDL_static_cast(SDL_Event *, NULL))->padding)); /* Function prototypes */ diff --git a/thirdparty/sdl/include/SDL3/SDL_hints.h b/thirdparty/sdl/include/SDL3/SDL_hints.h index a081535716c..ecee3d36f17 100644 --- a/thirdparty/sdl/include/SDL3/SDL_hints.h +++ b/thirdparty/sdl/include/SDL3/SDL_hints.h @@ -595,7 +595,7 @@ extern "C" { * A variable that limits what CPU features are available. * * By default, SDL marks all features the current CPU supports as available. - * This hint allows to limit these to a subset. + * This hint allows the enabled features to be limited to a subset. * * When the hint is unset, or empty, SDL will enable all detected CPU * features. @@ -2126,8 +2126,8 @@ extern "C" { * * The variable can be set to the following values: * - * - "0": WGI is not used. - * - "1": WGI is used. (default) + * - "0": WGI is not used. (default) + * - "1": WGI is used. * * This hint should be set before SDL is initialized. * diff --git a/thirdparty/sdl/include/SDL3/SDL_intrin.h b/thirdparty/sdl/include/SDL3/SDL_intrin.h index bac6d7ad4fa..c7338ee8f5e 100644 --- a/thirdparty/sdl/include/SDL3/SDL_intrin.h +++ b/thirdparty/sdl/include/SDL3/SDL_intrin.h @@ -280,12 +280,14 @@ _m_prefetch(void *__P) * \sa SDL_TARGETING */ #define SDL_HAS_TARGET_ATTRIBS - +#elif defined(__loongarch64) && defined(__GNUC__) && (__GNUC__ >= 15) +/* LoongArch requires GCC 15+ for target attribute support */ +# define SDL_HAS_TARGET_ATTRIBS #elif defined(__clang__) && defined(__has_attribute) # if __has_attribute(target) # define SDL_HAS_TARGET_ATTRIBS # endif -#elif defined(__GNUC__) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */ +#elif defined(__GNUC__) && !defined(__loongarch64) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */ # define SDL_HAS_TARGET_ATTRIBS #elif defined(__ICC) && __ICC >= 1600 # define SDL_HAS_TARGET_ATTRIBS diff --git a/thirdparty/sdl/include/SDL3/SDL_mutex.h b/thirdparty/sdl/include/SDL3/SDL_mutex.h index c88ec153153..9ab164078a9 100644 --- a/thirdparty/sdl/include/SDL3/SDL_mutex.h +++ b/thirdparty/sdl/include/SDL3/SDL_mutex.h @@ -360,7 +360,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mut * \sa SDL_LockMutex * \sa SDL_UnlockMutex */ -extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0, mutex); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(true, mutex); /** * Unlock the mutex. @@ -559,7 +559,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SD * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ -extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(0, rwlock); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(true, rwlock); /** * Try to lock a read/write lock _for writing_ without blocking. @@ -589,7 +589,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) * \sa SDL_TryLockRWLockForReading * \sa SDL_UnlockRWLock */ -extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(0, rwlock); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(true, rwlock); /** * Unlock the read/write lock. diff --git a/thirdparty/sdl/include/SDL3/SDL_rect.h b/thirdparty/sdl/include/SDL3/SDL_rect.h index eb2d34a69a1..603f7b39046 100644 --- a/thirdparty/sdl/include/SDL3/SDL_rect.h +++ b/thirdparty/sdl/include/SDL3/SDL_rect.h @@ -125,10 +125,10 @@ typedef struct SDL_FRect */ SDL_FORCE_INLINE void SDL_RectToFRect(const SDL_Rect *rect, SDL_FRect *frect) { - frect->x = (float)rect->x; - frect->y = (float)rect->y; - frect->w = (float)rect->w; - frect->h = (float)rect->h; + frect->x = SDL_static_cast(float, rect->x); + frect->y = SDL_static_cast(float, rect->y); + frect->w = SDL_static_cast(float, rect->w); + frect->h = SDL_static_cast(float, rect->h); } /** diff --git a/thirdparty/sdl/include/SDL3/SDL_render.h b/thirdparty/sdl/include/SDL3/SDL_render.h index c9d184cc07c..e7928118abf 100644 --- a/thirdparty/sdl/include/SDL3/SDL_render.h +++ b/thirdparty/sdl/include/SDL3/SDL_render.h @@ -2612,7 +2612,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderDebugText(SDL_Renderer *renderer, flo * Draw debug text to an SDL_Renderer. * * This function will render a printf()-style format string to a renderer. - * Note that this is a convinence function for debugging, with severe + * Note that this is a convenience function for debugging, with severe * limitations, and is not intended to be used for production apps and games. * * For the full list of limitations and other useful information, see diff --git a/thirdparty/sdl/include/SDL3/SDL_scancode.h b/thirdparty/sdl/include/SDL3/SDL_scancode.h index 9650a6cfe35..6e9be47e6ae 100644 --- a/thirdparty/sdl/include/SDL3/SDL_scancode.h +++ b/thirdparty/sdl/include/SDL3/SDL_scancode.h @@ -208,7 +208,7 @@ typedef enum SDL_Scancode SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO * keyboards have over ANSI ones, - * located between left shift and Y. + * located between left shift and Z. * Produces GRAVE ACCENT and TILDE in a * US or UK Mac layout, REVERSE SOLIDUS * (backslash) and VERTICAL LINE in a diff --git a/thirdparty/sdl/include/SDL3/SDL_sensor.h b/thirdparty/sdl/include/SDL3/SDL_sensor.h index b220f0538c0..43366f13570 100644 --- a/thirdparty/sdl/include/SDL3/SDL_sensor.h +++ b/thirdparty/sdl/include/SDL3/SDL_sensor.h @@ -138,7 +138,8 @@ typedef enum SDL_SensorType SDL_SENSOR_ACCEL_L, /**< Accelerometer for left Joy-Con controller and Wii nunchuk */ SDL_SENSOR_GYRO_L, /**< Gyroscope for left Joy-Con controller */ SDL_SENSOR_ACCEL_R, /**< Accelerometer for right Joy-Con controller */ - SDL_SENSOR_GYRO_R /**< Gyroscope for right Joy-Con controller */ + SDL_SENSOR_GYRO_R, /**< Gyroscope for right Joy-Con controller */ + SDL_SENSOR_COUNT } SDL_SensorType; diff --git a/thirdparty/sdl/include/SDL3/SDL_stdinc.h b/thirdparty/sdl/include/SDL3/SDL_stdinc.h index 7df253feceb..5b8dc463408 100644 --- a/thirdparty/sdl/include/SDL3/SDL_stdinc.h +++ b/thirdparty/sdl/include/SDL3/SDL_stdinc.h @@ -1164,7 +1164,7 @@ typedef struct SDL_alignment_test void *b; } SDL_alignment_test; SDL_COMPILE_TIME_ASSERT(struct_alignment, sizeof(SDL_alignment_test) == (2 * sizeof(void *))); -SDL_COMPILE_TIME_ASSERT(two_s_complement, (int)~(int)0 == (int)(-1)); +SDL_COMPILE_TIME_ASSERT(two_s_complement, SDL_static_cast(int, ~SDL_static_cast(int, 0)) == SDL_static_cast(int, -1)); #endif /* DOXYGEN_SHOULD_IGNORE_THIS */ /** \endcond */ @@ -3426,7 +3426,7 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_utf8strnlen(const char *str, size_t bytes * Convert an integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3454,7 +3454,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_itoa(int value, char *str, int radix); * Convert an unsigned integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3482,7 +3482,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_uitoa(unsigned int value, char *str, int * Convert a long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3510,7 +3510,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_ltoa(long value, char *str, int radix); * Convert an unsigned long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3540,7 +3540,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_ultoa(unsigned long value, char *str, int * Convert a long long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3568,7 +3568,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_lltoa(long long value, char *str, int rad * Convert an unsigned long long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3923,7 +3923,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen); /** - * Searches a string for the first occurence of any character contained in a + * Searches a string for the first occurrence of any character contained in a * breakset, and returns a pointer from the string to that character. * * \param str The null-terminated string to be searched. Must not be NULL, and @@ -3931,7 +3931,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *st * \param breakset A null-terminated string containing the list of characters * to look for. Must not be NULL, and must not overlap with * `str`. - * \returns A pointer to the location, in str, of the first occurence of a + * \returns A pointer to the location, in str, of the first occurrence of a * character present in the breakset, or NULL if none is found. * * \threadsafety It is safe to call this function from any thread. @@ -5821,7 +5821,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd); * This function converts text between encodings, reading from and writing to * a buffer. * - * It returns the number of succesful conversions on success. On error, + * It returns the number of successful conversions on success. On error, * SDL_ICONV_E2BIG is returned when the output buffer is too small, or * SDL_ICONV_EILSEQ is returned when an invalid input sequence is encountered, * or SDL_ICONV_EINVAL is returned when an incomplete input sequence is @@ -5921,7 +5921,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * * \since This macro is available since SDL 3.2.0. */ -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) SDL_reinterpret_cast(Uint16 *, SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)) /** * Convert a UTF-8 string to UCS-4. @@ -5935,7 +5935,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * * \since This macro is available since SDL 3.2.0. */ -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) SDL_reinterpret_cast(Uint32 *, SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)) /** * Convert a wchar_t string to UTF-8. @@ -5949,7 +5949,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * * \since This macro is available since SDL 3.2.0. */ -#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) +#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", SDL_reinterpret_cast(const char *, S), (SDL_wcslen(S)+1)*sizeof(wchar_t)) /* force builds using Clang's static analysis tools to use literal C runtime diff --git a/thirdparty/sdl/include/SDL3/SDL_version.h b/thirdparty/sdl/include/SDL3/SDL_version.h index 435b3f95fe7..4c3b9b9645f 100644 --- a/thirdparty/sdl/include/SDL3/SDL_version.h +++ b/thirdparty/sdl/include/SDL3/SDL_version.h @@ -62,7 +62,7 @@ extern "C" { * * \since This macro is available since SDL 3.2.0. */ -#define SDL_MICRO_VERSION 16 +#define SDL_MICRO_VERSION 28 /** * This macro turns the version numbers into a numeric value. diff --git a/thirdparty/sdl/include/SDL3/SDL_video.h b/thirdparty/sdl/include/SDL3/SDL_video.h index 877b9adde59..ce40fe41777 100644 --- a/thirdparty/sdl/include/SDL3/SDL_video.h +++ b/thirdparty/sdl/include/SDL3/SDL_video.h @@ -1167,6 +1167,15 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int * Popup windows implicitly do not have a border/decorations and do not appear * on the taskbar/dock or in lists of windows such as alt-tab menus. * + * By default, popup window positions will automatically be constrained to keep + * the entire window within display bounds. This can be overridden with the + * `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN` property. + * + * By default, popup menus will automatically grab keyboard focus from the parent + * when shown. This behavior can be overridden by setting the `SDL_WINDOW_NOT_FOCUSABLE` + * flag, setting the `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN` property to false, or + * toggling it after creation via the `SDL_SetWindowFocusable()` function. + * * If a parent window is hidden or destroyed, any child popup windows will be * recursively hidden or destroyed as well. Child popup windows not explicitly * hidden will be restored when the parent is shown. @@ -1207,6 +1216,9 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren * be always on top * - `SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has no * window decoration + * - `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN`: true if the "tooltip" and + * "menu" window types should be automatically constrained to be entirely within + * display bounds (default), false if no constraints on the position are desired. * - `SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN`: true if the * window will be used with an externally managed graphics context. * - `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should @@ -1321,6 +1333,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop #define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "SDL.window.create.always_on_top" #define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "SDL.window.create.borderless" +#define SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN "SDL.window.create.constrain_popup" #define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "SDL.window.create.focusable" #define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "SDL.window.create.external_graphics_context" #define SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER "SDL.window.create.flags" @@ -1460,7 +1473,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window) * - `SDL_PROP_WINDOW_COCOA_WINDOW_POINTER`: the `(__unsafe_unretained)` * NSWindow associated with the window * - `SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag - * assocated with metal views on the window + * associated with metal views on the window * * On OpenVR: * diff --git a/thirdparty/sdl/io/SDL_iostream.c b/thirdparty/sdl/io/SDL_iostream.c index 989f3b9c4c0..7c982027dee 100644 --- a/thirdparty/sdl/io/SDL_iostream.c +++ b/thirdparty/sdl/io/SDL_iostream.c @@ -455,7 +455,8 @@ static bool SDLCALL fd_flush(void *userdata, SDL_IOStatus *status) result = SDL_fdatasync(iodata->fd); } while (result < 0 && errno == EINTR); - if (result < 0) { + // We get EINVAL when flushing a pipe, just make that a no-op + if (result < 0 && errno != EINVAL) { return SDL_SetError("Error flushing datastream: %s", strerror(errno)); } return true; diff --git a/thirdparty/sdl/joystick/SDL_gamepad.c b/thirdparty/sdl/joystick/SDL_gamepad.c index 385e890cf98..791ea213c2d 100644 --- a/thirdparty/sdl/joystick/SDL_gamepad.c +++ b/thirdparty/sdl/joystick/SDL_gamepad.c @@ -32,10 +32,11 @@ #include "hidapi/SDL_hidapi_nintendo.h" #include "../events/SDL_events_c.h" - -#ifdef SDL_PLATFORM_ANDROID +#ifdef SDL_PLATFORM_WIN32 +#include "../core/windows/SDL_windows.h" #endif + // Many gamepads turn the center button into an instantaneous button press #define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS 250 @@ -149,6 +150,51 @@ static SDL_vidpid_list SDL_ignored_gamepads = { false }; +/* + List of words in gamepad names that indicate that the gamepad should not be detected. + See also `initial_blacklist_devices` in SDL_joystick.c +*/ + +enum SDL_GamepadBlacklistWordsPosition { + GAMEPAD_BLACKLIST_BEGIN, + GAMEPAD_BLACKLIST_END, + GAMEPAD_BLACKLIST_ANYWHERE, +}; + +struct SDL_GamepadBlacklistWords { + const char* str; + enum SDL_GamepadBlacklistWordsPosition pos; +}; + +static const struct SDL_GamepadBlacklistWords SDL_gamepad_blacklist_words[] = { +#ifdef SDL_PLATFORM_LINUX + {" Motion Sensors", GAMEPAD_BLACKLIST_END}, // Don't treat the PS3 and PS4 motion controls as a separate gamepad + {" IMU", GAMEPAD_BLACKLIST_END}, // Don't treat the Nintendo IMU as a separate gamepad + {" Touchpad", GAMEPAD_BLACKLIST_END}, // "Sony Interactive Entertainment DualSense Wireless Controller Touchpad" + + // Don't treat the Wii extension controls as a separate gamepad + {" Accelerometer", GAMEPAD_BLACKLIST_END}, + {" IR", GAMEPAD_BLACKLIST_END}, + {" Motion Plus", GAMEPAD_BLACKLIST_END}, + {" Nunchuk", GAMEPAD_BLACKLIST_END}, +#endif + + // The Google Pixel fingerprint sensor, as well as other fingerprint sensors, reports itself as a joystick + {"uinput-", GAMEPAD_BLACKLIST_BEGIN}, + + {"Synaptics ", GAMEPAD_BLACKLIST_ANYWHERE}, // "Synaptics TM2768-001", "SynPS/2 Synaptics TouchPad" + {"Trackpad", GAMEPAD_BLACKLIST_ANYWHERE}, + {"Clickpad", GAMEPAD_BLACKLIST_ANYWHERE}, + // "PG-90215 Keyboard", "Usb Keyboard Usb Keyboard Consumer Control", "Framework Laptop 16 Keyboard Module - ISO System Control" + {" Keyboard", GAMEPAD_BLACKLIST_ANYWHERE}, + {" Laptop ", GAMEPAD_BLACKLIST_ANYWHERE}, // "Framework Laptop 16 Numpad Module System Control" + {"Mouse ", GAMEPAD_BLACKLIST_BEGIN}, // "Mouse passthrough" + {" Pen", GAMEPAD_BLACKLIST_END}, // "Wacom One by Wacom S Pen" + {" Finger", GAMEPAD_BLACKLIST_END}, // "Wacom HID 495F Finger" + {" LED ", GAMEPAD_BLACKLIST_ANYWHERE}, // "ASRock LED Controller" + {" Thelio ", GAMEPAD_BLACKLIST_ANYWHERE}, // "System76 Thelio Io 2" +}; + static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_GUID jGUID, const char *mappingString, bool *existing, SDL_GamepadMappingPriority priority); static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t *pGamepadMapping); static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id, bool create_mapping); @@ -311,7 +357,7 @@ void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id) { SDL_Event event; - if (!SDL_gamepads_initialized) { + if (!SDL_gamepads_initialized || SDL_IsJoystickBeingAdded()) { return; } @@ -777,7 +823,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid) if (SDL_IsJoystickSteamController(vendor, product)) { // Steam controllers have 2 back paddle buttons - SDL_strlcat(mapping_string, "paddle1:b12,paddle2:b11,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b12,", sizeof(mapping_string)); } else if (SDL_IsJoystickNintendoSwitchPro(vendor, product) || SDL_IsJoystickNintendoSwitchProInputOnly(vendor, product)) { // Nintendo Switch Pro controllers have a screenshot button @@ -913,7 +959,7 @@ static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_GUID guid, bo // An exact match, including CRC return mapping; } else if (crc && exact_match_crc) { - return NULL; + continue; } if (!best_match) { @@ -1729,17 +1775,6 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForNameAndGUID(const char * SDL_AssertJoysticksLocked(); mapping = SDL_PrivateGetGamepadMappingForGUID(guid, false); -#ifdef SDL_PLATFORM_LINUX - if (!mapping && name) { - if (SDL_strstr(name, "Xbox 360 Wireless Receiver")) { - // The Linux driver xpad.c maps the wireless dpad to buttons - bool existing; - mapping = SDL_PrivateAddMappingForGUID(guid, - "none,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT); - } - } -#endif // SDL_PLATFORM_LINUX return mapping; } @@ -1786,6 +1821,11 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char * char name_string[128]; char mapping[1024]; + // Remove the CRC from the GUID + // We already know that this GUID doesn't have a mapping without the CRC, and we want newly + // added mappings without a CRC to override this mapping. + SDL_SetJoystickGUIDCRC(&guid, 0); + // Remove any commas in the name SDL_strlcpy(name_string, name, sizeof(name_string)); { @@ -2660,35 +2700,37 @@ bool SDL_IsGamepad(SDL_JoystickID instance_id) */ bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) { -#ifdef SDL_PLATFORM_LINUX - if (SDL_endswith(name, " Motion Sensors")) { - // Don't treat the PS3 and PS4 motion controls as a separate gamepad - return true; - } - if (SDL_strncmp(name, "Nintendo ", 9) == 0 && SDL_strstr(name, " IMU") != NULL) { - // Don't treat the Nintendo IMU as a separate gamepad - return true; - } - if (SDL_endswith(name, " Accelerometer") || - SDL_endswith(name, " IR") || - SDL_endswith(name, " Motion Plus") || - SDL_endswith(name, " Nunchuk")) { - // Don't treat the Wii extension controls as a separate gamepad - return true; - } -#endif + int i; + for (i = 0; i < SDL_arraysize(SDL_gamepad_blacklist_words); i++) { + const struct SDL_GamepadBlacklistWords *blacklist_word = &SDL_gamepad_blacklist_words[i]; - if (name && SDL_strcmp(name, "uinput-fpc") == 0) { - // The Google Pixel fingerprint sensor reports itself as a joystick - return true; + switch (blacklist_word->pos) { + case GAMEPAD_BLACKLIST_BEGIN: + if (SDL_startswith(name, blacklist_word->str)) { + return true; + } + break; + + case GAMEPAD_BLACKLIST_END: + if (SDL_endswith(name, blacklist_word->str)) { + return true; + } + break; + + case GAMEPAD_BLACKLIST_ANYWHERE: + if (SDL_strstr(name, blacklist_word->str) != NULL) { + return true; + } + break; + } } #ifdef SDL_PLATFORM_WIN32 if (SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", false) && - SDL_GetHintBoolean("STEAM_COMPAT_PROTON", false)) { - // We are launched by Steam and running under Proton + WIN_IsWine()) { + // We are launched by Steam and running under Proton or Wine // We can't tell whether this controller is a Steam Virtual Gamepad, - // so assume that Proton is doing the appropriate filtering of controllers + // so assume that is doing the appropriate filtering of controllers // and anything we see here is fine to use. return false; } diff --git a/thirdparty/sdl/joystick/SDL_gamepad_db.h b/thirdparty/sdl/joystick/SDL_gamepad_db.h index a0f8ea8e891..d5c04384d72 100644 --- a/thirdparty/sdl/joystick/SDL_gamepad_db.h +++ b/thirdparty/sdl/joystick/SDL_gamepad_db.h @@ -215,7 +215,7 @@ static const char *s_GamepadMappings[] = { "03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,", "03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,", "030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,", - "0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:-a5,start:b11,x:b3,y:b4,", + "0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", "03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,", "030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", "03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", @@ -339,6 +339,7 @@ static const char *s_GamepadMappings[] = { "03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,", "03000000c0160000e105000000000000,Xin-Mo Dual Arcade,crc:2246,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */ "03000000790000004f18000000000000,ZD-T Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", + "03000000073500000400000000000000,ZENAIM ARCADE CONTROLLER,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,", "03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", @@ -416,12 +417,13 @@ static const char *s_GamepadMappings[] = { "03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,", "0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,", "03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,", + "03000000853200008906000000010000,NACON Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,", "03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,", "030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,", "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:a5,start:b11,x:b3,y:b4,", + "0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", "030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", "030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", @@ -480,6 +482,7 @@ static const char *s_GamepadMappings[] = { "030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,", "03000000c0160000e105000000040000,Xin-Mo Dual Arcade,crc:82d5,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,", /* Ultimate Atari Fight Stick */ + "03000000073500000400000000010000,ZENAIM ARCADE CONTROLLER,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,", "03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", @@ -501,6 +504,7 @@ static const char *s_GamepadMappings[] = { "06000000c82d00000020000006010000,8BitDo Pro 2 Wired Controller for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", + "03000000c82d00000960000011010000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000102800000900000000010000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00003028000000010000,8BitDo SFC30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", @@ -536,7 +540,6 @@ static const char *s_GamepadMappings[] = { "03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,", "05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,", "05000000503200000210000000000000128804098,Atari Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,", - "030000005e0400008e02000047010000,Atari Xbox 360 Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:,lefty:,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:,righty:,start:b9,x:b0,y:b3,", @@ -626,8 +629,6 @@ static const char *s_GamepadMappings[] = { "03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,", "03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,", "030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,", - "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,", @@ -742,8 +743,6 @@ static const char *s_GamepadMappings[] = { "03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "03000000632500002305000010010000,ShanWan USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,", - "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,", "03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", @@ -780,22 +779,17 @@ static const char *s_GamepadMappings[] = { "030000006f0e00000702000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", "030000000d0f0000ab01000011010000,Wireless HORIPAD For Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,misc3:b16,misc4:b17,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "050000000d0f00009601000091000000,Wireless HORIPAD For Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,misc3:b16,misc4:b17,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", - "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,", - "030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,", "050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,", "03000000c0160000e105000010010000,Xin-Mo Dual Arcade,crc:82d5,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */ + "03000000073500000400000011010000,ZENAIM ARCADE CONTROLLER,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", + "03000000120c0000182e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", "03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", diff --git a/thirdparty/sdl/joystick/SDL_joystick.c b/thirdparty/sdl/joystick/SDL_joystick.c index f36ca95baad..090dc07303a 100644 --- a/thirdparty/sdl/joystick/SDL_joystick.c +++ b/thirdparty/sdl/joystick/SDL_joystick.c @@ -277,7 +277,10 @@ static Uint32 initial_blacklist_devices[] = { MAKE_VIDPID(0x1532, 0x0282), // Razer Huntsman Mini Analog, non-functional DInput device MAKE_VIDPID(0x26ce, 0x01a2), // ASRock LED Controller MAKE_VIDPID(0x20d6, 0x0002), // PowerA Enhanced Wireless Controller for Nintendo Switch (charging port only) + MAKE_VIDPID(0x31e3, 0x1310), // Wooting 60HE (ARM) + MAKE_VIDPID(0x3297, 0x1969), // Moonlander MK1 Keyboard MAKE_VIDPID(0x3434, 0x0211), // Keychron K1 Pro System Control + MAKE_VIDPID(0x04f2, 0xa13c), // HP Deluxe Webcam KQ246AA }; static SDL_vidpid_list blacklist_devices = { SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL, @@ -2139,6 +2142,7 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id) SDL_JoystickDriver *driver; int device_index; int player_index = -1; + bool is_gamepad; SDL_AssertJoysticksLocked(); @@ -2173,9 +2177,12 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id) } } + // This might create an automatic gamepad mapping, so wait to send the event + is_gamepad = SDL_IsGamepad(instance_id); + SDL_joystick_being_added = false; - if (SDL_IsGamepad(instance_id)) { + if (is_gamepad) { SDL_PrivateGamepadAdded(instance_id); } } @@ -2491,7 +2498,7 @@ void SDL_UpdateJoysticks(void) Uint64 now; SDL_Joystick *joystick; - if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { + if (!SDL_joysticks_initialized) { return; } diff --git a/thirdparty/sdl/joystick/SDL_steam_virtual_gamepad.c b/thirdparty/sdl/joystick/SDL_steam_virtual_gamepad.c index 6b253de3a04..e4461066400 100644 --- a/thirdparty/sdl/joystick/SDL_steam_virtual_gamepad.c +++ b/thirdparty/sdl/joystick/SDL_steam_virtual_gamepad.c @@ -23,6 +23,9 @@ #include "SDL_joystick_c.h" #include "SDL_steam_virtual_gamepad.h" +#ifdef SDL_PLATFORM_LINUX +#include "../core/unix/SDL_appid.h" +#endif #ifdef SDL_PLATFORM_WIN32 #include "../core/windows/SDL_windows.h" #else @@ -134,6 +137,15 @@ void SDL_InitSteamVirtualGamepadInfo(void) file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE); if (file && *file) { +#ifdef SDL_PLATFORM_LINUX + // Older versions of Wine will blacklist the Steam Virtual Gamepad if + // it appears to have the real controller's VID/PID, so ignore this. + const char *exe = SDL_GetExeName(); + if (exe && SDL_strcmp(exe, "wine64-preloader") == 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Wine launched by Steam, ignoring %s", SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE); + return; + } +#endif SDL_steam_virtual_gamepad_info_file = SDL_strdup(file); } SDL_UpdateSteamVirtualGamepadInfo(); diff --git a/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m b/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m index 2ba2cbeae64..48e9051798c 100644 --- a/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m +++ b/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m @@ -300,15 +300,15 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle * struct, and ARC doesn't work with structs. */ device->controller = (__bridge GCController *)CFBridgingRetain(controller); - if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { - if (controller.productCategory) { - name = controller.productCategory.UTF8String; - } - } else { - if (controller.vendorName) { - name = controller.vendorName.UTF8String; - } - } + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { + if (controller.productCategory) { + name = controller.productCategory.UTF8String; + } + } else { + if (controller.vendorName) { + name = controller.vendorName.UTF8String; + } + } if (!name) { name = "MFi Gamepad"; diff --git a/thirdparty/sdl/joystick/controller_list.h b/thirdparty/sdl/joystick/controller_list.h index 5a62ece1c37..0fedb651aa9 100644 --- a/thirdparty/sdl/joystick/controller_list.h +++ b/thirdparty/sdl/joystick/controller_list.h @@ -21,7 +21,6 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x0079, 0x181a ), k_eControllerType_PS3Controller, NULL }, // Venom Arcade Stick - { MAKE_CONTROLLER_ID( 0x0079, 0x1844 ), k_eControllerType_PS3Controller, NULL }, // From SDL { MAKE_CONTROLLER_ID( 0x044f, 0xb315 ), k_eControllerType_PS3Controller, NULL }, // Firestorm Dual Analog 3 { MAKE_CONTROLLER_ID( 0x044f, 0xd007 ), k_eControllerType_PS3Controller, NULL }, // Thrustmaster wireless 3-1 { MAKE_CONTROLLER_ID( 0x046d, 0xcad1 ), k_eControllerType_PS3Controller, NULL }, // Logitech Chillstream @@ -96,6 +95,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x0c12, 0x0ef6 ), k_eControllerType_PS4Controller, NULL }, // Hitbox Arcade Stick { MAKE_CONTROLLER_ID( 0x0c12, 0x1cf6 ), k_eControllerType_PS4Controller, NULL }, // EMIO PS4 Elite Controller { MAKE_CONTROLLER_ID( 0x0c12, 0x1e10 ), k_eControllerType_PS4Controller, NULL }, // P4 Wired Gamepad generic knock off - lightbar but not trackpad or gyro + { MAKE_CONTROLLER_ID( 0x0c12, 0x2e18 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad { MAKE_CONTROLLER_ID( 0x0e6f, 0x0203 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS (PS4 peripheral but no trackpad/lightbar) { MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS V2 w/ Touchpad for PS4 { MAKE_CONTROLLER_ID( 0x0e6f, 0x020a ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS4 mode) @@ -435,7 +435,8 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x24c6, 0x592a ), k_eControllerType_XBoxOneController, NULL }, // BDA XB1 Spectra Pro { MAKE_CONTROLLER_ID( 0x24c6, 0x791a ), k_eControllerType_XBoxOneController, NULL }, // PowerA Fusion Fight Pad { MAKE_CONTROLLER_ID( 0x2dc8, 0x2002 ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate Wired Controller for Xbox - { MAKE_CONTROLLER_ID( 0x2dc8, 0x3106 ), k_eControllerType_XBoxOneController, NULL }, // 8Bitdo Ultimate Wired Controller. Windows, Android, Switch. + { MAKE_CONTROLLER_ID( 0x2dc8, 0x3106 ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate Wired Controller. Windows, Android, Switch. + { MAKE_CONTROLLER_ID( 0x2dc8, 0x310a ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate 2C Wireless Controller { MAKE_CONTROLLER_ID( 0x2e24, 0x0652 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin Duke { MAKE_CONTROLLER_ID( 0x2e24, 0x1618 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin Duke { MAKE_CONTROLLER_ID( 0x2e24, 0x1688 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin X91 diff --git a/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick.c b/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick.c index 9327276a427..e87ab8243ca 100644 --- a/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick.c +++ b/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick.c @@ -27,6 +27,7 @@ #include "SDL_iokitjoystick_c.h" #include "../hidapi/SDL_hidapijoystick_c.h" #include "../../haptic/darwin/SDL_syshaptic_c.h" // For haptic hot plugging +#include "../usb_ids.h" #define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick") @@ -213,6 +214,29 @@ static bool GetHIDScaledCalibratedState(recDevice *pDevice, recElement *pElement return result; } +static bool GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(recDevice *pDevice, recElement *pElement, SInt32 min, SInt32 max, SInt32 *pValue) +{ + if (pElement->minReport == 0 && pElement->maxReport == 255) { + return GetHIDScaledCalibratedState(pDevice, pElement, min, max, pValue); + } + + // This device thumbstick axes have an unusual axis range that + // doesn't work with GetHIDScaledCalibratedState() above. + // + // See https://github.com/libsdl-org/SDL/issues/13143 for details + if (GetHIDElementState(pDevice, pElement, pValue)) { + if (*pValue >= 0) { + // Negative axis values range from 32767 (at rest) to 0 (minimum) + *pValue = -32767 + *pValue; + } else if (*pValue < 0) { + // Positive axis values range from -32768 (at rest) to 0 (maximum) + *pValue = 32768 + *pValue; + } + return true; + } + return false; +} + static void JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender) { recDevice *device = (recDevice *)ctx; @@ -506,6 +530,11 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0); pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string); + if (vendor == USB_VENDOR_NACON_ALT && + product == USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT) { + pDevice->nacon_revolution_x_unlimited = true; + } + array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); if (array) { AddHIDElements(array, pDevice); @@ -957,7 +986,11 @@ static void DARWIN_JoystickUpdate(SDL_Joystick *joystick) i = 0; while (element) { - goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value); + if (device->nacon_revolution_x_unlimited) { + goodRead = GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(device, element, -32768, 32767, &value); + } else { + goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value); + } if (goodRead) { SDL_SendJoystickAxis(timestamp, joystick, i, value); } diff --git a/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick_c.h b/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick_c.h index 91deb240e47..3a70d2bde1d 100644 --- a/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick_c.h +++ b/thirdparty/sdl/joystick/darwin/SDL_iokitjoystick_c.h @@ -72,6 +72,7 @@ struct joystick_hwdata int instance_id; SDL_GUID guid; int steam_virtual_gamepad_slot; + bool nacon_revolution_x_unlimited; struct joystick_hwdata *pNext; // next device }; diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_gamecube.c b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_gamecube.c index 4d45c7a264d..c03d92702eb 100644 --- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_gamecube.c @@ -31,7 +31,9 @@ #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE // Define this if you want to log all packets from the controller -// #define DEBUG_GAMECUBE_PROTOCOL +#if 0 +#define DEBUG_GAMECUBE_PROTOCOL +#endif #define MAX_CONTROLLERS 4 @@ -119,22 +121,15 @@ static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) } device->context = ctx; - ctx->joysticks[0] = 0; - ctx->joysticks[1] = 0; - ctx->joysticks[2] = 0; - ctx->joysticks[3] = 0; ctx->rumble[0] = rumbleMagic; - ctx->useRumbleBrake = false; if (device->vendor_id != USB_VENDOR_NINTENDO) { ctx->pc_mode = true; } if (ctx->pc_mode) { - for (i = 0; i < MAX_CONTROLLERS; ++i) { - ResetAxisRange(ctx, i); - HIDAPI_JoystickConnected(device, &ctx->joysticks[i]); - } + ResetAxisRange(ctx, 0); + HIDAPI_JoystickConnected(device, &ctx->joysticks[0]); } else { // This is all that's needed to initialize the device. Really! if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) { @@ -204,69 +199,61 @@ static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device { } -static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, int size) +static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, bool invert_c_stick) { SDL_Joystick *joystick; - Uint8 i, v; + const Uint8 i = 0; // We have a separate context for each connected controller in PC mode, just use the first index + Uint8 v; Sint16 axis_value; Uint64 timestamp = SDL_GetTicksNS(); - if (size != 10) { - return; // How do we handle this packet? - } - - i = packet[0] - 1; - if (i >= MAX_CONTROLLERS) { - return; // How do we handle this packet? - } - joystick = SDL_GetJoystickFromID(ctx->joysticks[i]); if (!joystick) { // Hasn't been opened yet, skip return; } -#define READ_BUTTON(off, flag, button) \ - SDL_SendJoystickButton( \ - timestamp, \ - joystick, \ - button, \ +#define READ_BUTTON(off, flag, button) \ + SDL_SendJoystickButton( \ + timestamp, \ + joystick, \ + button, \ ((packet[off] & flag) != 0)); - READ_BUTTON(1, 0x02, 0) // A - READ_BUTTON(1, 0x04, 1) // B - READ_BUTTON(1, 0x08, 3) // Y - READ_BUTTON(1, 0x01, 2) // X - READ_BUTTON(2, 0x80, 4) // DPAD_LEFT - READ_BUTTON(2, 0x20, 5) // DPAD_RIGHT - READ_BUTTON(2, 0x40, 6) // DPAD_DOWN - READ_BUTTON(2, 0x10, 7) // DPAD_UP - READ_BUTTON(2, 0x02, 8) // START - READ_BUTTON(1, 0x80, 9) // RIGHTSHOULDER + READ_BUTTON(0, 0x02, 0) // A + READ_BUTTON(0, 0x04, 1) // B + READ_BUTTON(0, 0x08, 3) // Y + READ_BUTTON(0, 0x01, 2) // X + READ_BUTTON(1, 0x80, 4) // DPAD_LEFT + READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT + READ_BUTTON(1, 0x40, 6) // DPAD_DOWN + READ_BUTTON(1, 0x10, 7) // DPAD_UP + READ_BUTTON(1, 0x02, 8) // START + READ_BUTTON(0, 0x80, 9) // RIGHTSHOULDER /* These two buttons are for the bottoms of the analog triggers. * More than likely, you're going to want to read the axes instead! * -flibit */ - READ_BUTTON(1, 0x20, 10) // TRIGGERRIGHT - READ_BUTTON(1, 0x10, 11) // TRIGGERLEFT + READ_BUTTON(0, 0x20, 10) // TRIGGERRIGHT + READ_BUTTON(0, 0x10, 11) // TRIGGERLEFT #undef READ_BUTTON -#define READ_AXIS(off, axis, invert) \ - v = invert ? (0xff - packet[off]) : packet[off]; \ - if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ - ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ - if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ - ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ +#define READ_AXIS(off, axis, invert) \ + v = (invert) ? (0xff - packet[off]) : packet[off]; \ + if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ + ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ + if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ + ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ axis_value = (Sint16)HIDAPI_RemapVal(v, ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \ - SDL_SendJoystickAxis( \ - timestamp, \ - joystick, \ + SDL_SendJoystickAxis( \ + timestamp, \ + joystick, \ axis, axis_value); - READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0) - READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1) - READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0) - READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1) - READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) - READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) + READ_AXIS(2, SDL_GAMEPAD_AXIS_LEFTX, 0) + READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTY, 1) + READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX, invert_c_stick ? 1 : 0) + READ_AXIS(4, SDL_GAMEPAD_AXIS_RIGHTY, invert_c_stick ? 0 : 1) + READ_AXIS(6, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) + READ_AXIS(7, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) #undef READ_AXIS } @@ -365,7 +352,18 @@ static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device) HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size); #endif if (ctx->pc_mode) { - HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size); + if (size == 10) { + // This is the older firmware + // The first byte is the index of the connected controller + // The C stick has an inverted value range compared to the left stick + HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, &packet[1], true); + } else if (size == 9) { + // This is the newer firmware (version 0x7) + // The C stick has the same value range compared to the left stick + HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, false); + } else { + // How do we handle this packet? + } } else { HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size); } diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c index e40170086e0..1abde084949 100644 --- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c +++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c @@ -251,6 +251,7 @@ typedef struct Uint64 last_packet; int player_index; bool player_lights; + bool enhanced_rumble; Uint8 rumble_left; Uint8 rumble_right; bool color_set; @@ -432,6 +433,14 @@ static bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) } } + if (device->vendor_id == USB_VENDOR_SONY) { + if (device->product_id == USB_PRODUCT_SONY_DS5_EDGE || + ctx->firmware_version == 0 || // Assume that it's updated firmware over Bluetooth + ctx->firmware_version >= 0x0224) { + ctx->enhanced_rumble = true; + } + } + // Get the device capabilities if (device->vendor_id == USB_VENDOR_SONY) { ctx->sensors_supported = true; @@ -684,17 +693,17 @@ static bool HIDAPI_DriverPS5_UpdateEffects(SDL_DriverPS5_Context *ctx, int effec if (ctx->vibration_supported) { if (ctx->rumble_left || ctx->rumble_right) { - if (ctx->firmware_version < 0x0224) { + if (ctx->enhanced_rumble) { + effects.ucEnableBits3 |= 0x04; // Enable improved rumble emulation on 2.24 firmware and newer + + effects.ucRumbleLeft = ctx->rumble_left; + effects.ucRumbleRight = ctx->rumble_right; + } else { effects.ucEnableBits1 |= 0x01; // Enable rumble emulation // Shift to reduce effective rumble strength to match Xbox controllers effects.ucRumbleLeft = ctx->rumble_left >> 1; effects.ucRumbleRight = ctx->rumble_right >> 1; - } else { - effects.ucEnableBits3 |= 0x04; // Enable improved rumble emulation on 2.24 firmware and newer - - effects.ucRumbleLeft = ctx->rumble_left; - effects.ucRumbleRight = ctx->rumble_right; } effects.ucEnableBits1 |= 0x02; // Disable audio haptics } else { @@ -812,14 +821,19 @@ static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx } if (ctx->sensors_supported) { + // Standard DualSense sensor update rate is 250 Hz over USB + float update_rate = 250.0f; + if (ctx->device->is_bluetooth) { // Bluetooth sensor update rate appears to be 1000 Hz - SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 1000.0f); - SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 1000.0f); - } else { - SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 250.0f); - SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 250.0f); + update_rate = 1000.0f; + } else if (SDL_IsJoystickDualSenseEdge(ctx->device->vendor_id, ctx->device->product_id)) { + // DualSense Edge sensor update rate is 1000 Hz over USB + update_rate = 1000.0f; } + + SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, update_rate); + SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, update_rate); } ctx->report_battery = true; @@ -1033,6 +1047,9 @@ static bool HIDAPI_DriverPS5_InternalSendJoystickEffect(SDL_DriverPS5_Context *c if (!ctx->enhanced_mode) { if (application_usage) { HIDAPI_DriverPS5_UpdateEnhancedModeOnApplicationUsage(ctx); + + // Wait briefly before sending additional effects + SDL_Delay(10); } if (!ctx->enhanced_mode) { diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_rumble.h b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_rumble.h index ede061e0cf2..0442448dcd9 100644 --- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_rumble.h +++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_rumble.h @@ -28,7 +28,7 @@ #ifdef SDL_THREAD_SAFETY_ANALYSIS extern SDL_Mutex *SDL_HIDAPI_rumble_lock; #endif -bool SDL_HIDAPI_LockRumble(void) SDL_TRY_ACQUIRE(0, SDL_HIDAPI_rumble_lock); +bool SDL_HIDAPI_LockRumble(void) SDL_TRY_ACQUIRE(true, SDL_HIDAPI_rumble_lock); bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size); int SDL_HIDAPI_SendRumbleAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size) SDL_RELEASE(SDL_HIDAPI_rumble_lock); typedef void (*SDL_HIDAPI_RumbleSentCallback)(void *userdata); diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_steam.c b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_steam.c index b48d35393b1..38180189d95 100644 --- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_steam.c +++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_steam.c @@ -706,13 +706,6 @@ static void RotatePad(int *pX, int *pY, float flAngleInRad) *pX = (int)(SDL_cosf(flAngleInRad) * origX - SDL_sinf(flAngleInRad) * origY); *pY = (int)(SDL_sinf(flAngleInRad) * origX + SDL_cosf(flAngleInRad) * origY); } -static void RotatePadShort(short *pX, short *pY, float flAngleInRad) -{ - int origX = *pX, origY = *pY; - - *pX = (short)(SDL_cosf(flAngleInRad) * origX - SDL_sinf(flAngleInRad) * origY); - *pY = (short)(SDL_sinf(flAngleInRad) * origX + SDL_cosf(flAngleInRad) * origY); -} //--------------------------------------------------------------------------- // Format the first part of the state packet @@ -836,9 +829,16 @@ static void FormatStatePacketUntilGyro(SteamControllerStateInternal_t *pState, V //--------------------------------------------------------------------------- static bool UpdateBLESteamControllerState(const uint8_t *pData, int nDataSize, SteamControllerStateInternal_t *pState) { - const float flRotationAngle = 0.261799f; + int nLeftPadX; + int nLeftPadY; + int nRightPadX; + int nRightPadY; + int nPadOffset; uint32_t ucOptionDataMask; + // 15 degrees in rad + const float flRotationAngle = 0.261799f; + pState->unPacketNum++; ucOptionDataMask = (*pData++ & 0xF0); ucOptionDataMask |= (uint32_t)(*pData++) << 8; @@ -867,7 +867,6 @@ static bool UpdateBLESteamControllerState(const uint8_t *pData, int nDataSize, S } if (ucOptionDataMask & k_EBLELeftTrackpadChunk) { int nLength = sizeof(pState->sLeftPadX) + sizeof(pState->sLeftPadY); - int nPadOffset; SDL_memcpy(&pState->sLeftPadX, pData, nLength); if (pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK) { nPadOffset = 1000; @@ -875,14 +874,15 @@ static bool UpdateBLESteamControllerState(const uint8_t *pData, int nDataSize, S nPadOffset = 0; } - RotatePadShort(&pState->sLeftPadX, &pState->sLeftPadY, -flRotationAngle); - pState->sLeftPadX = (short)clamp(pState->sLeftPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); - pState->sLeftPadY = (short)clamp(pState->sLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); + nLeftPadX = pState->sLeftPadX; + nLeftPadY = pState->sLeftPadY; + RotatePad(&nLeftPadX, &nLeftPadY, -flRotationAngle); + pState->sLeftPadX = (short)clamp(nLeftPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); + pState->sLeftPadY = (short)clamp(nLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); pData += nLength; } if (ucOptionDataMask & k_EBLERightTrackpadChunk) { int nLength = sizeof(pState->sRightPadX) + sizeof(pState->sRightPadY); - int nPadOffset = 0; SDL_memcpy(&pState->sRightPadX, pData, nLength); @@ -892,9 +892,11 @@ static bool UpdateBLESteamControllerState(const uint8_t *pData, int nDataSize, S nPadOffset = 0; } - RotatePadShort(&pState->sRightPadX, &pState->sRightPadY, flRotationAngle); - pState->sRightPadX = (short)clamp(pState->sRightPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); - pState->sRightPadY = (short)clamp(pState->sRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); + nRightPadX = pState->sRightPadX; + nRightPadY = pState->sRightPadY; + RotatePad(&nRightPadX, &nRightPadY, flRotationAngle); + pState->sRightPadX = (short)clamp(nRightPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); + pState->sRightPadY = (short)clamp(nRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); pData += nLength; } if (ucOptionDataMask & k_EBLEIMUAccelChunk) { @@ -1038,6 +1040,11 @@ static bool HIDAPI_DriverSteam_IsSupportedDevice(SDL_HIDAPI_Device *device, cons return false; } + if (!device) { + // Might be supported by this driver, enumerate and find out + return true; + } + if (device->is_bluetooth) { return true; } diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_switch.c b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_switch.c index 0e7b823c552..8585b2847a4 100644 --- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_switch.c +++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_switch.c @@ -58,9 +58,7 @@ #define SWITCH_GYRO_SCALE 14.2842f #define SWITCH_ACCEL_SCALE 4096.f -#define SWITCH_GYRO_SCALE_OFFSET 13371.0f #define SWITCH_GYRO_SCALE_MULT 936.0f -#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f #define SWITCH_ACCEL_SCALE_MULT 4.0f enum @@ -161,20 +159,21 @@ typedef struct Uint8 ucVibrationCode; } SwitchControllerStatePacket_t; +typedef struct +{ + Sint16 sAccelX; + Sint16 sAccelY; + Sint16 sAccelZ; + + Sint16 sGyroX; + Sint16 sGyroY; + Sint16 sGyroZ; +} SwitchControllerIMUState_t; + typedef struct { SwitchControllerStatePacket_t controllerState; - - struct - { - Sint16 sAccelX; - Sint16 sAccelY; - Sint16 sAccelZ; - - Sint16 sGyroX; - Sint16 sGyroY; - Sint16 sGyroZ; - } imuState[3]; + SwitchControllerIMUState_t imuState[3]; } SwitchStatePacket_t; typedef struct @@ -390,7 +389,7 @@ static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int siz #endif // SWITCH_SYNCHRONOUS_WRITES } -static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID) +static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID, const Uint8 *pBuf, Uint8 ucLen) { // Average response time for messages is ~30ms Uint64 endTicks = SDL_GetTicks() + 100; @@ -400,9 +399,17 @@ static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Conte if (nRead > 0) { if (ctx->m_rgucReadBuffer[0] == k_eSwitchInputReportIDs_SubcommandReply) { SwitchSubcommandInputPacket_t *reply = (SwitchSubcommandInputPacket_t *)&ctx->m_rgucReadBuffer[1]; - if (reply->ucSubcommandID == expectedID && (reply->ucSubcommandAck & 0x80)) { - return reply; + if (reply->ucSubcommandID != expectedID || !(reply->ucSubcommandAck & 0x80)) { + continue; } + if (reply->ucSubcommandID == k_eSwitchSubcommandIDs_SPIFlashRead) { + SDL_assert(ucLen == sizeof(reply->spiReadData.opData)); + if (SDL_memcmp(&reply->spiReadData.opData, pBuf, ucLen) != 0) { + // This was a reply for another SPI read command + continue; + } + } + return reply; } } else { SDL_Delay(1); @@ -489,7 +496,7 @@ static bool WriteSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs continue; } - reply = ReadSubcommandReply(ctx, ucCommandID); + reply = ReadSubcommandReply(ctx, ucCommandID, pBuf, ucLen); } if (ppReply) { @@ -930,13 +937,14 @@ static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled) static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx) { - Uint8 *pLeftStickCal; - Uint8 *pRightStickCal; + Uint8 *pLeftStickCal = NULL; + Uint8 *pRightStickCal = NULL; size_t stick, axis; SwitchSubcommandInputPacket_t *user_reply = NULL; SwitchSubcommandInputPacket_t *factory_reply = NULL; SwitchSPIOpData_t readUserParams; SwitchSPIOpData_t readFactoryParams; + Uint8 userParamsReadSuccessCount = 0; // Read User Calibration Info readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset; @@ -949,33 +957,46 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx) readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset; readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength; - const int MAX_ATTEMPTS = 3; - for (int attempt = 0; ; ++attempt) { - if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) { - return false; - } - - if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) { - // We successfully read the calibration data - break; - } - - if (attempt == MAX_ATTEMPTS) { - return false; - } - } - // Automatically select the user calibration if magic bytes are set if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) { + userParamsReadSuccessCount += 1; pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration; - } else { - pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration; } if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) { + userParamsReadSuccessCount += 1; pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration; - } else { - pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration; + } + + // Only read the factory calibration info if we failed to receive the correct magic bytes + if (userParamsReadSuccessCount < 2) { + // Read Factory Calibration Info + readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset; + readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength; + + const int MAX_ATTEMPTS = 3; + for (int attempt = 0;; ++attempt) { + if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) { + return false; + } + + if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) { + // We successfully read the calibration data + pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration; + pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration; + break; + } + + if (attempt == MAX_ATTEMPTS) { + return false; + } + } + } + + // If we still don't have calibration data, return false + if (pLeftStickCal == NULL || pRightStickCal == NULL) + { + return false; } /* Stick calibration values are 12-bits each and are packed by bit @@ -1044,6 +1065,8 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx) if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply)) { Uint8 *pIMUScale; Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ; + Sint16 sAccelSensCoeffX, sAccelSensCoeffY, sAccelSensCoeffZ; + Sint16 sGyroSensCoeffX, sGyroSensCoeffY, sGyroSensCoeffZ; // IMU scale gives us multipliers for converting raw values to real world values pIMUScale = reply->spiReadData.rgucReadData; @@ -1052,10 +1075,18 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx) sAccelRawY = (pIMUScale[3] << 8) | pIMUScale[2]; sAccelRawZ = (pIMUScale[5] << 8) | pIMUScale[4]; + sAccelSensCoeffX = (pIMUScale[7] << 8) | pIMUScale[6]; + sAccelSensCoeffY = (pIMUScale[9] << 8) | pIMUScale[8]; + sAccelSensCoeffZ = (pIMUScale[11] << 8) | pIMUScale[10]; + sGyroRawX = (pIMUScale[13] << 8) | pIMUScale[12]; sGyroRawY = (pIMUScale[15] << 8) | pIMUScale[14]; sGyroRawZ = (pIMUScale[17] << 8) | pIMUScale[16]; + sGyroSensCoeffX = (pIMUScale[19] << 8) | pIMUScale[18]; + sGyroSensCoeffY = (pIMUScale[21] << 8) | pIMUScale[20]; + sGyroSensCoeffZ = (pIMUScale[23] << 8) | pIMUScale[22]; + // Check for user calibration data. If it's present and set, it'll override the factory settings readParams.unAddress = k_unSPIIMUUserScaleStartOffset; readParams.ucLength = k_unSPIIMUUserScaleLength; @@ -1072,14 +1103,14 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx) } // Accelerometer scale - ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawX) * SDL_STANDARD_GRAVITY; - ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawY) * SDL_STANDARD_GRAVITY; - ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY; + ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY; + ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY; + ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY; // Gyro scale - ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawX) * SDL_PI_F / 180.0f; - ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawY) * SDL_PI_F / 180.0f; - ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawZ) * SDL_PI_F / 180.0f; + ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * SDL_PI_F / 180.0f; + ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * SDL_PI_F / 180.0f; + ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * SDL_PI_F / 180.0f; } else { // Use default values @@ -1101,14 +1132,17 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i { sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter; - if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) { - ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue; + if (sRawValue >= 0) { + if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) { + ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16); + } else { + if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) { + ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0); } - if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) { - ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue; - } - - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue) @@ -1118,14 +1152,17 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt sRawValue -= usJoystickCenter; - if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) { - ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue; + if (sRawValue >= 0) { + if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) { + ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16); + } else { + if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) { + ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue; + } + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0); } - if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) { - ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue; - } - - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button) @@ -2561,9 +2598,14 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C SDL_SendJoystickPowerInfo(joystick, state, percent); if (ctx->m_bReportSensors) { - bool bHasSensorData = (packet->imuState[0].sAccelZ != 0 || - packet->imuState[0].sAccelY != 0 || - packet->imuState[0].sAccelX != 0); + // Need to copy the imuState to an aligned variable + SwitchControllerIMUState_t imuState[3]; + SDL_assert(sizeof(imuState) == sizeof(packet->imuState)); + SDL_memcpy(imuState, packet->imuState, sizeof(imuState)); + + bool bHasSensorData = (imuState[0].sAccelZ != 0 || + imuState[0].sAccelY != 0 || + imuState[0].sAccelX != 0); if (bHasSensorData) { const Uint32 IMU_UPDATE_RATE_SAMPLE_FREQUENCY = 1000; Uint64 sensor_timestamp[3]; @@ -2592,37 +2634,37 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C if (!ctx->device->parent || ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[0], &packet->imuState[2].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[0], &packet->imuState[2].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[0], &imuState[2].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[0], &imuState[2].sAccelX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[1], &packet->imuState[1].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[1], &packet->imuState[1].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[1], &imuState[1].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[1], &imuState[1].sAccelX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[2], &packet->imuState[0].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[2], &packet->imuState[0].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[2], &imuState[0].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[2], &imuState[0].sAccelX); } if (ctx->device->parent && ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) { - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[0], &packet->imuState[2].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[0], &packet->imuState[2].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[0], &imuState[2].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[0], &imuState[2].sAccelX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[1], &packet->imuState[1].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[1], &packet->imuState[1].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[1], &imuState[1].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[1], &imuState[1].sAccelX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[2], &packet->imuState[0].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[2], &packet->imuState[0].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[2], &imuState[0].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[2], &imuState[0].sAccelX); } if (ctx->device->parent && ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[0], &packet->imuState[2].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[0], &packet->imuState[2].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[0], &imuState[2].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[0], &imuState[2].sAccelX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[1], &packet->imuState[1].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[1], &packet->imuState[1].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[1], &imuState[1].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[1], &imuState[1].sAccelX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[2], &packet->imuState[0].sGyroX); - SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[2], &packet->imuState[0].sAccelX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[2], &imuState[0].sGyroX); + SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[2], &imuState[0].sAccelX); } } else if (ctx->m_bHasSensorData) { diff --git a/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c b/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c index ea73821c064..7d936d4cf51 100644 --- a/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c +++ b/thirdparty/sdl/joystick/linux/SDL_sysjoystick.c @@ -150,6 +150,8 @@ typedef struct SDL_joylist_item { SDL_JoystickID device_instance; char *path; // "/dev/input/event2" or whatever + Uint16 vendor; + Uint16 product; char *name; // "SideWinder 3D Pro" or whatever SDL_GUID guid; dev_t devnum; @@ -486,6 +488,8 @@ static void MaybeAddDevice(const char *path) item->devnum = sb.st_rdev; item->steam_virtual_gamepad_slot = -1; item->path = SDL_strdup(path); + item->vendor = vendor; + item->product = product; item->name = name; item->guid = guid; @@ -1844,6 +1848,20 @@ static void PollAllValues(Uint64 timestamp, SDL_Joystick *joystick) // Joyballs are relative input, so there's no poll state. Events only! } +static void CorrectSensorData(struct joystick_hwdata *hwdata, float *values, float *data) +{ + if (hwdata->item->vendor == USB_VENDOR_NINTENDO) { + // The Nintendo driver uses a different axis order than SDL + data[0] = -values[1]; + data[1] = values[2]; + data[2] = -values[0]; + } else { + data[0] = values[0]; + data[1] = values[1]; + data[2] = values[2]; + } +} + static void PollAllSensors(Uint64 timestamp, SDL_Joystick *joystick) { struct input_absinfo absinfo; @@ -1854,27 +1872,31 @@ static void PollAllSensors(Uint64 timestamp, SDL_Joystick *joystick) SDL_assert(joystick->hwdata->fd_sensor >= 0); if (joystick->hwdata->has_gyro) { - float data[3] = {0.0f, 0.0f, 0.0f}; + float values[3] = {0.0f, 0.0f, 0.0f}; for (i = 0; i < 3; i++) { if (ioctl(joystick->hwdata->fd_sensor, EVIOCGABS(ABS_RX + i), &absinfo) >= 0) { - data[i] = absinfo.value * (SDL_PI_F / 180.f) / joystick->hwdata->gyro_scale[i]; + values[i] = absinfo.value * (SDL_PI_F / 180.f) / joystick->hwdata->gyro_scale[i]; #ifdef DEBUG_INPUT_EVENTS SDL_Log("Joystick : Re-read Gyro (axis %d) val= %f", i, data[i]); #endif } } + float data[3]; + CorrectSensorData(joystick->hwdata, values, data); SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, SDL_US_TO_NS(joystick->hwdata->sensor_tick), data, 3); } if (joystick->hwdata->has_accelerometer) { - float data[3] = {0.0f, 0.0f, 0.0f}; + float values[3] = {0.0f, 0.0f, 0.0f}; for (i = 0; i < 3; i++) { if (ioctl(joystick->hwdata->fd_sensor, EVIOCGABS(ABS_X + i), &absinfo) >= 0) { - data[i] = absinfo.value * SDL_STANDARD_GRAVITY / joystick->hwdata->accelerometer_scale[i]; + values[i] = absinfo.value * SDL_STANDARD_GRAVITY / joystick->hwdata->accelerometer_scale[i]; #ifdef DEBUG_INPUT_EVENTS SDL_Log("Joystick : Re-read Accelerometer (axis %d) val= %f", i, data[i]); #endif } } + float data[3]; + CorrectSensorData(joystick->hwdata, values, data); SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, SDL_US_TO_NS(joystick->hwdata->sensor_tick), data, 3); } } @@ -2058,12 +2080,15 @@ static void HandleInputEvents(SDL_Joystick *joystick) PollAllSensors(SDL_GetTicksNS(), joystick); // try to sync up to current state now } else { Uint64 timestamp = SDL_EVDEV_GetEventTimestamp(event); + float data[3]; + CorrectSensorData(joystick->hwdata, joystick->hwdata->gyro_data, data); SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, SDL_US_TO_NS(joystick->hwdata->sensor_tick), - joystick->hwdata->gyro_data, 3); + data, 3); + CorrectSensorData(joystick->hwdata, joystick->hwdata->accel_data, data); SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, SDL_US_TO_NS(joystick->hwdata->sensor_tick), - joystick->hwdata->accel_data, 3); + data, 3); } break; default: diff --git a/thirdparty/sdl/joystick/usb_ids.h b/thirdparty/sdl/joystick/usb_ids.h index 15c1bb74542..4c85b6dad3b 100644 --- a/thirdparty/sdl/joystick/usb_ids.h +++ b/thirdparty/sdl/joystick/usb_ids.h @@ -84,6 +84,7 @@ #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED 0x0d19 +#define USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT 0x0689 #define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337 #define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019 #define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e diff --git a/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c b/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c index 377992ed9ee..5b4b6fc0bb1 100644 --- a/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c +++ b/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c @@ -42,7 +42,6 @@ // external variables referenced. extern HWND SDL_HelperWindow; - // local variables static bool coinitialized = false; static LPDIRECTINPUT8 dinput = NULL; diff --git a/thirdparty/sdl/joystick/windows/SDL_windows_gaming_input.c b/thirdparty/sdl/joystick/windows/SDL_windows_gaming_input.c index dbc5658ef54..5f9435e34a5 100644 --- a/thirdparty/sdl/joystick/windows/SDL_windows_gaming_input.c +++ b/thirdparty/sdl/joystick/windows/SDL_windows_gaming_input.c @@ -69,6 +69,7 @@ typedef PCWSTR(WINAPI *WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 *leng static struct { + bool ro_initialized; CoIncrementMTAUsage_t CoIncrementMTAUsage; RoGetActivationFactory_t RoGetActivationFactory; WindowsCreateStringReference_t WindowsCreateStringReference; @@ -585,13 +586,14 @@ static bool WGI_JoystickInit(void) { HRESULT hr; - if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_WGI, true)) { + if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_WGI, false)) { return true; } if (FAILED(WIN_RoInitialize())) { return SDL_SetError("RoInitialize() failed"); } + wgi.ro_initialized = true; #define RESOLVE(x) wgi.x = (x##_t)WIN_LoadComBaseFunction(#x); if (!wgi.x) return WIN_SetError("GetProcAddress failed for " #x); RESOLVE(CoIncrementMTAUsage); @@ -1002,7 +1004,9 @@ static void WGI_JoystickQuit(void) __x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.controller_statics); } - WIN_RoUninitialize(); + if (wgi.ro_initialized) { + WIN_RoUninitialize(); + } SDL_zero(wgi); } diff --git a/thirdparty/sdl/patches/0001-remove-unnecessary-subsystems.patch b/thirdparty/sdl/patches/0001-remove-unnecessary-subsystems.patch index e47cec9699e..f98e90b02cc 100644 --- a/thirdparty/sdl/patches/0001-remove-unnecessary-subsystems.patch +++ b/thirdparty/sdl/patches/0001-remove-unnecessary-subsystems.patch @@ -1,5 +1,5 @@ diff --git a/thirdparty/sdl/SDL.c b/thirdparty/sdl/SDL.c -index 502f6617a4..dd0b823634 100644 +index 46a74aafdb..3dad7e29ba 100644 --- a/thirdparty/sdl/SDL.c +++ b/thirdparty/sdl/SDL.c @@ -40,23 +40,14 @@ @@ -358,7 +358,7 @@ index 5746e2ef98..04e3e9d6b6 100644 SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); diff --git a/thirdparty/sdl/events/SDL_events.c b/thirdparty/sdl/events/SDL_events.c -index a151740524..24c2c4270f 100644 +index 81220a1787..7ca683e0eb 100644 --- a/thirdparty/sdl/events/SDL_events.c +++ b/thirdparty/sdl/events/SDL_events.c @@ -24,10 +24,7 @@ @@ -417,7 +417,7 @@ index a151740524..24c2c4270f 100644 #endif } -@@ -1420,9 +1406,9 @@ void SDL_PumpEventMaintenance(void) +@@ -1421,9 +1407,9 @@ void SDL_PumpEventMaintenance(void) } #endif @@ -429,7 +429,7 @@ index a151740524..24c2c4270f 100644 } // Run the system dependent event loops -@@ -1432,7 +1418,7 @@ static void SDL_PumpEventsInternal(bool push_sentinel) +@@ -1433,7 +1419,7 @@ static void SDL_PumpEventsInternal(bool push_sentinel) SDL_FreeTemporaryMemory(); // Release any keys held down from last frame @@ -438,7 +438,7 @@ index a151740524..24c2c4270f 100644 // Run any pending main thread callbacks SDL_RunMainThreadCallbacks(); -@@ -1440,12 +1426,6 @@ static void SDL_PumpEventsInternal(bool push_sentinel) +@@ -1441,12 +1427,6 @@ static void SDL_PumpEventsInternal(bool push_sentinel) #ifdef SDL_PLATFORM_ANDROID // Android event processing is independent of the video subsystem Android_PumpEvents(0); @@ -451,7 +451,7 @@ index a151740524..24c2c4270f 100644 #endif SDL_PumpEventMaintenance(); -@@ -1476,103 +1456,6 @@ bool SDL_PollEvent(SDL_Event *event) +@@ -1477,103 +1457,6 @@ bool SDL_PollEvent(SDL_Event *event) return SDL_WaitEventTimeoutNS(event, 0); } @@ -555,7 +555,7 @@ index a151740524..24c2c4270f 100644 bool SDL_WaitEvent(SDL_Event *event) { return SDL_WaitEventTimeoutNS(event, -1); -@@ -1662,24 +1545,6 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) +@@ -1665,24 +1548,6 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) Android_PumpEvents(delay); } #else @@ -580,7 +580,7 @@ index a151740524..24c2c4270f 100644 for (;;) { SDL_PumpEventsInternal(true); -@@ -1852,7 +1717,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled) +@@ -1855,7 +1720,7 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled) /* turn off drag'n'drop support if we've disabled the events. This might change some UI details at the OS level. */ if (type == SDL_EVENT_DROP_FILE || type == SDL_EVENT_DROP_TEXT) { @@ -589,7 +589,7 @@ index a151740524..24c2c4270f 100644 } } } -@@ -1944,14 +1809,14 @@ bool SDL_InitEvents(void) +@@ -1947,14 +1812,14 @@ bool SDL_InitEvents(void) return false; } @@ -629,7 +629,7 @@ index e56ac475e5..f3a0744d1c 100644 // Start and stop the event processing loop extern bool SDL_StartEventLoop(void); diff --git a/thirdparty/sdl/include/SDL3/SDL.h b/thirdparty/sdl/include/SDL3/SDL.h -index ed1b32483a..f0671c95c3 100644 +index 7ec527b6d0..c99997044b 100644 --- a/thirdparty/sdl/include/SDL3/SDL.h +++ b/thirdparty/sdl/include/SDL3/SDL.h @@ -47,7 +47,7 @@ @@ -650,7 +650,7 @@ index ed1b32483a..f0671c95c3 100644 #endif /* SDL_h_ */ diff --git a/thirdparty/sdl/joystick/SDL_joystick.c b/thirdparty/sdl/joystick/SDL_joystick.c -index 921576854e..f36ca95baa 100644 +index 5ce36de867..090dc07303 100644 --- a/thirdparty/sdl/joystick/SDL_joystick.c +++ b/thirdparty/sdl/joystick/SDL_joystick.c @@ -29,7 +29,7 @@ @@ -662,7 +662,7 @@ index 921576854e..f36ca95baa 100644 #include "../sensor/SDL_sensor_c.h" #include "hidapi/SDL_hidapijoystick_c.h" -@@ -1011,7 +1011,8 @@ static void AttemptSensorFusion(SDL_Joystick *joystick, bool invert_sensors) +@@ -1014,7 +1014,8 @@ static void AttemptSensorFusion(SDL_Joystick *joystick, bool invert_sensors) When a phone is being used as a gamepad, its orientation changes, so adjust sensor axes to match. */ @@ -672,7 +672,7 @@ index 921576854e..f36ca95baa 100644 /* When a device in landscape orientation is laid flat, the axes change orientation as follows: -X to +X becomes -X to +X -@@ -2068,11 +2069,6 @@ static bool SDL_PrivateJoystickShouldIgnoreEvent(void) +@@ -2071,11 +2072,6 @@ static bool SDL_PrivateJoystickShouldIgnoreEvent(void) if (SDL_joystick_allows_background_events) { return false; } @@ -684,20 +684,3 @@ index 921576854e..f36ca95baa 100644 return false; } -diff --git a/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c b/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c -index b00218d969..377992ed9e 100644 ---- a/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c -+++ b/thirdparty/sdl/joystick/windows/SDL_dinputjoystick.c -@@ -40,11 +40,8 @@ - #define CONVERT_MAGNITUDE(x) (((x)*10000) / 0x7FFF) - - // external variables referenced. --#ifdef SDL_VIDEO_DRIVER_WINDOWS - extern HWND SDL_HelperWindow; --#else --static const HWND SDL_HelperWindow = NULL; --#endif -+ - - // local variables - static bool coinitialized = false; diff --git a/thirdparty/sdl/patches/0002-msvc-constants-fpstrict.patch b/thirdparty/sdl/patches/0002-msvc-constants-fpstrict.patch deleted file mode 100644 index 3be681fbb11..00000000000 --- a/thirdparty/sdl/patches/0002-msvc-constants-fpstrict.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps4.c b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps4.c -index 7404bf2268..a697cdf6d9 100644 ---- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps4.c -+++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps4.c -@@ -1003,8 +1003,8 @@ static bool HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device - - static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet, int size) - { -- static const float TOUCHPAD_SCALEX = 1.0f / 1920; -- static const float TOUCHPAD_SCALEY = 1.0f / 920; // This is noted as being 944 resolution, but 920 feels better -+ static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920 -+ static const float TOUCHPAD_SCALEY = 1.08695652e-3f; // 1.0f / 920 // This is noted as being 944 resolution, but 920 feels better - Sint16 axis; - bool touchpad_down; - int touchpad_x, touchpad_y; -diff --git a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c -index abf59a87f2..a486af6b0f 100644 ---- a/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c -+++ b/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps5.c -@@ -1355,8 +1355,8 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL - - static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet, Uint64 timestamp) - { -- static const float TOUCHPAD_SCALEX = 1.0f / 1920; -- static const float TOUCHPAD_SCALEY = 1.0f / 1070; -+ static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920 -+ static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070 - bool touchpad_down; - int touchpad_x, touchpad_y; - -@@ -1406,8 +1406,8 @@ static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d - - static void HIDAPI_DriverPS5_HandleStatePacketAlt(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacketAlt_t *packet, Uint64 timestamp) - { -- static const float TOUCHPAD_SCALEX = 1.0f / 1920; -- static const float TOUCHPAD_SCALEY = 1.0f / 1070; -+ static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920 -+ static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070 - bool touchpad_down; - int touchpad_x, touchpad_y; - diff --git a/thirdparty/sdl/patches/0006-fix-cs-environ.patch b/thirdparty/sdl/patches/0006-fix-cs-environ.patch index 0e49b06a176..7ed530e58ac 100644 --- a/thirdparty/sdl/patches/0006-fix-cs-environ.patch +++ b/thirdparty/sdl/patches/0006-fix-cs-environ.patch @@ -1,8 +1,8 @@ diff --git a/thirdparty/sdl/stdlib/SDL_getenv.c b/thirdparty/sdl/stdlib/SDL_getenv.c -index b4a19224655..e23f8a0ea0d 100644 +index 54fb6a7b46..d805217b19 100644 --- a/thirdparty/sdl/stdlib/SDL_getenv.c +++ b/thirdparty/sdl/stdlib/SDL_getenv.c -@@ -50,6 +50,9 @@ extern char **environ; +@@ -55,6 +55,9 @@ extern char **environ; static char **environ; #endif @@ -12,7 +12,7 @@ index b4a19224655..e23f8a0ea0d 100644 struct SDL_Environment { -@@ -149,6 +152,9 @@ SDL_Environment *SDL_CreateEnvironment(bool populated) +@@ -154,6 +157,9 @@ SDL_Environment *SDL_CreateEnvironment(bool populated) const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name) { @@ -22,7 +22,7 @@ index b4a19224655..e23f8a0ea0d 100644 const char *result = NULL; if (!env) { -@@ -168,6 +174,7 @@ const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name) +@@ -173,6 +179,7 @@ const char *SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name) SDL_UnlockMutex(env->lock); return result; @@ -30,7 +30,7 @@ index b4a19224655..e23f8a0ea0d 100644 } typedef struct CountEnvStringsData -@@ -246,6 +253,9 @@ char **SDL_GetEnvironmentVariables(SDL_Environment *env) +@@ -251,6 +258,9 @@ char **SDL_GetEnvironmentVariables(SDL_Environment *env) bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, bool overwrite) { @@ -40,7 +40,7 @@ index b4a19224655..e23f8a0ea0d 100644 bool result = false; if (!env) { -@@ -281,10 +291,14 @@ bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const ch +@@ -286,10 +296,14 @@ bool SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const ch SDL_UnlockMutex(env->lock); return result; @@ -55,7 +55,7 @@ index b4a19224655..e23f8a0ea0d 100644 bool result = false; if (!env) { -@@ -305,6 +319,7 @@ bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name) +@@ -310,6 +324,7 @@ bool SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name) SDL_UnlockMutex(env->lock); return result; diff --git a/thirdparty/sdl/patches/0007-macos-joypad-name.patch b/thirdparty/sdl/patches/0007-macos-joypad-name.patch deleted file mode 100644 index c8ca1505f1f..00000000000 --- a/thirdparty/sdl/patches/0007-macos-joypad-name.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m b/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m -index 811a9f1ae7..2ba2cbeae6 100644 ---- a/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m -+++ b/thirdparty/sdl/joystick/apple/SDL_mfijoystick.m -@@ -300,9 +300,15 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle - * struct, and ARC doesn't work with structs. */ - device->controller = (__bridge GCController *)CFBridgingRetain(controller); - -- if (controller.vendorName) { -- name = controller.vendorName.UTF8String; -- } -+ if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { -+ if (controller.productCategory) { -+ name = controller.productCategory.UTF8String; -+ } -+ } else { -+ if (controller.vendorName) { -+ name = controller.vendorName.UTF8String; -+ } -+ } - - if (!name) { - name = "MFi Gamepad"; --- -2.51.0 diff --git a/thirdparty/sdl/stdlib/SDL_getenv.c b/thirdparty/sdl/stdlib/SDL_getenv.c index e23f8a0ea0d..d805217b197 100644 --- a/thirdparty/sdl/stdlib/SDL_getenv.c +++ b/thirdparty/sdl/stdlib/SDL_getenv.c @@ -41,7 +41,12 @@ #define environ (*_NSGetEnviron()) #elif defined(SDL_PLATFORM_FREEBSD) #include -#define environ ((char **)dlsym(RTLD_DEFAULT, "environ")) +static char **get_environ_rtld(void) +{ + char ***environ_rtld = (char ***)dlsym(RTLD_DEFAULT, "environ"); + return environ_rtld ? *environ_rtld : NULL; +} +#define environ (get_environ_rtld()) #else extern char **environ; #endif diff --git a/thirdparty/sdl/stdlib/SDL_malloc.c b/thirdparty/sdl/stdlib/SDL_malloc.c index 00118b8ae61..0ccdf39a91c 100644 --- a/thirdparty/sdl/stdlib/SDL_malloc.c +++ b/thirdparty/sdl/stdlib/SDL_malloc.c @@ -1478,6 +1478,13 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int); #endif /* NO_MALLOC_STATS */ #ifndef LACKS_ERRNO_H #include /* for MALLOC_FAILURE_ACTION */ +#else /* LACKS_ERRNO_H */ +#ifndef EINVAL +#define EINVAL 22 +#endif +#ifndef ENOMEM +#define ENOMEM 12 +#endif #endif /* LACKS_ERRNO_H */ #ifdef DEBUG #if ABORT_ON_ASSERT_FAILURE diff --git a/thirdparty/sdl/stdlib/SDL_mslibc.c b/thirdparty/sdl/stdlib/SDL_mslibc.c index 6698403fe89..1dfc76166b3 100644 --- a/thirdparty/sdl/stdlib/SDL_mslibc.c +++ b/thirdparty/sdl/stdlib/SDL_mslibc.c @@ -95,6 +95,39 @@ void _ftol2() _ftol(); } +void __declspec(naked) _ftoul2_legacy() +{ + static const Uint64 LLONG_MAX_PLUS_ONE = 0x43e0000000000000ULL; + /* *INDENT-OFF* */ + __asm { + fld qword ptr [LLONG_MAX_PLUS_ONE] + fcom + fnstsw ax + test ah, 41h + jnp greater_than_int64 + + fstp st(0) + jmp _ftol + +greater_than_int64: + fsub st(1), st(0) + fcomp + fnstsw ax + test ah, 41h + jnz greater_than_uint64 + + call _ftol + add edx, 80000000h + ret + +greater_than_uint64: + xor eax, eax + mov edx, 80000000h + ret + } + /* *INDENT-ON* */ +} + // 64-bit math operators for 32-bit systems void __declspec(naked) _allmul() { diff --git a/thirdparty/sdl/thread/SDL_thread.c b/thirdparty/sdl/thread/SDL_thread.c index 99cb9dd7f15..f31e670b9d4 100644 --- a/thirdparty/sdl/thread/SDL_thread.c +++ b/thirdparty/sdl/thread/SDL_thread.c @@ -80,6 +80,15 @@ bool SDL_SetTLS(SDL_TLSID *id, const void *value, SDL_TLSDestructorCallback dest * will have the same storage index for this id. */ storage_index = SDL_GetAtomicInt(id) - 1; + } else { + // Make sure we don't allocate an ID clobbering this one + int tls_id = SDL_GetAtomicInt(&SDL_tls_id); + while (storage_index >= tls_id) { + if (SDL_CompareAndSwapAtomicInt(&SDL_tls_id, tls_id, storage_index + 1)) { + break; + } + tls_id = SDL_GetAtomicInt(&SDL_tls_id); + } } // Get the storage for the current thread @@ -333,7 +342,7 @@ void SDL_RunThread(SDL_Thread *thread) // Mark us as ready to be joined (or detached) if (!SDL_CompareAndSwapAtomicInt(&thread->state, SDL_THREAD_ALIVE, SDL_THREAD_COMPLETE)) { // Clean up if something already detached us. - if (SDL_GetThreadState(thread) == SDL_THREAD_DETACHED) { + if (SDL_GetAtomicInt(&thread->state) == SDL_THREAD_DETACHED) { SDL_free(thread->name); // Can't free later, we've already cleaned up TLS SDL_free(thread); } @@ -487,11 +496,10 @@ void SDL_DetachThread(SDL_Thread *thread) return; } - // The thread may vanish at any time, it's no longer valid - SDL_SetObjectValid(thread, SDL_OBJECT_TYPE_THREAD, false); - // Grab dibs if the state is alive+joinable. if (SDL_CompareAndSwapAtomicInt(&thread->state, SDL_THREAD_ALIVE, SDL_THREAD_DETACHED)) { + // The thread may vanish at any time, it's no longer valid + SDL_SetObjectValid(thread, SDL_OBJECT_TYPE_THREAD, false); SDL_SYS_DetachThread(thread); } else { // all other states are pretty final, see where we landed. diff --git a/thirdparty/sdl/update-sdl.sh b/thirdparty/sdl/update-sdl.sh index c9be179969f..6c68a415987 100755 --- a/thirdparty/sdl/update-sdl.sh +++ b/thirdparty/sdl/update-sdl.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=3.2.16 +VERSION=3.2.28 target=$(dirname "$(realpath $0)") pushd $target