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.
The existing code does not set any values outside the specified axes. This effectively sets the strength to zero along these axes. Testing setting just one axis with the MS Sidewinder 2 under Windows, however, reveals that revealed that it sets the first axis (the X-axis) to the given parameter values and sets the other axis to full strength (this is most easily felt/tested with the spring effect).
This sets unspecified axes in the SDL and udev input backends to play at full strength to agree with Windows. It also updates joy.cpl to play condition effects along the indicated axis too.
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.
What values should then be used for any unspecified axes under these? The exsting code implicitly sets playback strength to zero for unspesified axes. Testing a MS Sidewinder 2 under Windows and hidraw, however, indicates this is incorrect. Unspecified axes actually playback at full strength, not no strength.
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 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/dlls/joy.cpl/dinput.c b/dlls/joy.cpl/dinput.c index 925c6d0038c..d4bee27ce6f 100644 --- a/dlls/joy.cpl/dinput.c +++ b/dlls/joy.cpl/dinput.c @@ -92,12 +92,17 @@ 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, + /* Playback on y-axis only so rotates to correct position */ + { + }, + { + .dwPositiveSaturation = 10000, + .dwNegativeSaturation = 10000, + .lPositiveCoefficient = 10000, + .lNegativeCoefficient = 10000, + }, }; DIRAMPFORCE ramp = {
@rbernon another one for you stemming from the testing I was doing. I think this is it apart from the issue of autocenter.