From 24829b2ba6d5efd950f178b8282dda826c4d1df0 Mon Sep 17 00:00:00 2001
From: Bruno Jesus <bjesus@codeweavers.com>
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 433348cd04..c150528e3d 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -312,6 +312,76 @@ BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
     return (devcaps->dwAxes == 6 && devcaps->dwButtons >= 14);
 }
 
+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
   */
@@ -319,7 +389,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);
 
@@ -336,69 +405,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;
         }
@@ -407,15 +422,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;
         }
@@ -424,15 +437,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;
         }
-- 
2.17.1