Last active
March 22, 2018 23:43
-
-
Save Ryochan7/13f9f3fa77fd4097cd26d406a7ea9205 to your computer and use it in GitHub Desktop.
ViGEm integration into DS4Windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/DS4Windows/DS4Control/ControlService.cs b/DS4Windows/DS4Control/ControlService.cs | |
| index e8a164c..ae10895 100644 | |
| --- a/DS4Windows/DS4Control/ControlService.cs | |
| +++ b/DS4Windows/DS4Control/ControlService.cs | |
| @@ -7,6 +7,9 @@ using System.Media; | |
| using System.Threading.Tasks; | |
| using static DS4Windows.Global; | |
| using System.Threading; | |
| +using Nefarius.ViGEm.Client; | |
| +using Nefarius.ViGEm.Client.Targets; | |
| +using Nefarius.ViGEm.Client.Targets.Xbox360; | |
| using Registry = Microsoft.Win32.Registry; | |
| namespace DS4Windows | |
| @@ -14,6 +17,10 @@ namespace DS4Windows | |
| public class ControlService | |
| { | |
| public X360Device x360Bus = null; | |
| + public ViGEmClient vigemTestClient = null; | |
| + private const int inputResolution = 127 - (-128); | |
| + private const float reciprocalInputResolution = 1 / (float)inputResolution; | |
| + private const int outputResolution = 32767 - (-32768); | |
| public const int DS4_CONTROLLER_COUNT = 4; | |
| public DS4Device[] DS4Controllers = new DS4Device[DS4_CONTROLLER_COUNT]; | |
| public Mouse[] touchPad = new Mouse[DS4_CONTROLLER_COUNT]; | |
| @@ -28,6 +35,10 @@ namespace DS4Windows | |
| bool[] buttonsdown = new bool[4] { false, false, false, false }; | |
| bool[] held = new bool[DS4_CONTROLLER_COUNT]; | |
| int[] oldmouse = new int[DS4_CONTROLLER_COUNT] { -1, -1, -1, -1 }; | |
| + public Xbox360Controller[] x360controls = new Xbox360Controller[4] { null, null, null, null }; | |
| + private Xbox360Report[] x360reports = new Xbox360Report[4] { new Xbox360Report(), new Xbox360Report(), | |
| + new Xbox360Report(), new Xbox360Report() | |
| + }; | |
| Thread tempThread; | |
| public List<string> affectedDevs = new List<string>() | |
| { | |
| @@ -122,14 +133,44 @@ namespace DS4Windows | |
| return unplugResult; | |
| } | |
| + private void startViGEm() | |
| + { | |
| + tempThread = new Thread(() => { try { vigemTestClient = new ViGEmClient(); } catch { } }); | |
| + tempThread.Priority = ThreadPriority.AboveNormal; | |
| + tempThread.IsBackground = true; | |
| + tempThread.Start(); | |
| + while (tempThread.IsAlive) | |
| + { | |
| + Thread.SpinWait(500); | |
| + } | |
| + } | |
| + | |
| + private void stopViGEm() | |
| + { | |
| + if (tempThread != null) | |
| + { | |
| + tempThread.Interrupt(); | |
| + tempThread.Join(); | |
| + tempThread = null; | |
| + } | |
| + | |
| + if (vigemTestClient != null) | |
| + { | |
| + vigemTestClient.Dispose(); | |
| + vigemTestClient = null; | |
| + } | |
| + } | |
| + | |
| public bool Start(object tempui, bool showlog = true) | |
| { | |
| - if (x360Bus.Open() && x360Bus.Start()) | |
| + startViGEm(); | |
| + if (vigemTestClient != null) | |
| + //if (x360Bus.Open() && x360Bus.Start()) | |
| { | |
| if (showlog) | |
| LogDebug(Properties.Resources.Starting); | |
| - LogDebug("Connection to Scp Virtual Bus established"); | |
| + LogDebug("Connection to ViGEm established"); | |
| DS4Devices.isExclusiveMode = getUseExclusiveMode(); | |
| if (showlog) | |
| @@ -176,11 +217,17 @@ namespace DS4Windows | |
| if (!getDInputOnly(i) && device.isSynced()) | |
| { | |
| - int xinputIndex = x360Bus.FirstController + i; | |
| - LogDebug("Plugging in X360 Controller #" + xinputIndex); | |
| - bool xinputResult = x360Bus.Plugin(i); | |
| - LogDebug("X360 Controller # " + xinputIndex + " connected"); | |
| + //int xinputIndex = x360Bus.FirstController + i; | |
| + LogDebug("Plugging in X360 Controller #" + (i + 1)); | |
| useDInputOnly[i] = false; | |
| + x360controls[i] = new Xbox360Controller(vigemTestClient); | |
| + x360controls[i].Connect(); | |
| + int devIndex = i; | |
| + x360controls[i].FeedbackReceived += (sender, args) => | |
| + { | |
| + setRumble(args.SmallMotor, args.LargeMotor, devIndex); | |
| + }; | |
| + LogDebug("X360 Controller # " + (i + 1) + " connected"); | |
| } | |
| device.Report += this.On_Report; | |
| @@ -219,7 +266,7 @@ namespace DS4Windows | |
| } | |
| else | |
| { | |
| - string logMessage = "Could not connect to Scp Virtual Bus Driver. Please check the status of the System device in Device Manager"; | |
| + string logMessage = "Could not connect to ViGEm. Please check the status of the System device in Device Manager"; | |
| LogDebug(logMessage); | |
| Log.LogToTray(logMessage); | |
| } | |
| @@ -238,9 +285,8 @@ namespace DS4Windows | |
| if (showlog) | |
| LogDebug(Properties.Resources.StoppingX360); | |
| - LogDebug("Closing connection to Scp Virtual Bus"); | |
| + LogDebug("Closing connection to ViGEm"); | |
| - bool anyUnplugged = false; | |
| for (int i = 0, arlength = DS4Controllers.Length; i < arlength; i++) | |
| { | |
| DS4Device tempDevice = DS4Controllers[i]; | |
| @@ -272,9 +318,9 @@ namespace DS4Windows | |
| } | |
| CurrentState[i].Battery = PreviousState[i].Battery = 0; // Reset for the next connection's initial status change. | |
| - x360Bus.Unplug(i); | |
| + x360controls[i]?.Disconnect(); | |
| + x360controls[i] = null; | |
| useDInputOnly[i] = true; | |
| - anyUnplugged = true; | |
| DS4Controllers[i] = null; | |
| touchPad[i] = null; | |
| lag[i] = false; | |
| @@ -282,18 +328,14 @@ namespace DS4Windows | |
| } | |
| } | |
| - if (anyUnplugged) | |
| - Thread.Sleep(XINPUT_UNPLUG_SETTLE_TIME); | |
| - | |
| - x360Bus.UnplugAll(); | |
| - x360Bus.Stop(); | |
| - | |
| if (showlog) | |
| LogDebug(Properties.Resources.StoppingDS4); | |
| DS4Devices.stopControllers(); | |
| if (showlog) | |
| LogDebug(Properties.Resources.StoppedDS4Windows); | |
| + | |
| + stopViGEm(); | |
| } | |
| runHotPlug = false; | |
| @@ -358,11 +400,17 @@ namespace DS4Windows | |
| device.Report += this.On_Report; | |
| if (!getDInputOnly(Index) && device.isSynced()) | |
| { | |
| - int xinputIndex = x360Bus.FirstController + Index; | |
| - LogDebug("Plugging in X360 Controller #" + xinputIndex); | |
| - bool xinputResult = x360Bus.Plugin(Index); | |
| - LogDebug("X360 Controller # " + xinputIndex + " connected"); | |
| + //int xinputIndex = x360Bus.FirstController + Index; | |
| + LogDebug("Plugging in X360 Controller #" + (Index + 1)); | |
| useDInputOnly[Index] = false; | |
| + x360controls[Index] = new Xbox360Controller(vigemTestClient); | |
| + x360controls[Index].Connect(); | |
| + int devIndex = Index; | |
| + x360controls[Index].FeedbackReceived += (sender, args) => | |
| + { | |
| + setRumble(args.SmallMotor, args.LargeMotor, devIndex); | |
| + }; | |
| + LogDebug("X360 Controller # " + (Index + 1) + " connected"); | |
| } | |
| TouchPadOn(Index, device); | |
| @@ -392,6 +440,49 @@ namespace DS4Windows | |
| return true; | |
| } | |
| + private void testNewReport(ref Xbox360Report xboxreport, DS4State state) | |
| + { | |
| + Xbox360Buttons tempButtons = 0; | |
| + | |
| + if (state.Share) tempButtons |= Xbox360Buttons.Back; | |
| + if (state.L3) tempButtons |= Xbox360Buttons.LeftThumb; | |
| + if (state.R3) tempButtons |= Xbox360Buttons.RightThumb; | |
| + if (state.Options) tempButtons |= Xbox360Buttons.Start; | |
| + | |
| + if (state.DpadUp) tempButtons |= Xbox360Buttons.Up; | |
| + if (state.DpadRight) tempButtons |= Xbox360Buttons.Right; | |
| + if (state.DpadDown) tempButtons |= Xbox360Buttons.Down; | |
| + if (state.DpadLeft) tempButtons |= Xbox360Buttons.Left; | |
| + | |
| + if (state.L1) tempButtons |= Xbox360Buttons.LeftShoulder; | |
| + if (state.R1) tempButtons |= Xbox360Buttons.RightShoulder; | |
| + | |
| + if (state.Triangle) tempButtons |= Xbox360Buttons.Y; | |
| + if (state.Circle) tempButtons |= Xbox360Buttons.B; | |
| + if (state.Cross) tempButtons |= Xbox360Buttons.A; | |
| + if (state.Square) tempButtons |= Xbox360Buttons.X; | |
| + if (state.PS) tempButtons |= Xbox360Buttons.Guide; | |
| + xboxreport.SetButtons(tempButtons); | |
| + | |
| + xboxreport.LeftTrigger = state.L2; | |
| + xboxreport.RightTrigger = state.R2; | |
| + xboxreport.LeftThumbX = AxisScale(state.LX, false); | |
| + xboxreport.LeftThumbY = AxisScale(state.LY, true); | |
| + xboxreport.RightThumbX = AxisScale(state.RX, false); | |
| + xboxreport.RightThumbY = AxisScale(state.RY, true); | |
| + } | |
| + | |
| + private short AxisScale(Int32 Value, Boolean Flip) | |
| + { | |
| + Value -= 0x80; | |
| + | |
| + //float temp = (Value - (-128)) / (float)inputResolution; | |
| + float temp = (Value - (-128)) * reciprocalInputResolution; | |
| + if (Flip) temp = (temp - 0.5f) * -1.0f + 0.5f; | |
| + | |
| + return (short) (temp * outputResolution + (-32768)); | |
| + } | |
| + | |
| private void CheckProfileOptions(int ind, DS4Device device, bool startUp=false) | |
| { | |
| device.setIdleTimeout(getIdleDisconnectTimeout(ind)); | |
| @@ -607,21 +698,25 @@ namespace DS4Windows | |
| { | |
| if (!useDInputOnly[ind]) | |
| { | |
| - bool unplugResult = x360Bus.Unplug(ind); | |
| - int xinputIndex = x360Bus.FirstController + ind; | |
| - LogDebug("X360 Controller # " + xinputIndex + " unplugged"); | |
| + x360controls[ind].Disconnect(); | |
| + x360controls[ind] = null; | |
| useDInputOnly[ind] = true; | |
| + LogDebug("X360 Controller # " + (ind + 1) + " unplugged"); | |
| } | |
| } | |
| else | |
| { | |
| if (!getDInputOnly(ind)) | |
| { | |
| - int xinputIndex = x360Bus.FirstController + ind; | |
| - LogDebug("Plugging in X360 Controller #" + xinputIndex); | |
| - bool xinputResult = x360Bus.Plugin(ind); | |
| - LogDebug("X360 Controller # " + xinputIndex + " connected"); | |
| + LogDebug("Plugging in X360 Controller #" + (ind + 1)); | |
| + x360controls[ind] = new Xbox360Controller(vigemTestClient); | |
| + x360controls[ind].Connect(); | |
| + x360controls[ind].FeedbackReceived += (eventsender, args) => | |
| + { | |
| + setRumble(args.SmallMotor, args.LargeMotor, ind); | |
| + }; | |
| useDInputOnly[ind] = false; | |
| + LogDebug("X360 Controller # " + (ind + 1) + " connected"); | |
| } | |
| } | |
| } | |
| @@ -655,9 +750,9 @@ namespace DS4Windows | |
| CurrentState[ind].Battery = PreviousState[ind].Battery = 0; // Reset for the next connection's initial status change. | |
| if (!useDInputOnly[ind]) | |
| { | |
| - bool unplugResult = x360Bus.Unplug(ind); | |
| - int xinputIndex = x360Bus.FirstController + ind; | |
| - LogDebug("X360 Controller # " + xinputIndex + " unplugged"); | |
| + x360controls[ind].Disconnect(); | |
| + x360controls[ind] = null; | |
| + LogDebug("X360 Controller # " + (ind + 1) + " unplugged"); | |
| } | |
| string removed = Properties.Resources.ControllerWasRemoved.Replace("*Mac address*", (ind + 1).ToString()); | |
| @@ -688,7 +783,6 @@ namespace DS4Windows | |
| inWarnMonitor[ind] = false; | |
| useDInputOnly[ind] = true; | |
| OnControllerRemoved(this, ind); | |
| - Thread.Sleep(XINPUT_UNPLUG_SETTLE_TIME); | |
| } | |
| } | |
| } | |
| @@ -793,10 +887,12 @@ namespace DS4Windows | |
| if (!useDInputOnly[ind]) | |
| { | |
| - x360Bus.Parse(cState, processingData[ind].Report, ind); | |
| + testNewReport(ref x360reports[ind], cState); | |
| + x360controls[ind]?.SendReport(x360reports[ind]); | |
| + //x360Bus.Parse(cState, processingData[ind].Report, ind); | |
| // We push the translated Xinput state, and simultaneously we | |
| // pull back any possible rumble data coming from Xinput consumers. | |
| - if (x360Bus.Report(processingData[ind].Report, processingData[ind].Rumble)) | |
| + /*if (x360Bus.Report(processingData[ind].Report, processingData[ind].Rumble)) | |
| { | |
| byte Big = processingData[ind].Rumble[3]; | |
| byte Small = processingData[ind].Rumble[4]; | |
| @@ -806,6 +902,7 @@ namespace DS4Windows | |
| setRumble(Big, Small, ind); | |
| } | |
| } | |
| + */ | |
| } | |
| // Output any synthetic events. | |
| diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs | |
| index 807a926..e67a646 100644 | |
| --- a/DS4Windows/DS4Control/ScpUtil.cs | |
| +++ b/DS4Windows/DS4Control/ScpUtil.cs | |
| @@ -315,9 +315,9 @@ namespace DS4Windows | |
| dataBuffer, dataBuffer.Length, ref requiredSize, 0)) | |
| { | |
| string hardwareId = dataBuffer.ToUTF16String(); | |
| - //if (hardwareIds.Contains("Scp Virtual Bus Driver")) | |
| + //if (hardwareIds.Contains("Virtual Gamepad Emulation Bus")) | |
| // result = true; | |
| - if (hardwareId.Equals(@"root\ScpVBus")) | |
| + if (hardwareId.Equals(@"Root\ViGEmBus")) | |
| result = true; | |
| } | |
| } | |
| @@ -2843,15 +2843,15 @@ namespace DS4Windows | |
| tempDev.setBTPollRate(btPollRate[device]); | |
| if (xinputStatus && xinputPlug) | |
| { | |
| - bool xinputResult = control.x360Bus.Plugin(device); | |
| - int xinputIndex = control.x360Bus.FirstController + device; | |
| - Log.LogToGui("X360 Controller # " + xinputIndex + " connected", false); | |
| + control.x360controls[device] = new Nefarius.ViGEm.Client.Targets.Xbox360Controller(control.vigemTestClient); | |
| + control.x360controls[device].Connect(); | |
| + Log.LogToGui("X360 Controller # " + (device + 1) + " connected", false); | |
| } | |
| else if (xinputStatus && !xinputPlug) | |
| { | |
| - bool xinputResult = control.x360Bus.Unplug(device); | |
| - int xinputIndex = control.x360Bus.FirstController + device; | |
| - Log.LogToGui("X360 Controller # " + xinputIndex + " unplugged", false); | |
| + control.x360controls[device].Disconnect(); | |
| + control.x360controls[device] = null; | |
| + Log.LogToGui("X360 Controller # " + (device + 1) + " unplugged", false); | |
| } | |
| tempDev.setRumble(0, 0); | |
| diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs | |
| index 3ab369c..450a311 100644 | |
| --- a/DS4Windows/DS4Forms/DS4Form.cs | |
| +++ b/DS4Windows/DS4Forms/DS4Form.cs | |
| @@ -202,7 +202,7 @@ namespace DS4Windows | |
| cBDisconnectBT.Checked = DCBTatStop; | |
| cBQuickCharge.Checked = QuickCharge; | |
| nUDXIPorts.Value = FirstXinputPort; | |
| - Program.rootHub.x360Bus.FirstController = FirstXinputPort; | |
| + //Program.rootHub.x360Bus.FirstController = FirstXinputPort; | |
| // New settings | |
| this.Width = FormWidth; | |
| this.Height = FormHeight; | |
| @@ -2185,7 +2185,7 @@ Properties.Resources.DS4Update, MessageBoxButtons.YesNo, MessageBoxIcon.Question | |
| { | |
| oldxiport = (int)Math.Round(nUDXIPorts.Value, 0); | |
| FirstXinputPort = oldxiport; | |
| - Program.rootHub.x360Bus.FirstController = oldxiport; | |
| + //Program.rootHub.x360Bus.FirstController = oldxiport; | |
| BtnStartStop_Clicked(false); | |
| finishHideDS4Check(); | |
| } | |
| diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj | |
| index a6353ce..e40d54b 100644 | |
| --- a/DS4Windows/DS4Windows.csproj | |
| +++ b/DS4Windows/DS4Windows.csproj | |
| @@ -123,6 +123,9 @@ | |
| <Reference Include="Microsoft.Win32.TaskScheduler, Version=2.7.2.0, Culture=neutral, PublicKeyToken=c416bc1b32d97233, processorArchitecture=MSIL"> | |
| <HintPath>..\packages\TaskScheduler.2.7.2\lib\net452\Microsoft.Win32.TaskScheduler.dll</HintPath> | |
| </Reference> | |
| + <Reference Include="Nefarius.ViGEmClient"> | |
| + <HintPath>..\bin\Nefarius.ViGEmClient\Nefarius.ViGEmClient.dll</HintPath> | |
| + </Reference> | |
| <Reference Include="System" /> | |
| <Reference Include="System.Core" /> | |
| <Reference Include="System.IO.Compression" /> | |
| @@ -1235,4 +1238,4 @@ for %25%25l in (%25langs%25) do ( | |
| <Target Name="AfterBuild"> | |
| </Target> | |
| --> | |
| -</Project> | |
| \ No newline at end of file | |
| +</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment