From 1e3eb08c69ec70b2e7efb68c8d79e201f284089e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 11 Jan 2020 16:56:16 +1100 Subject: [PATCH] Added dinput-DIPROP_BUFFERSIZE patchset --- ...efault-DIPROP_BUFFERSIZE-buffer-size.patch | 187 ++++++++++++++++++ patches/dinput-DIPROP_BUFFERSIZE/definition | 1 + ...connecting-to-disconnected-joysticks.patch | 24 +-- patches/dinput-reconnect-joystick/definition | 2 +- patches/patchinstall.sh | 32 ++- ...ort-for-dinput-devices-that-use-raw-.patch | 10 +- 6 files changed, 237 insertions(+), 19 deletions(-) create mode 100644 patches/dinput-DIPROP_BUFFERSIZE/0001-dinput-Support-default-DIPROP_BUFFERSIZE-buffer-size.patch create mode 100644 patches/dinput-DIPROP_BUFFERSIZE/definition diff --git a/patches/dinput-DIPROP_BUFFERSIZE/0001-dinput-Support-default-DIPROP_BUFFERSIZE-buffer-size.patch b/patches/dinput-DIPROP_BUFFERSIZE/0001-dinput-Support-default-DIPROP_BUFFERSIZE-buffer-size.patch new file mode 100644 index 00000000..4cd308e9 --- /dev/null +++ b/patches/dinput-DIPROP_BUFFERSIZE/0001-dinput-Support-default-DIPROP_BUFFERSIZE-buffer-size.patch @@ -0,0 +1,187 @@ +From 095e3e2646bc5ba024c166a2ac6829a894c0d1f7 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Fri, 10 Jan 2020 09:28:50 +1100 +Subject: [PATCH] dinput: Support default DIPROP_BUFFERSIZE buffer size + +When a program calls SetProperty with DIPROP_BUFFERSIZE, dinput records +this value for GetProperty but only uses it when the device can support +that number of buffers otherwise a max value. + +In the case of game "Far Cry 5", it passes through (DWORD)-1 which +cause HeapAlloc to fail ((DWORD)-1 * sizeof(DIDEVICEOBJECTDATA)). + +Since there is no real way of working out the max value, I've capped it at 100 as +the default value is 20. + +MSDN reference. +https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee417908(v=vs.85) + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45732 + +Signed-off-by: Alistair Leslie-Hughes +--- + dlls/dinput/device.c | 14 ++++++++++---- + dlls/dinput/device_private.h | 3 ++- + dlls/dinput/joystick_linux.c | 4 ++++ + dlls/dinput/joystick_linuxinput.c | 4 ++++ + dlls/dinput/joystick_osx.c | 4 ++++ + dlls/dinput/keyboard.c | 3 +++ + dlls/dinput/mouse.c | 3 +++ + dlls/dinput/tests/device.c | 14 ++++++++++++++ + 8 files changed, 44 insertions(+), 5 deletions(-) + +diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c +index 28329d03b5..1604075f84 100644 +--- a/dlls/dinput/device.c ++++ b/dlls/dinput/device.c +@@ -1307,7 +1307,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, + + if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; + +- pd->dwData = This->queue_len; ++ pd->dwData = This->buffersize; + TRACE("buffersize = %d\n", pd->dwData); + break; + } +@@ -1396,12 +1396,18 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( + TRACE("buffersize = %d\n", pd->dwData); + + EnterCriticalSection(&This->crit); ++ ++ This->buffersize = pd->dwData; ++ ++ This->queue_len = This->buffersize > 100 ? 100 : This->buffersize; ++ if (This->buffersize > 100) ++ WARN("Trying to set large buffer size %d\n", pd->dwData); ++ + HeapFree(GetProcessHeap(), 0, This->data_queue); + +- This->data_queue = !pd->dwData ? NULL : HeapAlloc(GetProcessHeap(), 0, +- pd->dwData * sizeof(DIDEVICEOBJECTDATA)); ++ This->data_queue = !This->queue_len ? NULL : HeapAlloc(GetProcessHeap(), 0, ++ This->queue_len * sizeof(DIDEVICEOBJECTDATA)); + This->queue_head = This->queue_tail = This->overflow = 0; +- This->queue_len = pd->dwData; + + LeaveCriticalSection(&This->crit); + break; +diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h +index 27e9c26286..23d9e2eebc 100644 +--- a/dlls/dinput/device_private.h ++++ b/dlls/dinput/device_private.h +@@ -71,10 +71,11 @@ struct IDirectInputDeviceImpl + DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */ + + LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */ +- int queue_len; /* size of the queue - set in 'SetProperty' */ ++ int queue_len; /* valid size of the queue */ + int queue_head; /* position to write new event into queue */ + int queue_tail; /* next event to read from queue */ + BOOL overflow; /* return DI_BUFFEROVERFLOW in 'GetDeviceData' */ ++ DWORD buffersize; /* size of the queue - set in 'SetProperty' */ + + DataFormat data_format; /* user data format and wine to user format converter */ + +diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c +index afdf659b4a..1e7bf72936 100644 +--- a/dlls/dinput/joystick_linux.c ++++ b/dlls/dinput/joystick_linux.c +@@ -501,6 +501,10 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput, + newDevice->generic.base.ref = 1; + newDevice->generic.base.dinput = dinput; + newDevice->generic.base.guid = *rguid; ++ newDevice->generic.base.buffersize = 20; ++ newDevice->generic.base.queue_len = 20; ++ newDevice->generic.base.data_queue = HeapAlloc(GetProcessHeap(), 0, ++ newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA)); + InitializeCriticalSection(&newDevice->generic.base.crit); + newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit"); + +diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c +index b5418d805c..98283a1eed 100644 +--- a/dlls/dinput/joystick_linuxinput.c ++++ b/dlls/dinput/joystick_linuxinput.c +@@ -471,6 +471,10 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig + newDevice->generic.base.ref = 1; + newDevice->generic.base.guid = *rguid; + newDevice->generic.base.dinput = dinput; ++ newDevice->generic.base.buffersize = 20; ++ newDevice->generic.base.queue_len = 20; ++ newDevice->generic.base.data_queue = HeapAlloc(GetProcessHeap(), 0, ++ newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA)); + newDevice->generic.joy_polldev = joy_polldev; + newDevice->joyfd = -1; + newDevice->joydev = &joydevs[index]; +diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c +index 990f5d1f07..c48cad1f5a 100644 +--- a/dlls/dinput/joystick_osx.c ++++ b/dlls/dinput/joystick_osx.c +@@ -1168,6 +1168,10 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput, + newDevice->generic.base.ref = 1; + newDevice->generic.base.dinput = dinput; + newDevice->generic.base.guid = *rguid; ++ newDevice->generic.base.buffersize = 20; ++ newDevice->generic.base.queue_len = 20; ++ newDevice->generic.base.data_queue = HeapAlloc(GetProcessHeap(), 0, ++ newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA)); + InitializeCriticalSection(&newDevice->generic.base.crit); + newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit"); + +diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c +index 47f28cac52..15a6be4dee 100644 +--- a/dlls/dinput/keyboard.c ++++ b/dlls/dinput/keyboard.c +@@ -268,6 +268,9 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) + InitializeCriticalSection(&newDevice->base.crit); + newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit"); + newDevice->subtype = get_keyboard_subtype(); ++ newDevice->base.buffersize = 20; ++ newDevice->base.queue_len = 20; ++ newDevice->base.data_queue = HeapAlloc(GetProcessHeap(), 0, newDevice->base.queue_len * sizeof(DIDEVICEOBJECTDATA)); + + /* Create copy of default data format */ + if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIKeyboard.dwSize))) goto failed; +diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c +index 08ace2f4e9..59c8c9dad8 100644 +--- a/dlls/dinput/mouse.c ++++ b/dlls/dinput/mouse.c +@@ -214,6 +214,9 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) + newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit"); + newDevice->base.dinput = dinput; + newDevice->base.event_proc = dinput_mouse_hook; ++ newDevice->base.buffersize = 20; ++ newDevice->base.queue_len = 20; ++ newDevice->base.data_queue = HeapAlloc(GetProcessHeap(), 0, newDevice->base.queue_len * sizeof(DIDEVICEOBJECTDATA)); + + get_app_key(&hkey, &appkey); + if (!get_config_key(hkey, appkey, "MouseWarpOverride", buffer, sizeof(buffer))) +diff --git a/dlls/dinput/tests/device.c b/dlls/dinput/tests/device.c +index a2a5a65686..4dd16c70d2 100644 +--- a/dlls/dinput/tests/device.c ++++ b/dlls/dinput/tests/device.c +@@ -106,8 +106,22 @@ static void test_object_info(IDirectInputDeviceA *device, HWND hwnd) + dp.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dp.diph.dwHow = DIPH_DEVICE; + dp.diph.dwObj = 0; ++ dp.dwData = -1; ++ ++ hr = IDirectInputDevice_GetProperty(device, DIPROP_BUFFERSIZE, &dp.diph); ++ ok(hr == DI_OK, "Failed: %08x\n", hr); ++ ok(dp.dwData == 20, "got %d\n", dp.dwData); ++ ++ dp.dwData = -1; ++ hr = IDirectInputDevice_SetProperty(device, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&dp.diph); ++ ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr); ++ + dp.dwData = 0; ++ hr = IDirectInputDevice_GetProperty(device, DIPROP_BUFFERSIZE, &dp.diph); ++ ok(hr == DI_OK, "Failed: %08x\n", hr); ++ ok(dp.dwData == -1, "got %d\n", dp.dwData); + ++ dp.dwData = 0; + hr = IDirectInputDevice_SetProperty(device, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&dp.diph); + ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr); + cnt = 5; +-- +2.17.1 + diff --git a/patches/dinput-DIPROP_BUFFERSIZE/definition b/patches/dinput-DIPROP_BUFFERSIZE/definition new file mode 100644 index 00000000..5a425db7 --- /dev/null +++ b/patches/dinput-DIPROP_BUFFERSIZE/definition @@ -0,0 +1 @@ +Fixes: [45732] Far Cry 5 Cannot Steer Land Vehicles diff --git a/patches/dinput-reconnect-joystick/0001-dinput-Allow-reconnecting-to-disconnected-joysticks.patch b/patches/dinput-reconnect-joystick/0001-dinput-Allow-reconnecting-to-disconnected-joysticks.patch index db5c7aed..4d17f168 100644 --- a/patches/dinput-reconnect-joystick/0001-dinput-Allow-reconnecting-to-disconnected-joysticks.patch +++ b/patches/dinput-reconnect-joystick/0001-dinput-Allow-reconnecting-to-disconnected-joysticks.patch @@ -1,18 +1,18 @@ -From 47a1e3618a1629a6f7cca1b84f761eaab3627f75 Mon Sep 17 00:00:00 2001 +From dd42a25720d9d711137e84a449319fc197b2639f Mon Sep 17 00:00:00 2001 From: Andrew Church Date: Mon, 25 Feb 2019 11:23:12 +1100 Subject: [PATCH] dinput: Allow reconnecting to disconnected joysticks Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=34297 --- - dlls/dinput/joystick_linuxinput.c | 148 +++++++++++++++++++++++++++++--------- + dlls/dinput/joystick_linuxinput.c | 148 +++++++++++++++++++++++------- 1 file changed, 113 insertions(+), 35 deletions(-) diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c -index ace4641..233dd25 100644 +index 98283a1eedd..439e7d84bd4 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c -@@ -83,6 +83,13 @@ struct wine_input_absinfo { +@@ -84,6 +84,13 @@ struct wine_input_absinfo { LONG flat; }; @@ -26,7 +26,7 @@ index ace4641..233dd25 100644 /* implemented in effect_linuxinput.c */ HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff); HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info); -@@ -122,6 +129,7 @@ struct JoystickImpl +@@ -123,6 +130,7 @@ struct JoystickImpl /* joystick private */ int joyfd; @@ -34,15 +34,15 @@ index ace4641..233dd25 100644 int dev_axes_to_di[ABS_MAX]; POINTL povs[4]; -@@ -466,6 +474,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig - newDevice->generic.base.dinput = dinput; +@@ -477,6 +485,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig + newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA)); newDevice->generic.joy_polldev = joy_polldev; newDevice->joyfd = -1; + newDevice->joyfd_state = WINE_FD_STATE_CLOSED; newDevice->joydev = &joydevs[index]; newDevice->generic.name = newDevice->joydev->name; list_init(&newDevice->ff_effects); -@@ -669,38 +678,15 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF +@@ -684,38 +693,15 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF return DIERR_DEVICENOTREG; } @@ -85,7 +85,7 @@ index ace4641..233dd25 100644 } else { -@@ -715,18 +701,53 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) +@@ -730,18 +716,53 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) event.type = EV_FF; event.code = FF_GAIN; event.value = This->ff_gain; @@ -141,7 +141,7 @@ index ace4641..233dd25 100644 return DI_OK; } -@@ -764,6 +785,7 @@ static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) +@@ -779,6 +800,7 @@ static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) close(This->joyfd); This->joyfd = -1; @@ -149,7 +149,7 @@ index ace4641..233dd25 100644 } return res; } -@@ -808,23 +830,79 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface) +@@ -823,23 +845,79 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface) struct input_event ie; JoystickImpl *This = impl_from_IDirectInputDevice8A(iface); @@ -236,5 +236,5 @@ index ace4641..233dd25 100644 TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value); switch (ie.type) { -- -1.9.1 +2.24.1 diff --git a/patches/dinput-reconnect-joystick/definition b/patches/dinput-reconnect-joystick/definition index 4aa535ba..7ce6f609 100644 --- a/patches/dinput-reconnect-joystick/definition +++ b/patches/dinput-reconnect-joystick/definition @@ -1,2 +1,2 @@ Fixes: [34297] dinput: Allow reconnecting to disconnected joysticks - +Depends: dinput-DIPROP_BUFFERSIZE diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 647070ef..f8d4dae0 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -52,7 +52,7 @@ usage() # Get the upstream commit sha upstream_commit() { - echo "4f0212c4fd35ac4b03a082cab27e629130ac1b13" + echo "c84fa0a2661f2235fac6f3427201fbb3fd8c8028" } # Show version information @@ -128,6 +128,7 @@ patch_enable_all () enable_ddraw_Texture_Wrong_Caps="$1" enable_ddraw_Write_Vtable="$1" enable_ddraw_version_check="$1" + enable_dinput_DIPROP_BUFFERSIZE="$1" enable_dinput_SetActionMap_genre="$1" enable_dinput_axis_recalc="$1" enable_dinput_joy_mappings="$1" @@ -518,6 +519,9 @@ patch_enable () ddraw-version-check) enable_ddraw_version_check="$2" ;; + dinput-DIPROP_BUFFERSIZE) + enable_dinput_DIPROP_BUFFERSIZE="$2" + ;; dinput-SetActionMap-genre) enable_dinput_SetActionMap_genre="$2" ;; @@ -2049,6 +2053,13 @@ if test "$enable_dsound_EAX" -eq 1; then enable_dsound_Fast_Mixer=1 fi +if test "$enable_dinput_reconnect_joystick" -eq 1; then + if test "$enable_dinput_DIPROP_BUFFERSIZE" -gt 1; then + abort "Patchset dinput-DIPROP_BUFFERSIZE disabled, but dinput-reconnect-joystick depends on that." + fi + enable_dinput_DIPROP_BUFFERSIZE=1 +fi + if test "$enable_dinput_SetActionMap_genre" -eq 1; then if test "$enable_dinput_joy_mappings" -gt 1; then abort "Patchset dinput-joy-mappings disabled, but dinput-SetActionMap-genre depends on that." @@ -3089,6 +3100,22 @@ if test "$enable_ddraw_version_check" -eq 1; then ) >> "$patchlist" fi +# Patchset dinput-DIPROP_BUFFERSIZE +# | +# | This patchset fixes the following Wine bugs: +# | * [#45732] Far Cry 5 Cannot Steer Land Vehicles +# | +# | Modified files: +# | * dlls/dinput/device.c, dlls/dinput/device_private.h, dlls/dinput/joystick_linux.c, dlls/dinput/joystick_linuxinput.c, +# | dlls/dinput/joystick_osx.c, dlls/dinput/keyboard.c, dlls/dinput/mouse.c, dlls/dinput/tests/device.c +# | +if test "$enable_dinput_DIPROP_BUFFERSIZE" -eq 1; then + patch_apply dinput-DIPROP_BUFFERSIZE/0001-dinput-Support-default-DIPROP_BUFFERSIZE-buffer-size.patch + ( + printf '%s\n' '+ { "Alistair Leslie-Hughes", "dinput: Support default DIPROP_BUFFERSIZE buffer size.", 1 },'; + ) >> "$patchlist" +fi + # Patchset dinput-joy-mappings # | # | This patchset fixes the following Wine bugs: @@ -3148,6 +3175,9 @@ fi # Patchset dinput-reconnect-joystick # | +# | This patchset has the following (direct or indirect) dependencies: +# | * dinput-DIPROP_BUFFERSIZE +# | # | This patchset fixes the following Wine bugs: # | * [#34297] dinput: Allow reconnecting to disconnected joysticks # | diff --git a/patches/user32-rawinput-mouse/0011-dinput8-Add-support-for-dinput-devices-that-use-raw-.patch b/patches/user32-rawinput-mouse/0011-dinput8-Add-support-for-dinput-devices-that-use-raw-.patch index 30409d35..55628fa7 100644 --- a/patches/user32-rawinput-mouse/0011-dinput8-Add-support-for-dinput-devices-that-use-raw-.patch +++ b/patches/user32-rawinput-mouse/0011-dinput8-Add-support-for-dinput-devices-that-use-raw-.patch @@ -1,8 +1,8 @@ -From 7f814cd77f1766b98318bbc8ea5fff241c20ec4b Mon Sep 17 00:00:00 2001 +From 8217791e4b68de86e713dee0ecdd3c5ccd029017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Mon, 26 Aug 2019 16:06:59 +0200 -Subject: [PATCH 11/12] dinput8: Add support for dinput devices that use raw - input interface. +Subject: [PATCH] dinput8: Add support for dinput devices that use raw input + interface. This adds a global message window that will receive WM_INPUT messages, dispatched to every raw input device event_proc. @@ -16,7 +16,7 @@ outside of dinput, as exposed by the unit tests. 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h -index 114e3971ed8..9116aaeab66 100644 +index 423e8f77792..b0fb181fc6d 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -70,6 +70,9 @@ struct IDirectInputDeviceImpl @@ -27,7 +27,7 @@ index 114e3971ed8..9116aaeab66 100644 + RAWINPUTDEVICE raw_device; /* raw device to (un)register */ + LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */ - int queue_len; /* size of the queue - set in 'SetProperty' */ + int queue_len; /* valid size of the queue */ int queue_head; /* position to write new event into queue */ diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 4d2d4afe106..9e3b9f48250 100644