From 8a561d1cde394029c44192024f0835ae8b9a1c04 Mon Sep 17 00:00:00 2001 From: mika-n Date: Thu, 9 May 2019 21:32:29 +0300 Subject: [PATCH] Steering wheel emulation for the new dualshock4 controller output option. --- DS4Windows/DS4Control/DS4OutDevice.cs | 68 +++++++++++++++++++++++++-- DS4Windows/DS4Control/Mapping.cs | 28 ++++++++--- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/DS4Windows/DS4Control/DS4OutDevice.cs b/DS4Windows/DS4Control/DS4OutDevice.cs index 05bf2bb..c477cf7 100644 --- a/DS4Windows/DS4Control/DS4OutDevice.cs +++ b/DS4Windows/DS4Control/DS4OutDevice.cs @@ -72,10 +72,70 @@ namespace DS4Windows report.LeftTrigger = state.L2; report.RightTrigger = state.R2; - report.LeftThumbX = state.LX; - report.LeftThumbY = state.LY; - report.RightThumbX = state.RX; - report.RightThumbY = state.RY; + + SASteeringWheelEmulationAxisType steeringWheelMappedAxis = Global.GetSASteeringWheelEmulationAxis(device); + switch (steeringWheelMappedAxis) + { + case SASteeringWheelEmulationAxisType.None: + report.LeftThumbX = state.LX; + report.LeftThumbY = state.LY; + report.RightThumbX = state.RX; + report.RightThumbY = state.RY; + break; + + case SASteeringWheelEmulationAxisType.LX: + report.LeftThumbX = (byte)state.SASteeringWheelEmulationUnit; + report.LeftThumbY = state.LY; + report.RightThumbX = state.RX; + report.RightThumbY = state.RY; + break; + + case SASteeringWheelEmulationAxisType.LY: + report.LeftThumbX = state.LX; + report.LeftThumbY = (byte)state.SASteeringWheelEmulationUnit; + report.RightThumbX = state.RX; + report.RightThumbY = state.RY; + break; + + case SASteeringWheelEmulationAxisType.RX: + report.LeftThumbX = state.LX; + report.LeftThumbY = state.LY; + report.RightThumbX = (byte)state.SASteeringWheelEmulationUnit; + report.RightThumbY = state.RY; + break; + + case SASteeringWheelEmulationAxisType.RY: + report.LeftThumbX = state.LX; + report.LeftThumbY = state.LY; + report.RightThumbX = state.RX; + report.RightThumbY = (byte)state.SASteeringWheelEmulationUnit; + break; + + case SASteeringWheelEmulationAxisType.L2R2: + report.LeftTrigger = report.RightTrigger = 0; + if (state.SASteeringWheelEmulationUnit >= 0) report.LeftTrigger = (Byte)state.SASteeringWheelEmulationUnit; + else report.RightTrigger = (Byte)state.SASteeringWheelEmulationUnit; + goto case SASteeringWheelEmulationAxisType.None; + + case SASteeringWheelEmulationAxisType.VJoy1X: + case SASteeringWheelEmulationAxisType.VJoy2X: + DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_X); + goto case SASteeringWheelEmulationAxisType.None; + + case SASteeringWheelEmulationAxisType.VJoy1Y: + case SASteeringWheelEmulationAxisType.VJoy2Y: + DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_Y); + goto case SASteeringWheelEmulationAxisType.None; + + case SASteeringWheelEmulationAxisType.VJoy1Z: + case SASteeringWheelEmulationAxisType.VJoy2Z: + DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_Z); + goto case SASteeringWheelEmulationAxisType.None; + + default: + // Should never come here but just in case use the NONE case as default handler.... + goto case SASteeringWheelEmulationAxisType.None; + } cont.SendReport(report); } diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index c6e8fc8..b7500a5 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -4058,6 +4058,22 @@ namespace DS4Windows // Apply anti-deadzone (SA X-antideadzone value) double sxAntiDead = getSXAntiDeadzone(device); + int outputAxisMax, outputAxisMin, outputAxisZero; + if ( Global.OutContType[device] == OutContType.DS4 ) + { + // DS4 analog stick axis supports only 0...255 output value range (not the best one for steering wheel usage) + outputAxisMax = 255; + outputAxisMin = 0; + outputAxisZero = 128; + } + else + { + // x360 (xinput) analog stick axis supports -32768...32767 output value range (more than enough for steering wheel usage) + outputAxisMax = 32767; + outputAxisMin = -32768; + outputAxisZero = 0; + } + switch (Global.GetSASteeringWheelEmulationAxis(device)) { case SASteeringWheelEmulationAxisType.LX: @@ -4066,23 +4082,22 @@ namespace DS4Windows case SASteeringWheelEmulationAxisType.RY: // DS4 thumbstick axis output (-32768..32767 raw value range) //return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); - if (result == 0) return 0; + if (result == 0) return outputAxisZero; if (sxAntiDead > 0) { - sxAntiDead *= 32767; - if (result < 0) return (((result - maxRangeLeft) * (-Convert.ToInt32(sxAntiDead) - (-32768))) / (0 - maxRangeLeft)) + (-32768); - else return (((result - 0) * (32767 - (Convert.ToInt32(sxAntiDead)))) / (maxRangeRight - 0)) + (Convert.ToInt32(sxAntiDead)); + sxAntiDead *= (outputAxisMax - outputAxisZero); + if (result < 0) return (((result - maxRangeLeft) * (-Convert.ToInt32(sxAntiDead) - (outputAxisMin))) / (0 - maxRangeLeft)) + (outputAxisMin); + else return (((result - 0) * (outputAxisMax - (Convert.ToInt32(sxAntiDead)))) / (maxRangeRight - 0)) + (Convert.ToInt32(sxAntiDead)); } else { - return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + return (((result - maxRangeLeft) * (outputAxisMax - (outputAxisMin))) / (maxRangeRight - maxRangeLeft)) + (outputAxisMin); } case SASteeringWheelEmulationAxisType.L2R2: // DS4 Trigger axis output. L2+R2 triggers share the same axis in x360 xInput/DInput controller, // so L2+R2 steering output supports only 360 turn range (-255..255 raw value range in the shared trigger axis) - // return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); if (result == 0) return 0; result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); @@ -4106,7 +4121,6 @@ namespace DS4Windows case SASteeringWheelEmulationAxisType.VJoy2Y: case SASteeringWheelEmulationAxisType.VJoy2Z: // SASteeringWheelEmulationAxisType.VJoy1X/VJoy1Y/VJoy1Z/VJoy2X/VJoy2Y/VJoy2Z VJoy axis output (0..32767 raw value range by default) - // return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); if (result == 0) return 16384; if (sxAntiDead > 0)