Supersedes https://gitlab.winehq.org/wine/wine/-/merge_requests/8824
With some minor stylistic tweaks.
From: Tyson Whitehead twhitehead@gmail.com
Under Windows and the PID specification it is possible to specify less than the full set of condition blocks. Under SDL and the Linux FF input API all condition blocks must always be specified.
This sets unspecified axes in the SDL and input backends to play at full strength to agree with Windows and hidraw. --- dlls/winebus.sys/bus_sdl.c | 29 +++++++++++++++-------------- dlls/winebus.sys/bus_udev.c | 28 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 852541bf4f0..3a12183534a 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -652,6 +652,7 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT struct sdl_device *impl = impl_from_unix_device(iface); int id = impl->effect_ids[index]; SDL_HapticEffect effect = {0}; + int i; INT32 direction; NTSTATUS status;
@@ -699,23 +700,23 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.condition.direction.type = SDL_HAPTIC_SPHERICAL; effect.condition.direction.dir[0] = direction; effect.condition.direction.dir[1] = params->direction[1]; - if (params->condition_count >= 1) + + for (i = 0; i < max(params->condition_count, 3); i++) { - effect.condition.right_sat[0] = params->condition[0].positive_saturation; - effect.condition.left_sat[0] = params->condition[0].negative_saturation; - effect.condition.right_coeff[0] = params->condition[0].positive_coefficient; - effect.condition.left_coeff[0] = params->condition[0].negative_coefficient; - effect.condition.deadband[0] = params->condition[0].dead_band; - effect.condition.center[0] = params->condition[0].center_point_offset; + effect.condition.right_sat[i] = params->condition[i].positive_saturation; + effect.condition.left_sat[i] = params->condition[i].negative_saturation; + effect.condition.right_coeff[i] = params->condition[i].positive_coefficient; + effect.condition.left_coeff[i] = params->condition[i].negative_coefficient; + effect.condition.deadband[i] = params->condition[i].dead_band; + effect.condition.center[i] = params->condition[i].center_point_offset; } - if (params->condition_count >= 2) + /* Testing MS Sidewinder 2 indicates unspecified paramater blocks are full strength */ + for (; i < 3; i++) { - effect.condition.right_sat[1] = params->condition[1].positive_saturation; - effect.condition.left_sat[1] = params->condition[1].negative_saturation; - effect.condition.right_coeff[1] = params->condition[1].positive_coefficient; - effect.condition.left_coeff[1] = params->condition[1].negative_coefficient; - effect.condition.deadband[1] = params->condition[1].dead_band; - effect.condition.center[1] = params->condition[1].center_point_offset; + effect.condition.right_sat[i] = 65535; + effect.condition.left_sat[i] = 65535; + effect.condition.right_coeff[i] = 32767; + effect.condition.left_coeff[i] = 32767; } break;
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index e7b936198eb..5c108f59c4c 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -998,6 +998,7 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B { struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); struct ff_effect effect = {.id = impl->effect_ids[index]}; + int i; NTSTATUS status;
TRACE("iface %p, index %u, params %p.\n", iface, index, params); @@ -1035,23 +1036,22 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B case PID_USAGE_ET_DAMPER: case PID_USAGE_ET_INERTIA: case PID_USAGE_ET_FRICTION: - if (params->condition_count >= 1) + for (i = 0; i < max(params->condition_count, 2); i++) { - effect.u.condition[0].right_saturation = params->condition[0].positive_saturation; - effect.u.condition[0].left_saturation = params->condition[0].negative_saturation; - effect.u.condition[0].right_coeff = params->condition[0].positive_coefficient; - effect.u.condition[0].left_coeff = params->condition[0].negative_coefficient; - effect.u.condition[0].deadband = params->condition[0].dead_band; - effect.u.condition[0].center = params->condition[0].center_point_offset; + effect.u.condition[i].right_saturation = params->condition[i].positive_saturation; + effect.u.condition[i].left_saturation = params->condition[i].negative_saturation; + effect.u.condition[i].right_coeff = params->condition[i].positive_coefficient; + effect.u.condition[i].left_coeff = params->condition[i].negative_coefficient; + effect.u.condition[i].deadband = params->condition[i].dead_band; + effect.u.condition[i].center = params->condition[i].center_point_offset; } - if (params->condition_count >= 2) + /* Testing MS Sidewinder 2 indicates unspecified paramater blocks are full strength */ + for (; i < 2; i++) { - effect.u.condition[1].right_saturation = params->condition[1].positive_saturation; - effect.u.condition[1].left_saturation = params->condition[1].negative_saturation; - effect.u.condition[1].right_coeff = params->condition[1].positive_coefficient; - effect.u.condition[1].left_coeff = params->condition[1].negative_coefficient; - effect.u.condition[1].deadband = params->condition[1].dead_band; - effect.u.condition[1].center = params->condition[1].center_point_offset; + effect.u.condition[i].right_saturation = 65535; + effect.u.condition[i].left_saturation = 65535; + effect.u.condition[i].right_coeff = 32767; + effect.u.condition[i].left_coeff = 32767; } break;
From: Tyson Whitehead twhitehead@gmail.com
Testing with a MS Sidewinde 2 under Windows reveals that playing a codition effect on just one axis can only be done by explicitly setting the other axes to a zero strength as unspecified axes run at full strength and not no strength as might be expected.
The choosen axis must also be the Y axis in order for the result of the rotation to agree with what happens with non-condition effects. This is because the the -Y axis is the reference axis for the direction (i.e., no rotation plays back on the Y axis). --- dlls/joy.cpl/dinput.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 925c6d0038c..8838b0ffa1c 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -92,12 +92,15 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) .dwMagnitude = DI_FFNOMINALMAX, .dwPeriod = DI_SECONDS / 2, }; - DICONDITION condition = + DICONDITION condition[2] = { - .dwPositiveSaturation = 10000, - .dwNegativeSaturation = 10000, - .lPositiveCoefficient = 10000, - .lNegativeCoefficient = 10000, + {0}, + { + .dwPositiveSaturation = 10000, + .dwNegativeSaturation = 10000, + .lPositiveCoefficient = 10000, + .lNegativeCoefficient = 10000, + }, }; DIRAMPFORCE ramp = { @@ -130,8 +133,15 @@ static BOOL CALLBACK enum_effects( const DIEFFECTINFOW *info, void *context ) break; }
- do hr = IDirectInputDevice2_CreateEffect( device, &info->guid, ¶ms, &effect, NULL ); - while (FAILED(hr) && --params.cAxes); + do + { + hr = IDirectInputDevice2_CreateEffect( device, &info->guid, ¶ms, &effect, NULL ); + if (FAILED(hr) && DIEFT_GETTYPE(info->dwEffType) == DIEFT_CONDITION) + { + params.cbTypeSpecificParams = sizeof(condition[1]); + params.lpvTypeSpecificParams = &condition[1]; + } + } while (FAILED(hr) && --params.cAxes);
if (FAILED(hr)) {
This merge request was approved by Rémi Bernon.