diff --git a/patches/dinput-axis-recalc/0001-dinput-Recalculated-Axis-after-deadzone-change.patch b/patches/dinput-axis-recalc/0001-dinput-Recalculated-Axis-after-deadzone-change.patch new file mode 100644 index 00000000..6f012f30 --- /dev/null +++ b/patches/dinput-axis-recalc/0001-dinput-Recalculated-Axis-after-deadzone-change.patch @@ -0,0 +1,214 @@ +From b5311918d5fbdc15b3321fed444daa0d0c8507de Mon Sep 17 00:00:00 2001 +From: Bruno Jesus +Date: Thu, 28 Feb 2019 15:56:18 +1100 +Subject: [PATCH] dinput: Recalculated Axis after deadzone change. + +Wine-bugs: https://bugs.winehq.org/show_bug.cgi?id=41317 +--- + dlls/dinput/joystick.c | 149 ++++++++++++++++++++++++++----------------------- + 1 file changed, 80 insertions(+), 69 deletions(-) + +diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c +index 0ec1ceb..fd3d44d 100644 +--- a/dlls/dinput/joystick.c ++++ b/dlls/dinput/joystick.c +@@ -271,6 +271,76 @@ BOOL device_disabled_registry(const char* name) + return do_disable; + } + ++static void remap_init(JoystickGenericImpl *This, int obj, ObjProps *remap_props) ++{ ++ /* Configure as if nothing changed so the helper functions can only change ++ * what they need, thus reducing code duplication. */ ++ remap_props->lDevMin = remap_props->lMin = This->props[obj].lMin; ++ remap_props->lDevMax = remap_props->lMax = This->props[obj].lMax; ++ ++ remap_props->lDeadZone = This->props[obj].lDeadZone; ++ remap_props->lSaturation = This->props[obj].lSaturation; ++} ++ ++static void remap_apply(JoystickGenericImpl *This, int obj, ObjProps *remap_props) ++{ ++ /* Many games poll the joystick immediately after setting the range ++ * for calibration purposes, so the old values need to be remapped ++ * to the new range before it does so */ ++ switch (This->base.data_format.wine_df->rgodf[obj].dwOfs){ ++ case DIJOFS_X : This->js.lX = joystick_map_axis(remap_props, This->js.lX); break; ++ case DIJOFS_Y : This->js.lY = joystick_map_axis(remap_props, This->js.lY); break; ++ case DIJOFS_Z : This->js.lZ = joystick_map_axis(remap_props, This->js.lZ); break; ++ case DIJOFS_RX : This->js.lRx = joystick_map_axis(remap_props, This->js.lRx); break; ++ case DIJOFS_RY : This->js.lRy = joystick_map_axis(remap_props, This->js.lRy); break; ++ case DIJOFS_RZ : This->js.lRz = joystick_map_axis(remap_props, This->js.lRz); break; ++ case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(remap_props, This->js.rglSlider[0]); break; ++ case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(remap_props, This->js.rglSlider[1]); break; ++ default: break; ++ } ++} ++ ++static void remap_range(JoystickGenericImpl *This, int obj, LPCDIPROPRANGE pr) ++{ ++ ObjProps remap_props; ++ remap_init(This, obj, &remap_props); ++ ++ remap_props.lMin = pr->lMin; ++ remap_props.lMax = pr->lMax; ++ ++ remap_apply(This, obj, &remap_props); ++ ++ /* Store new values */ ++ This->props[obj].lMin = pr->lMin; ++ This->props[obj].lMax = pr->lMax; ++} ++ ++static void remap_deadzone(JoystickGenericImpl *This, int obj, LPCDIPROPDWORD pd) ++{ ++ ObjProps remap_props; ++ remap_init(This, obj, &remap_props); ++ ++ remap_props.lDeadZone = pd->dwData; ++ ++ remap_apply(This, obj, &remap_props); ++ ++ /* Store new value */ ++ This->props[obj].lDeadZone = pd->dwData; ++} ++ ++static void remap_saturation(JoystickGenericImpl *This, int obj, LPCDIPROPDWORD pd) ++{ ++ ObjProps remap_props; ++ remap_init(This, obj, &remap_props); ++ ++ remap_props.lSaturation = pd->dwData; ++ ++ remap_apply(This, obj, &remap_props); ++ ++ /* Store new value */ ++ This->props[obj].lSaturation = pd->dwData; ++} ++ + /****************************************************************************** + * SetProperty : change input device properties + */ +@@ -278,7 +348,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF + { + JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); + DWORD i; +- ObjProps remap_props; + + TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph); + +@@ -295,69 +364,15 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF + case (DWORD_PTR)DIPROP_RANGE: { + LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph; + if (ph->dwHow == DIPH_DEVICE) { +- +- /* Many games poll the joystick immediately after setting the range +- * for calibration purposes, so the old values need to be remapped +- * to the new range before it does so */ +- + TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax); +- for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) { +- +- remap_props.lDevMin = This->props[i].lMin; +- remap_props.lDevMax = This->props[i].lMax; +- +- remap_props.lDeadZone = This->props[i].lDeadZone; +- remap_props.lSaturation = This->props[i].lSaturation; +- +- remap_props.lMin = pr->lMin; +- remap_props.lMax = pr->lMax; +- +- switch (This->base.data_format.wine_df->rgodf[i].dwOfs) { +- case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; +- case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; +- case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; +- case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break; +- case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break; +- case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break; +- case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break; +- case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break; +- default: break; +- } +- +- This->props[i].lMin = pr->lMin; +- This->props[i].lMax = pr->lMax; +- } ++ for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) ++ remap_range(This, i, pr); + } else { + int obj = find_property(&This->base.data_format, ph); + + TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj); +- if (obj >= 0) { +- +- remap_props.lDevMin = This->props[obj].lMin; +- remap_props.lDevMax = This->props[obj].lMax; +- +- remap_props.lDeadZone = This->props[obj].lDeadZone; +- remap_props.lSaturation = This->props[obj].lSaturation; +- +- remap_props.lMin = pr->lMin; +- remap_props.lMax = pr->lMax; +- +- switch (This->base.data_format.wine_df->rgodf[obj].dwOfs) { +- case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; +- case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; +- case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; +- case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break; +- case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break; +- case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break; +- case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break; +- case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break; +- default: break; +- } +- +- This->props[obj].lMin = pr->lMin; +- This->props[obj].lMax = pr->lMax; +- return DI_OK; +- } ++ if (obj >= 0) ++ remap_range(This, obj, pr); + } + break; + } +@@ -366,15 +381,13 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF + if (ph->dwHow == DIPH_DEVICE) { + TRACE("deadzone(%d) all\n", pd->dwData); + for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) +- This->props[i].lDeadZone = pd->dwData; ++ remap_deadzone(This, i, pd); + } else { + int obj = find_property(&This->base.data_format, ph); + + TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj); +- if (obj >= 0) { +- This->props[obj].lDeadZone = pd->dwData; +- return DI_OK; +- } ++ if (obj >= 0) ++ remap_deadzone(This, obj, pd); + } + break; + } +@@ -383,15 +396,13 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF + if (ph->dwHow == DIPH_DEVICE) { + TRACE("saturation(%d) all\n", pd->dwData); + for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) +- This->props[i].lSaturation = pd->dwData; ++ remap_saturation(This, i, pd); + } else { + int obj = find_property(&This->base.data_format, ph); + + TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); +- if (obj >= 0) { +- This->props[obj].lSaturation = pd->dwData; +- return DI_OK; +- } ++ if (obj >= 0) ++ remap_saturation(This, obj, pd); + } + break; + } +-- +1.9.1 + diff --git a/patches/dinput-axis-recalc/definition b/patches/dinput-axis-recalc/definition new file mode 100644 index 00000000..fd0f2a28 --- /dev/null +++ b/patches/dinput-axis-recalc/definition @@ -0,0 +1 @@ +Fixes: [41317] dinput: Recalculated Axis after deadzone change. diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index e150a6b9..2ff167c9 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -133,6 +133,7 @@ patch_enable_all () enable_ddraw_version_check="$1" enable_dinput_Deadlock="$1" enable_dinput_Initialize="$1" + enable_dinput_axis_recalc="$1" enable_dinput_reconnect_joystick="$1" enable_dinput_remap_joystick="$1" enable_dsound_EAX="$1" @@ -549,6 +550,9 @@ patch_enable () dinput-Initialize) enable_dinput_Initialize="$2" ;; + dinput-axis-recalc) + enable_dinput_axis_recalc="$2" + ;; dinput-reconnect-joystick) enable_dinput_reconnect_joystick="$2" ;; @@ -3239,6 +3243,21 @@ if test "$enable_dinput_Initialize" -eq 1; then ) >> "$patchlist" fi +# Patchset dinput-axis-recalc +# | +# | This patchset fixes the following Wine bugs: +# | * [#41317] dinput: Recalculated Axis after deadzone change. +# | +# | Modified files: +# | * dlls/dinput/joystick.c +# | +if test "$enable_dinput_axis_recalc" -eq 1; then + patch_apply dinput-axis-recalc/0001-dinput-Recalculated-Axis-after-deadzone-change.patch + ( + printf '%s\n' '+ { "Bruno Jesus", "dinput: Recalculated Axis after deadzone change.", 1 },'; + ) >> "$patchlist" +fi + # Patchset dinput-reconnect-joystick # | # | This patchset fixes the following Wine bugs: