diff --git a/scripts/deps/build-dependencies-windows-arm64.bat b/scripts/deps/build-dependencies-windows-arm64.bat index b3ef69047..7bd54942b 100644 --- a/scripts/deps/build-dependencies-windows-arm64.bat +++ b/scripts/deps/build-dependencies-windows-arm64.bat @@ -190,6 +190,7 @@ echo Building SDL... rmdir /S /Q "SDL3-%SDL3%" %SEVENZIP% x "SDL3-%SDL3%.zip" || goto error cd "SDL3-%SDL3%" || goto error +%PATCH% -p1 < "%SCRIPTDIR%\sdl3-ezfrd64-dll.patch" || goto error cmake -B build %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -G Ninja || goto error cmake --build build --parallel || goto error ninja -C build install || goto error diff --git a/scripts/deps/build-dependencies-windows-x64.bat b/scripts/deps/build-dependencies-windows-x64.bat index 716241dd2..c943925d2 100644 --- a/scripts/deps/build-dependencies-windows-x64.bat +++ b/scripts/deps/build-dependencies-windows-x64.bat @@ -187,6 +187,7 @@ echo Building SDL... rmdir /S /Q "SDL3-%SDL3%" %SEVENZIP% x "SDL3-%SDL3%.zip" || goto error cd "SDL3-%SDL3%" || goto error +%PATCH% -p1 < "%SCRIPTDIR%\sdl3-ezfrd64-dll.patch" || goto error cmake -B build -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -G Ninja || goto error cmake --build build --parallel || goto error ninja -C build install || goto error diff --git a/scripts/deps/sdl3-ezfrd64-dll.patch b/scripts/deps/sdl3-ezfrd64-dll.patch new file mode 100644 index 000000000..f01560aca --- /dev/null +++ b/scripts/deps/sdl3-ezfrd64-dll.patch @@ -0,0 +1,73 @@ +From f369e804e27731e128caf3b370e0569e0695c57e Mon Sep 17 00:00:00 2001 +From: Sam Lantinga +Date: Wed, 7 Jan 2026 17:11:57 -0800 +Subject: [PATCH] Fixed crash when the broken EZFRD64.DLL is present + +Fixes https://github.com/ppy/osu/issues/13634 +--- + src/joystick/windows/SDL_dinputjoystick.c | 38 +++++++++++++++++++---- + 1 file changed, 32 insertions(+), 6 deletions(-) + +diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c +index d265d9fcd5fa4..62ffbb46ec9fa 100644 +--- a/src/joystick/windows/SDL_dinputjoystick.c ++++ b/src/joystick/windows/SDL_dinputjoystick.c +@@ -45,6 +45,7 @@ extern HWND SDL_HelperWindow; + // local variables + static bool coinitialized = false; + static LPDIRECTINPUT8 dinput = NULL; ++static bool has_broken_EZFRD64DLL = false; + + // Taken from Wine - Thanks! + static DIOBJECTDATAFORMAT dfDIJoystick2[] = { +@@ -437,6 +438,29 @@ bool SDL_DINPUT_JoystickInit(void) + dinput = NULL; + return SetDIerror("IDirectInput::Initialize", result); + } ++ ++#ifdef _WIN64 ++ if (SDL_GetHintBoolean("SDL_JOYSTICK_CHECK_EZFRD64", true)) { ++ // The 64-bit version of EZFRD64.DLL crashes after being loaded, ++ // which happens implicitly when querying the device capabilities, ++ // so make sure we don't do that if there's a possibility of crashing ++ static const char *directories[] = { ++ "C:/Windows/USB_Vibration", ++ "C:/Windows/USB Vibration" ++ }; ++ for (int i = 0; i < SDL_arraysize(directories) && !has_broken_EZFRD64DLL; ++i) { ++ int count = 0; ++ char **files = SDL_GlobDirectory(directories[i], "*/EZFRD64.DLL", SDL_GLOB_CASEINSENSITIVE, &count); ++ if (count > 0) { ++ has_broken_EZFRD64DLL = true; ++ } ++ SDL_free(files); ++ } ++ if (has_broken_EZFRD64DLL) { ++ SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Broken EZFRD64.DLL detected, disabling DirectInput force feedback"); ++ } ++ } ++#endif + return true; + } + +@@ -778,12 +802,14 @@ bool SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joysti + return SetDIerror("IDirectInputDevice8::SetDataFormat", result); + } + +- // Get device capabilities +- result = +- IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice, +- &joystick->hwdata->Capabilities); +- if (FAILED(result)) { +- return SetDIerror("IDirectInputDevice8::GetCapabilities", result); ++ if (!has_broken_EZFRD64DLL) { ++ // Get device capabilities to see if we are force feedback capable ++ result = ++ IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice, ++ &joystick->hwdata->Capabilities); ++ if (FAILED(result)) { ++ return SetDIerror("IDirectInputDevice8::GetCapabilities", result); ++ } + } + + // Force capable?