mirror of
https://github.com/cemu-project/DS4Windows.git
synced 2025-01-10 07:19:24 +01:00
7673d6351a
Special Actions: press a control or a set of controls to perform a macro, launch a program/file, or load a different profile. Create new actions in profile options, and check which ones you want the selected profile to use. Set an analog curve for the left and right stick, see the changes live in the controller readout Option to set the close button to minimize DS4Windows, and truly close it by the notification icon Added Spanish Translations (added credits to the translations sheets so users can be properly thanked if wanted to be) Sticks Deadzone reworked from being a square to radial as the controller readout actually shows Fix pressing keyboard not setting an action for controls Fix Tilts and Swipes controls not showing text in the control list Fix program crashing when uses x360 macros with shift controls Fix for trying to edit a profile from the context menu after never restoring DS4Windows form start. Fix for settings low flash color Now running with startup will always start minimized, even if start minimized is unchecked
229 lines
6.9 KiB
C#
229 lines
6.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Windows.Forms;
|
|
using DS4Library;
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.Win32.SafeHandles;
|
|
|
|
namespace DS4Control
|
|
{
|
|
public partial class X360Device : ScpDevice
|
|
{
|
|
private const String DS3_BUS_CLASS_GUID = "{F679F562-3164-42CE-A4DB-E7DDBE723909}";
|
|
private const int CONTROLLER_OFFSET = 1; // Device 0 is the virtual USB hub itself, and we leave devices 1-10 available for other software (like the Scarlet.Crush DualShock driver itself)
|
|
|
|
private int firstController = 1;
|
|
// Device 0 is the virtual USB hub itself, and we can leave more available for other software (like the Scarlet.Crush DualShock driver)
|
|
public int FirstController
|
|
{
|
|
get { return firstController; }
|
|
set { firstController = value > 0 ? value : 1; }
|
|
}
|
|
|
|
protected Int32 Scale(Int32 Value, Boolean Flip)
|
|
{
|
|
Value -= 0x80;
|
|
|
|
if (Value == -128) Value = -127;
|
|
if (Flip) Value *= -1;
|
|
|
|
return (Int32)((float)Value * 258.00787401574803149606299212599f);
|
|
}
|
|
|
|
|
|
public X360Device()
|
|
: base(DS3_BUS_CLASS_GUID)
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
public X360Device(IContainer container)
|
|
: base(DS3_BUS_CLASS_GUID)
|
|
{
|
|
container.Add(this);
|
|
|
|
InitializeComponent();
|
|
}
|
|
|
|
|
|
/* public override Boolean Open(int Instance = 0)
|
|
{
|
|
if (base.Open(Instance))
|
|
{
|
|
}
|
|
|
|
return true;
|
|
} */
|
|
|
|
public override Boolean Open(String DevicePath)
|
|
{
|
|
m_Path = DevicePath;
|
|
m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE;
|
|
|
|
if (GetDeviceHandle(m_Path))
|
|
{
|
|
m_IsActive = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override Boolean Start()
|
|
{
|
|
if (IsActive)
|
|
{
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override Boolean Stop()
|
|
{
|
|
if (IsActive)
|
|
{
|
|
//Unplug(0);
|
|
}
|
|
|
|
return base.Stop();
|
|
}
|
|
|
|
public override Boolean Close()
|
|
{
|
|
if (IsActive)
|
|
{
|
|
Unplug(0);
|
|
}
|
|
|
|
return base.Close();
|
|
}
|
|
|
|
|
|
public void Parse(DS4State state, Byte[] Output, int device)
|
|
{
|
|
Output[0] = 0x1C;
|
|
Output[4] = (Byte)(device + firstController);
|
|
Output[9] = 0x14;
|
|
|
|
for (int i = 10; i < Output.Length; i++)
|
|
{
|
|
Output[i] = 0;
|
|
}
|
|
if (state.Share) Output[10] |= (Byte)(1 << 5); // Back
|
|
if (state.L3) Output[10] |= (Byte)(1 << 6); // Left Thumb
|
|
if (state.R3) Output[10] |= (Byte)(1 << 7); // Right Thumb
|
|
if (state.Options) Output[10] |= (Byte)(1 << 4); // Start
|
|
|
|
if (state.DpadUp) Output[10] |= (Byte)(1 << 0); // Up
|
|
if (state.DpadRight) Output[10] |= (Byte)(1 << 3); // Down
|
|
if (state.DpadDown) Output[10] |= (Byte)(1 << 1); // Right
|
|
if (state.DpadLeft) Output[10] |= (Byte)(1 << 2); // Left
|
|
|
|
if (state.L1) Output[11] |= (Byte)(1 << 0); // Left Shoulder
|
|
if (state.R1) Output[11] |= (Byte)(1 << 1); // Right Shoulder
|
|
|
|
if (state.Triangle) Output[11] |= (Byte)(1 << 7); // Y
|
|
if (state.Circle) Output[11] |= (Byte)(1 << 5); // B
|
|
if (state.Cross) Output[11] |= (Byte)(1 << 4); // A
|
|
if (state.Square) Output[11] |= (Byte)(1 << 6); // X
|
|
|
|
if (state.PS) Output[11] |= (Byte)(1 << 2); // Guide
|
|
|
|
Output[12] = state.L2; // Left Trigger
|
|
Output[13] = state.R2; // Right Trigger
|
|
|
|
Int32 ThumbLX = Scale(state.LX, false);
|
|
Int32 ThumbLY = -Scale(state.LY, false);
|
|
Int32 ThumbRX = Scale(state.RX, false);
|
|
Int32 ThumbRY = -Scale(state.RY, false);
|
|
Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX
|
|
Output[15] = (Byte)((ThumbLX >> 8) & 0xFF);
|
|
Output[16] = (Byte)((ThumbLY >> 0) & 0xFF); // LY
|
|
Output[17] = (Byte)((ThumbLY >> 8) & 0xFF);
|
|
Output[18] = (Byte)((ThumbRX >> 0) & 0xFF); // RX
|
|
Output[19] = (Byte)((ThumbRX >> 8) & 0xFF);
|
|
Output[20] = (Byte)((ThumbRY >> 0) & 0xFF); // RY
|
|
Output[21] = (Byte)((ThumbRY >> 8) & 0xFF);
|
|
}
|
|
|
|
public Boolean Plugin(Int32 Serial)
|
|
{
|
|
if (IsActive)
|
|
{
|
|
Int32 Transfered = 0;
|
|
Byte[] Buffer = new Byte[16];
|
|
|
|
Buffer[0] = 0x10;
|
|
Buffer[1] = 0x00;
|
|
Buffer[2] = 0x00;
|
|
Buffer[3] = 0x00;
|
|
|
|
Serial += firstController;
|
|
Buffer[4] = (Byte)((Serial >> 0) & 0xFF);
|
|
Buffer[5] = (Byte)((Serial >> 8) & 0xFF);
|
|
Buffer[6] = (Byte)((Serial >> 16) & 0xFF);
|
|
Buffer[7] = (Byte)((Serial >> 24) & 0xFF);
|
|
|
|
return DeviceIoControl(m_FileHandle, 0x2A4000, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public Boolean Unplug(Int32 Serial)
|
|
{
|
|
if (IsActive)
|
|
{
|
|
Int32 Transfered = 0;
|
|
Byte[] Buffer = new Byte[16];
|
|
|
|
Buffer[0] = 0x10;
|
|
Buffer[1] = 0x00;
|
|
Buffer[2] = 0x00;
|
|
Buffer[3] = 0x00;
|
|
|
|
Serial += firstController;
|
|
Buffer[4] = (Byte)((Serial >> 0) & 0xFF);
|
|
Buffer[5] = (Byte)((Serial >> 8) & 0xFF);
|
|
Buffer[6] = (Byte)((Serial >> 16) & 0xFF);
|
|
Buffer[7] = (Byte)((Serial >> 24) & 0xFF);
|
|
|
|
return DeviceIoControl(m_FileHandle, 0x2A4004, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public Boolean UnplugAll() //not yet implemented, not sure if will
|
|
{
|
|
if (IsActive)
|
|
{
|
|
Int32 Transfered = 0;
|
|
Byte[] Buffer = new Byte[16];
|
|
|
|
Buffer[0] = 0x10;
|
|
Buffer[1] = 0x00;
|
|
Buffer[2] = 0x00;
|
|
Buffer[3] = 0x00;
|
|
|
|
return DeviceIoControl(m_FileHandle, 0x2A4004, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
public Boolean Report(Byte[] Input, Byte[] Output)
|
|
{
|
|
if (IsActive)
|
|
{
|
|
Int32 Transfered = 0;
|
|
|
|
return DeviceIoControl(m_FileHandle, 0x2A400C, Input, Input.Length, Output, Output.Length, ref Transfered, IntPtr.Zero) && Transfered > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|