Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch DirectInput+XInput+XAudio2/OpenAL to use Vortice/SilkNET instead of SlimDX/OpenTK3 #3622

Closed
17 changes: 12 additions & 5 deletions BizHawk.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28729.10

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33516.290
MinimumVisualStudioVersion = 16.0.28729.10
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Version", "src\BizHawk.Version\BizHawk.Version.csproj", "{0CE8B337-08E3-4602-BF10-C4D4C75D2F13}"
EndProject
Expand Down Expand Up @@ -45,9 +46,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Emulation.Cores", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.BizwareGL", "src\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj", "{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.DirectX", "src\BizHawk.Bizware.DirectX\BizHawk.Bizware.DirectX.csproj", "{A914D063-9E4B-4086-B156-7B3F39E33DB2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.DirectX", "src\BizHawk.Bizware.DirectX\BizHawk.Bizware.DirectX.csproj", "{A914D063-9E4B-4086-B156-7B3F39E33DB2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.OpenTK3", "src\BizHawk.Bizware.OpenTK3\BizHawk.Bizware.OpenTK3.csproj", "{1FF433CC-96E1-4F14-B673-CDA7190169C9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.OpenTK3", "src\BizHawk.Bizware.OpenTK3\BizHawk.Bizware.OpenTK3.csproj", "{1FF433CC-96E1-4F14-B673-CDA7190169C9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.SilkNET", "src\BizHawk.Bizware.SilkNET\BizHawk.Bizware.SilkNET.csproj", "{48AAED49-6F4B-4877-B0E5-6FB392DC042C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.BizInvoke", "src\BizHawk.BizInvoke\BizHawk.BizInvoke.csproj", "{E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}"
EndProject
Expand Down Expand Up @@ -107,6 +110,10 @@ Global
{1FF433CC-96E1-4F14-B673-CDA7190169C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FF433CC-96E1-4F14-B673-CDA7190169C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FF433CC-96E1-4F14-B673-CDA7190169C9}.Release|Any CPU.Build.0 = Release|Any CPU
{48AAED49-6F4B-4877-B0E5-6FB392DC042C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48AAED49-6F4B-4877-B0E5-6FB392DC042C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48AAED49-6F4B-4877-B0E5-6FB392DC042C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48AAED49-6F4B-4877-B0E5-6FB392DC042C}.Release|Any CPU.Build.0 = Release|Any CPU
{E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down
6 changes: 6 additions & 0 deletions src/BizHawk.Bizware.DirectX/BizHawk.Bizware.DirectX.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Vortice.DirectInput" Version="2.4.2" />
<PackageReference Include="Vortice.MediaFoundation" Version="2.4.2" />
<PackageReference Include="Vortice.XAudio2" Version="2.4.2" />
<PackageReference Include="Vortice.XInput" Version="2.4.2" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms" />
<Reference Include="SlimDX" HintPath="$(ProjectDir)../../References/x64/SlimDX.dll" Private="true" />
Expand Down
118 changes: 69 additions & 49 deletions src/BizHawk.Bizware.DirectX/GamePad.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,65 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;

using BizHawk.Common;

using SlimDX;
using SlimDX.DirectInput;
using Vortice.DirectInput;

namespace BizHawk.Bizware.DirectX
{
internal sealed class GamePad
{
private static readonly object SyncObj = new object();
private static readonly List<GamePad> Devices = new List<GamePad>();
private static DirectInput _directInput;
private static readonly object SyncObj = new();
private static readonly List<GamePad> Devices = new();
private static IDirectInput8 _directInput;

public static void Initialize(IntPtr mainFormHandle)
{
lock (SyncObj)
{
Cleanup();

_directInput = new DirectInput();
_directInput = DInput.DirectInput8Create();

foreach (DeviceInstance device in _directInput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly))
foreach (var device in _directInput.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly))
{
Console.WriteLine("joy device: {0} `{1}`", device.InstanceGuid, device.ProductName);

if (device.ProductName.Contains("XBOX 360") || device.ProductName.Contains("Xbox One") || device.ProductName.Contains("XINPUT"))
continue; // Don't input XBOX 360 controllers into here; we'll process them via XInput (there are limitations in some trigger axes when xbox pads go over xinput)

var joystick = new Joystick(_directInput, device.InstanceGuid);
joystick.SetCooperativeLevel(mainFormHandle, CooperativeLevel.Background | CooperativeLevel.Nonexclusive);
foreach (DeviceObjectInstance deviceObject in joystick.GetObjects())
var joystick = _directInput.CreateDevice(device.InstanceGuid);
joystick.SetCooperativeLevel(mainFormHandle, CooperativeLevel.Background | CooperativeLevel.NonExclusive);
joystick.SetDataFormat<RawJoystickState>();
#if false
// GetObjects returns localized names, so this doesn't actually work
foreach (var deviceObject in joystick.GetObjects(DeviceObjectTypeFlags.Axis))
{
if ((deviceObject.ObjectType & ObjectDeviceType.Axis) != 0)
{
joystick.GetObjectPropertiesById((int)deviceObject.ObjectType).SetRange(-1000, 1000);
}
joystick.GetObjectPropertiesByName(deviceObject.Name).Range = new(-1000, 1000);
}
#elif false
// when https://github.com/amerkoleci/Vortice.Windows/issues/393 is fixed, this is what we should do
foreach (var deviceObject in joystick.GetObjects(DeviceObjectTypeFlags.Axis))
{
joystick.GetObjectPropertiesById(deviceObject.ObjectId).Range = new(-1000, 1000);
}
#else
// hack due to the above problems
var dict = (Dictionary<string, ObjectDataFormat>)typeof(IDirectInputDevice8)
.GetField("_mapNameToObjectFormat", BindingFlags.Instance | BindingFlags.NonPublic)!
.GetValue(joystick);

foreach (var deviceObject in joystick.GetObjects(DeviceObjectTypeFlags.Axis))
{
joystick.GetObjectPropertiesByName(dict.Values.First(odf => odf.Guid == deviceObject.ObjectType).Name!).Range = new(-1000, 1000);
}
#endif
joystick.Acquire();

GamePad p = new GamePad(joystick, Devices.Count);
var p = new GamePad(joystick, Devices.Count);
Devices.Add(p);
}
}
Expand Down Expand Up @@ -89,10 +108,10 @@ public static void Cleanup()

// ********************************** Instance Members **********************************

private readonly Joystick _joystick;
private JoystickState _state = new JoystickState();
private readonly IDirectInputDevice8 _joystick;
private JoystickState _state = new();

private GamePad(Joystick joystick, int index)
private GamePad(IDirectInputDevice8 joystick, int index)
{
_joystick = joystick;
PlayerNumber = index + 1;
Expand All @@ -105,7 +124,7 @@ public void Update()
{
try
{
if (_joystick.Acquire().IsFailure)
if (_joystick.Acquire().Failure)
return;
}
catch
Expand All @@ -114,24 +133,26 @@ public void Update()
}

if (_joystick.Poll()
.IsFailure)
.Failure)
{
return;
}

_state = _joystick.GetCurrentState();
if (Result.Last.IsFailure)
try
{
_joystick.GetCurrentJoystickState(ref _state);
}
catch (SharpGen.Runtime.SharpGenException)
{
// do something?
return;
}
}

private static readonly ImmutableArray<PropertyInfo> _axesPropertyInfos = typeof(JoystickState).GetProperties().Where(pi => pi.PropertyType == typeof(int)).ToImmutableArray();

public IEnumerable<(string AxisID, float Value)> GetAxes()
{
var pis = typeof(JoystickState).GetProperties();
foreach (var pi in pis)
{
yield return (pi.Name, 10.0f * (float)(int)pi.GetValue(_state, null));
}
return _axesPropertyInfos.Select(pi => (pi.Name, 10.0f * (int)pi.GetValue(_state)));
}

/// <summary>FOR DEBUGGING ONLY</summary>
Expand All @@ -156,8 +177,8 @@ public bool Pressed(int index)

public int NumButtons { get; private set; }

private readonly List<string> _names = new List<string>();
private readonly List<Func<bool>> _actions = new List<Func<bool>>();
private readonly List<string> _names = new();
private readonly List<Func<bool>> _actions = new();

private void AddItem(string name, Func<bool> callback)
{
Expand Down Expand Up @@ -226,22 +247,22 @@ private void InitializeCallbacks()

// i don't know what the "Slider"s do, so they're omitted for the moment

for (int i = 0; i < _state.GetButtons().Length; i++)
for (var i = 0; i < _state.Buttons.Length; i++)
{
int j = i;
AddItem($"B{i + 1}", () => _state.IsPressed(j));
var j = i;
AddItem($"B{i + 1}", () => _state.Buttons[j]);
}

for (int i = 0; i < _state.GetPointOfViewControllers().Length; i++)
for (var i = 0; i < _state.PointOfViewControllers.Length; i++)
{
int j = i;
var j = i;
AddItem($"POV{i + 1}U", () => {
var t = _state.GetPointOfViewControllers()[j];
var t = _state.PointOfViewControllers[j];
return 0.RangeTo(4500).Contains(t) || 31500.RangeToExclusive(36000).Contains(t);
});
AddItem($"POV{i + 1}D", () => 13500.RangeTo(22500).Contains(_state.GetPointOfViewControllers()[j]));
AddItem($"POV{i + 1}L", () => 22500.RangeTo(31500).Contains(_state.GetPointOfViewControllers()[j]));
AddItem($"POV{i + 1}R", () => 4500.RangeTo(13500).Contains(_state.GetPointOfViewControllers()[j]));
AddItem($"POV{i + 1}D", () => 13500.RangeTo(22500).Contains(_state.PointOfViewControllers[j]));
AddItem($"POV{i + 1}L", () => 22500.RangeTo(31500).Contains(_state.PointOfViewControllers[j]));
AddItem($"POV{i + 1}R", () => 4500.RangeTo(13500).Contains(_state.PointOfViewControllers[j]));
}
}

Expand All @@ -252,18 +273,17 @@ public void SetVibration(int left, int right)
// I should just look for C++ examples instead of trying to look for SlimDX examples

var parameters = new EffectParameters
{
Duration = 0x2710,
Gain = 0x2710,
SamplePeriod = 0,
TriggerButton = 0,
TriggerRepeatInterval = 0x2710,
Flags = EffectFlags.None
};
{
Duration = 0x2710,
Gain = 0x2710,
SamplePeriod = 0,
TriggerButton = 0,
TriggerRepeatInterval = 0x2710,
Flags = EffectFlags.None
};
parameters.GetAxes(out var temp1, out var temp2);
parameters.SetAxes(temp1, temp2);
var effect = new Effect(_joystick, EffectGuid.ConstantForce);
effect.SetParameters(parameters);
var effect = _joystick.CreateEffect(EffectGuid.ConstantForce, parameters);
effect.Start(1);
}
}
Expand Down
Loading