Skip to content

Instantly share code, notes, and snippets.

@Ryochan7
Last active March 22, 2018 23:43
Show Gist options
  • Select an option

  • Save Ryochan7/13f9f3fa77fd4097cd26d406a7ea9205 to your computer and use it in GitHub Desktop.

Select an option

Save Ryochan7/13f9f3fa77fd4097cd26d406a7ea9205 to your computer and use it in GitHub Desktop.
ViGEm integration into DS4Windows
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