Fix input delay 2 (#357)

* extract xboxc360ontroller

* extracts DualShock4Controller

* Revert "ensures we get the latest available HID data (#345)"

This reverts commit cd659366b5.

* Revert "fixes cpu busy spinning when there is no hid data available (#356)"

This reverts commit c4f5bbdc56.
This commit is contained in:
Robert Borg 2020-05-20 20:58:40 +02:00 committed by GitHub
parent c4f5bbdc56
commit a8396554e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 675 additions and 278 deletions

View file

@ -131,6 +131,8 @@
<DependentUpon>3rdPartyControllers.cs</DependentUpon>
</Compile>
<Compile Include="Config.cs" />
<Compile Include="Controller\OutputControllerDualShock4.cs" />
<Compile Include="Controller\OutputControllerXbox360.cs" />
<Compile Include="HIDapi.cs" />
<Compile Include="Joycon.cs" />
<Compile Include="MainForm.cs">

View file

@ -0,0 +1,192 @@
using Nefarius.ViGEm.Client.Targets;
using Nefarius.ViGEm.Client.Targets.DualShock4;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.VisualStyles;
using System.Xml.Serialization;
namespace BetterJoyForCemu.Controller
{
public enum DpadDirection
{
None,
Northwest,
West,
Southwest,
South,
Southeast,
East,
Northeast,
North,
}
public struct OutputControllerDualShock4InputState
{
public bool triangle;
public bool circle;
public bool cross;
public bool square;
public bool trigger_left;
public bool trigger_right;
public bool shoulder_left;
public bool shoulder_right;
public bool options;
public bool share;
public bool ps;
public bool touchpad;
public bool thumb_left;
public bool thumb_right;
public DpadDirection dPad;
public byte thumb_left_x;
public byte thumb_left_y;
public byte thumb_right_x;
public byte thumb_right_y;
public byte trigger_left_value;
public byte trigger_right_value;
public bool IsEqual(OutputControllerDualShock4InputState other) {
bool buttons = triangle == other.triangle
&& circle == other.circle
&& cross == other.cross
&& square == other.square
&& trigger_left == other.trigger_left
&& trigger_right == other.trigger_right
&& shoulder_left == other.shoulder_left
&& shoulder_right == other.shoulder_right
&& options == other.options
&& share == other.share
&& ps == other.ps
&& touchpad == other.touchpad
&& thumb_left == other.thumb_left
&& thumb_right == other.thumb_right
&& dPad == other.dPad;
bool axis = thumb_left_x == other.thumb_left_x
&& thumb_left_y == other.thumb_left_y
&& thumb_right_x == other.thumb_right_x
&& thumb_right_y == other.thumb_right_y;
bool triggers = trigger_left_value == other.trigger_left_value
&& trigger_right_value == other.trigger_right_value;
return buttons && axis && triggers;
}
}
public class OutputControllerDualShock4
{
private IDualShock4Controller controller;
private OutputControllerDualShock4InputState current_state;
public delegate void DualShock4FeedbackReceivedEventHandler(DualShock4FeedbackReceivedEventArgs e);
public event DualShock4FeedbackReceivedEventHandler FeedbackReceived;
public OutputControllerDualShock4()
{
controller = Program.emClient.CreateDualShock4Controller();
Init();
}
public OutputControllerDualShock4(ushort vendor_id, ushort product_id)
{
controller = Program.emClient.CreateDualShock4Controller(vendor_id, product_id);
Init();
}
private void Init()
{
controller.AutoSubmitReport = false;
controller.FeedbackReceived += FeedbackReceivedRcv;
}
private void FeedbackReceivedRcv(object _sender, DualShock4FeedbackReceivedEventArgs e)
{
FeedbackReceived(e);
}
public void Connect() {
controller.Connect();
}
public void Disconnect() {
controller.Disconnect();
}
public bool UpdateInput(OutputControllerDualShock4InputState new_state)
{
if(current_state.IsEqual(new_state))
{
return false;
}
DoUpdateInput(new_state);
return true;
}
private void DoUpdateInput(OutputControllerDualShock4InputState new_state)
{
controller.SetButtonState(DualShock4Button.Triangle, new_state.triangle);
controller.SetButtonState(DualShock4Button.Circle, new_state.circle);
controller.SetButtonState(DualShock4Button.Cross, new_state.cross);
controller.SetButtonState(DualShock4Button.Square, new_state.square);
controller.SetButtonState(DualShock4Button.ShoulderLeft, new_state.shoulder_left);
controller.SetButtonState(DualShock4Button.ShoulderRight, new_state.shoulder_right);
controller.SetButtonState(DualShock4Button.TriggerLeft, new_state.trigger_left);
controller.SetButtonState(DualShock4Button.TriggerRight, new_state.trigger_right);
controller.SetButtonState(DualShock4Button.ThumbLeft, new_state.thumb_left);
controller.SetButtonState(DualShock4Button.ThumbRight, new_state.thumb_left);
controller.SetButtonState(DualShock4Button.Share, new_state.share);
controller.SetButtonState(DualShock4Button.Options, new_state.options);
controller.SetButtonState(DualShock4SpecialButton.Ps, new_state.ps);
controller.SetButtonState(DualShock4SpecialButton.Touchpad, new_state.touchpad);
controller.SetDPadDirection(MapDPadDirection(new_state.dPad));
controller.SetAxisValue(DualShock4Axis.LeftThumbX, new_state.thumb_left_x);
controller.SetAxisValue(DualShock4Axis.LeftThumbY, new_state.thumb_left_y);
controller.SetAxisValue(DualShock4Axis.RightThumbX, new_state.thumb_right_x);
controller.SetAxisValue(DualShock4Axis.RightThumbY, new_state.thumb_right_y);
controller.SetSliderValue(DualShock4Slider.LeftTrigger, new_state.trigger_left_value);
controller.SetSliderValue(DualShock4Slider.RightTrigger, new_state.trigger_right_value);
controller.SubmitReport();
current_state = new_state;
}
private DualShock4DPadDirection MapDPadDirection(DpadDirection dPad)
{
switch(dPad)
{
case DpadDirection.None: return DualShock4DPadDirection.None;
case DpadDirection.North: return DualShock4DPadDirection.North;
case DpadDirection.Northeast: return DualShock4DPadDirection.Northeast;
case DpadDirection.East: return DualShock4DPadDirection.East;
case DpadDirection.Southeast: return DualShock4DPadDirection.Southeast;
case DpadDirection.South: return DualShock4DPadDirection.South;
case DpadDirection.Southwest: return DualShock4DPadDirection.Southwest;
case DpadDirection.West: return DualShock4DPadDirection.West;
case DpadDirection.Northwest: return DualShock4DPadDirection.Northwest;
default: throw new NotImplementedException();
}
}
}
}

View file

@ -0,0 +1,163 @@
using Nefarius.ViGEm.Client.Targets;
using Nefarius.ViGEm.Client.Targets.Xbox360;
using System.Web.UI;
namespace BetterJoyForCemu.Controller
{
public struct OutputControllerXbox360InputState
{
// buttons
public bool thumb_stick_left;
public bool thumb_stick_right;
public bool y;
public bool x;
public bool b;
public bool a;
public bool start;
public bool back;
public bool guide;
public bool shoulder_left;
public bool shoulder_right;
// dpad
public bool dpad_up;
public bool dpad_right;
public bool dpad_down;
public bool dpad_left;
// axis
public short axis_left_x;
public short axis_left_y;
public short axis_right_x;
public short axis_right_y;
// triggers
public byte trigger_left;
public byte trigger_right;
public bool IsEqual(OutputControllerXbox360InputState other)
{
bool buttons = thumb_stick_left == other.thumb_stick_left
&& thumb_stick_right == other.thumb_stick_right
&& y == other.y
&& x == other.x
&& b == other.b
&& a == other.a
&& start == other.start
&& back == other.back
&& guide == other.guide
&& shoulder_left == other.shoulder_left
&& shoulder_right == other.shoulder_right;
bool dpad = dpad_up == other.dpad_up
&& dpad_right == other.dpad_right
&& dpad_down == other.dpad_down
&& dpad_left == other.dpad_left;
bool axis = axis_left_x == other.axis_left_x
&& axis_left_y == other.axis_left_y
&& axis_right_x == other.axis_right_x
&& axis_right_y == other.axis_right_y;
bool triggers = trigger_left == other.trigger_left
&& trigger_right == other.trigger_right;
return buttons && dpad && axis && triggers;
}
}
public class OutputControllerXbox360
{
private IXbox360Controller xbox_controller;
private OutputControllerXbox360InputState current_state;
public delegate void Xbox360FeedbackReceivedEventHandler(Xbox360FeedbackReceivedEventArgs e);
public event Xbox360FeedbackReceivedEventHandler FeedbackReceived;
public OutputControllerXbox360()
{
xbox_controller = Program.emClient.CreateXbox360Controller();
Init();
}
public OutputControllerXbox360(ushort vendor_id, ushort product_id)
{
xbox_controller = Program.emClient.CreateXbox360Controller(vendor_id, product_id);
Init();
}
private void Init()
{
xbox_controller.FeedbackReceived += FeedbackReceivedRcv;
xbox_controller.AutoSubmitReport = false;
}
private void FeedbackReceivedRcv(object _sender, Xbox360FeedbackReceivedEventArgs e)
{
FeedbackReceived(e);
}
public bool UpdateInput(OutputControllerXbox360InputState new_state) {
if (current_state.IsEqual(new_state))
{
return false;
}
DoUpdateInput(new_state);
return true;
}
public void Connect()
{
xbox_controller.Connect();
DoUpdateInput(new OutputControllerXbox360InputState());
}
public void Disconnect()
{
xbox_controller.Disconnect();
}
private void DoUpdateInput(OutputControllerXbox360InputState new_state)
{
xbox_controller.SetButtonState(Xbox360Button.LeftThumb, new_state.thumb_stick_left);
xbox_controller.SetButtonState(Xbox360Button.RightThumb, new_state.thumb_stick_right);
xbox_controller.SetButtonState(Xbox360Button.Y, new_state.y);
xbox_controller.SetButtonState(Xbox360Button.X, new_state.x);
xbox_controller.SetButtonState(Xbox360Button.B, new_state.b);
xbox_controller.SetButtonState(Xbox360Button.A, new_state.a);
xbox_controller.SetButtonState(Xbox360Button.Start, new_state.start);
xbox_controller.SetButtonState(Xbox360Button.Back, new_state.back);
xbox_controller.SetButtonState(Xbox360Button.Guide, new_state.guide);
xbox_controller.SetButtonState(Xbox360Button.Up, new_state.dpad_up);
xbox_controller.SetButtonState(Xbox360Button.Right, new_state.dpad_right);
xbox_controller.SetButtonState(Xbox360Button.Down, new_state.dpad_down);
xbox_controller.SetButtonState(Xbox360Button.Left, new_state.dpad_left);
xbox_controller.SetButtonState(Xbox360Button.LeftShoulder, new_state.shoulder_left);
xbox_controller.SetButtonState(Xbox360Button.RightShoulder, new_state.shoulder_right);
xbox_controller.SetAxisValue(Xbox360Axis.LeftThumbX, new_state.axis_left_x);
xbox_controller.SetAxisValue(Xbox360Axis.LeftThumbY, new_state.axis_left_y);
xbox_controller.SetAxisValue(Xbox360Axis.RightThumbX, new_state.axis_right_x);
xbox_controller.SetAxisValue(Xbox360Axis.RightThumbY, new_state.axis_right_y);
xbox_controller.SetSliderValue(Xbox360Slider.LeftTrigger, new_state.trigger_left);
xbox_controller.SetSliderValue(Xbox360Slider.RightTrigger, new_state.trigger_right);
xbox_controller.SubmitReport();
current_state = new_state;
}
}
}

View file

@ -15,6 +15,7 @@ using System.Runtime.InteropServices;
using System.Windows.Forms;
using WindowsInput;
using Nefarius.ViGEm.Client.Targets.DualShock4;
using BetterJoyForCemu.Controller;
namespace BetterJoyForCemu {
public class Joycon {
@ -222,8 +223,8 @@ namespace BetterJoyForCemu {
public ulong Timestamp = 0;
public int packetCounter = 0;
public IXbox360Controller xin;
public IDualShock4Controller ds4;
public OutputControllerXbox360 out_xbox;
public OutputControllerDualShock4 out_ds4;
ushort ds4_ts = 0;
ulong lag;
@ -267,34 +268,31 @@ namespace BetterJoyForCemu {
connection = isUSB ? 0x01 : 0x02;
if (showAsXInput) {
xin = Program.emClient.CreateXbox360Controller();
xin.AutoSubmitReport = false;
if (toRumble)
xin.FeedbackReceived += ReceiveRumble;
out_xbox = new OutputControllerXbox360();
out_xbox.FeedbackReceived += ReceiveRumble;
}
if (showAsDS4) {
ds4 = Program.emClient.CreateDualShock4Controller();
ds4.AutoSubmitReport = false;
out_ds4 = new OutputControllerDualShock4();
if (toRumble)
ds4.FeedbackReceived += Ds4_FeedbackReceived;
out_ds4.FeedbackReceived += Ds4_FeedbackReceived;
}
}
public void getActiveData() {
public void getActiveData()
{
this.activeData = form.activeCaliData(serial_number);
}
public void ReceiveRumble(object sender, Nefarius.ViGEm.Client.Targets.Xbox360.Xbox360FeedbackReceivedEventArgs e) {
public void ReceiveRumble(Xbox360FeedbackReceivedEventArgs e) {
SetRumble(lowFreq, highFreq, (float)(e.LargeMotor + e.SmallMotor) / (float)255, rumblePeriod);
if (other != null && other != this)
other.SetRumble(lowFreq, highFreq, (float)(e.LargeMotor + e.SmallMotor) / (float)255, rumblePeriod);
}
public void Ds4_FeedbackReceived(object sender, DualShock4FeedbackReceivedEventArgs e) {
public void Ds4_FeedbackReceived(DualShock4FeedbackReceivedEventArgs e) {
SetRumble(lowFreq, highFreq, (float)(e.LargeMotor + e.SmallMotor) / (float)255, rumblePeriod);
if (other != null && other != this)
@ -472,12 +470,12 @@ namespace BetterJoyForCemu {
public void Detach(bool close = false) {
stop_polling = true;
if (xin != null) {
xin.Disconnect();
if (out_xbox != null) {
out_xbox.Disconnect();
}
if (ds4 != null) {
ds4.Disconnect();
if (out_ds4 != null) {
out_ds4.Disconnect();
}
if (state > state_.NO_JOYCONS) {
@ -505,32 +503,8 @@ namespace BetterJoyForCemu {
private int ReceiveRaw() {
if (handle == IntPtr.Zero) return -2;
HIDapi.hid_set_nonblocking(handle, 1);
byte[] raw_buf;
byte[][] buffers = new byte[][] { new byte[report_len], new byte[report_len] };
int ret = HIDapi.hid_read(handle, buffers[0], new UIntPtr(report_len));
if (ret == 0) return ret;
int ret2;
// read data until there is no more to read and discard all but the latest data
while(true)
{
ret2 = HIDapi.hid_read(handle, buffers[1], new UIntPtr(report_len));
if(ret2 == 0)
{
raw_buf = buffers[0];
break;
}
ret = HIDapi.hid_read(handle, buffers[1], new UIntPtr(report_len));
if(ret == 0)
{
ret = ret2;
raw_buf = buffers[1];
break;
}
}
byte[] raw_buf = new byte[report_len];
int ret = HIDapi.hid_read_timeout(handle, raw_buf, new UIntPtr(report_len), 5000);
if (ret > 0) {
// Process packets as soon as they come
for (int n = 0; n < 3; n++) {
@ -555,22 +529,19 @@ namespace BetterJoyForCemu {
if (Program.server != null)
Program.server.NewReportIncoming(this);
SetDS4ReportState(n);
if (ds4 != null) {
if (out_ds4 != null) {
try {
ds4.SubmitReport();
out_ds4.UpdateInput(MapToDualShock4Input(this));
} catch (Exception e) {
// ignore /shrug
}
}
}
SetXInputReportState();
// no reason to send XInput reports so often
if (xin != null) {
if (out_xbox != null) {
try {
xin.SubmitReport();
out_xbox.UpdateInput(MapToXbox360Input(this));
} catch (Exception e) {
// ignore /shrug
}
@ -775,7 +746,6 @@ namespace BetterJoyForCemu {
} else if (a == 0) {
// The non-blocking read timed out. No need to sleep.
// No need to increase attempts because it's not an error.
Thread.Sleep((Int32)5);
}
}
}
@ -907,201 +877,6 @@ namespace BetterJoyForCemu {
return 0;
}
private void SetXInputReportState() {
if (xin == null)
return;
if (isPro) {
xin.SetButtonState(Xbox360Button.A, buttons[(int)(!swapAB ? Button.B : Button.A)]);
xin.SetButtonState(Xbox360Button.B, buttons[(int)(!swapAB ? Button.A : Button.B)]);
xin.SetButtonState(Xbox360Button.Y, buttons[(int)(!swapXY ? Button.X : Button.Y)]);
xin.SetButtonState(Xbox360Button.X, buttons[(int)(!swapXY ? Button.Y : Button.X)]);
xin.SetButtonState(Xbox360Button.Up, buttons[(int)Button.DPAD_UP]);
xin.SetButtonState(Xbox360Button.Down, buttons[(int)Button.DPAD_DOWN]);
xin.SetButtonState(Xbox360Button.Left, buttons[(int)Button.DPAD_LEFT]);
xin.SetButtonState(Xbox360Button.Right, buttons[(int)Button.DPAD_RIGHT]);
xin.SetButtonState(Xbox360Button.Back, buttons[(int)Button.MINUS]);
xin.SetButtonState(Xbox360Button.Start, buttons[(int)Button.PLUS]);
xin.SetButtonState(Xbox360Button.Guide, buttons[(int)Button.HOME]);
xin.SetButtonState(Xbox360Button.LeftShoulder, buttons[(int)Button.SHOULDER_1]);
xin.SetButtonState(Xbox360Button.RightShoulder, buttons[(int)Button.SHOULDER2_1]);
xin.SetButtonState(Xbox360Button.LeftThumb, buttons[(int)Button.STICK]);
xin.SetButtonState(Xbox360Button.RightThumb, buttons[(int)Button.STICK2]);
} else {
if (other != null) { // no need for && other != this
xin.SetButtonState(!swapAB ? Xbox360Button.A : Xbox360Button.B, buttons[(int)(isLeft ? Button.B : Button.DPAD_DOWN)]);
xin.SetButtonState(!swapAB ? Xbox360Button.B : Xbox360Button.A, buttons[(int)(isLeft ? Button.A : Button.DPAD_RIGHT)]);
xin.SetButtonState(!swapXY ? Xbox360Button.Y : Xbox360Button.X, buttons[(int)(isLeft ? Button.X : Button.DPAD_UP)]);
xin.SetButtonState(!swapXY ? Xbox360Button.X : Xbox360Button.Y, buttons[(int)(isLeft ? Button.Y : Button.DPAD_LEFT)]);
xin.SetButtonState(Xbox360Button.Up, buttons[(int)(isLeft ? Button.DPAD_UP : Button.X)]);
xin.SetButtonState(Xbox360Button.Down, buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.B)]);
xin.SetButtonState(Xbox360Button.Left, buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)]);
xin.SetButtonState(Xbox360Button.Right, buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)]);
xin.SetButtonState(Xbox360Button.Back, buttons[(int)Button.MINUS]);
xin.SetButtonState(Xbox360Button.Start, buttons[(int)Button.PLUS]);
xin.SetButtonState(Xbox360Button.Guide, buttons[(int)Button.HOME]);
xin.SetButtonState(Xbox360Button.LeftShoulder, buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER2_1)]);
xin.SetButtonState(Xbox360Button.RightShoulder, buttons[(int)(isLeft ? Button.SHOULDER2_1 : Button.SHOULDER_1)]);
xin.SetButtonState(Xbox360Button.LeftThumb, buttons[(int)(isLeft ? Button.STICK : Button.STICK2)]);
xin.SetButtonState(Xbox360Button.RightThumb, buttons[(int)(isLeft ? Button.STICK2 : Button.STICK)]);
} else { // single joycon mode
xin.SetButtonState(!swapAB ? Xbox360Button.A : Xbox360Button.B, buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.DPAD_RIGHT)]);
xin.SetButtonState(!swapAB ? Xbox360Button.B : Xbox360Button.A, buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.DPAD_UP)]);
xin.SetButtonState(!swapXY ? Xbox360Button.Y : Xbox360Button.X, buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.DPAD_LEFT)]);
xin.SetButtonState(!swapXY ? Xbox360Button.X : Xbox360Button.Y, buttons[(int)(isLeft ? Button.DPAD_UP : Button.DPAD_DOWN)]);
xin.SetButtonState(Xbox360Button.Back, buttons[(int)Button.MINUS] | buttons[(int)Button.HOME]);
xin.SetButtonState(Xbox360Button.Start, buttons[(int)Button.PLUS] | buttons[(int)Button.CAPTURE]);
xin.SetButtonState(Xbox360Button.LeftShoulder, buttons[(int)Button.SL]);
xin.SetButtonState(Xbox360Button.RightShoulder, buttons[(int)Button.SR]);
xin.SetButtonState(Xbox360Button.LeftThumb, buttons[(int)Button.STICK]);
}
}
// overwrite guide button if it's custom-mapped
if (Config.Value("home") != "0")
xin.SetButtonState(Xbox360Button.Guide, false);
if (!isSnes) {
if (other != null || isPro) { // no need for && other != this
xin.SetAxisValue(Xbox360Axis.LeftThumbX, CastStickValue((other == this && !isLeft) ? stick2[0] : stick[0]));
xin.SetAxisValue(Xbox360Axis.LeftThumbY, CastStickValue((other == this && !isLeft) ? stick2[1] : stick[1]));
xin.SetAxisValue(Xbox360Axis.RightThumbX, CastStickValue((other == this && !isLeft) ? stick[0] : stick2[0]));
xin.SetAxisValue(Xbox360Axis.RightThumbY, CastStickValue((other == this && !isLeft) ? stick[1] : stick2[1]));
} else { // single joycon mode
xin.SetAxisValue(Xbox360Axis.LeftThumbY, CastStickValue((isLeft ? 1 : -1) * stick[0]));
xin.SetAxisValue(Xbox360Axis.LeftThumbX, CastStickValue((isLeft ? -1 : 1) * stick[1]));
}
}
if (other != null || isPro) {
byte lval = GyroAnalogSliders ? sliderVal[0] : Byte.MaxValue;
byte rval = GyroAnalogSliders ? sliderVal[1] : Byte.MaxValue;
xin.SetSliderValue(Xbox360Slider.LeftTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER2_2)] ? lval : 0));
xin.SetSliderValue(Xbox360Slider.RightTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER2_2 : Button.SHOULDER_2)] ? rval : 0));
} else {
xin.SetSliderValue(Xbox360Slider.LeftTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER_1)] ? Byte.MaxValue : 0));
xin.SetSliderValue(Xbox360Slider.RightTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER_2)] ? Byte.MaxValue : 0));
}
}
private void SetDS4ReportState(int n) {
if (ds4 == null)
return;
if (isPro) {
ds4.SetButtonState(DualShock4Button.Cross, buttons[(int)(!swapAB ? Button.B : Button.A)]);
ds4.SetButtonState(DualShock4Button.Circle, buttons[(int)(!swapAB ? Button.A : Button.B)]);
ds4.SetButtonState(DualShock4Button.Triangle, buttons[(int)(!swapXY ? Button.X : Button.Y)]);
ds4.SetButtonState(DualShock4Button.Square, buttons[(int)(!swapXY ? Button.Y : Button.X)]);
ds4.SetDPadDirection(DualShock4DPadDirection.None);
if (buttons[(int)Button.DPAD_LEFT])
ds4.SetDPadDirection(DualShock4DPadDirection.West);
if (buttons[(int)Button.DPAD_RIGHT])
ds4.SetDPadDirection(DualShock4DPadDirection.East);
if (buttons[(int)Button.DPAD_UP]) {
if (buttons[(int)Button.DPAD_LEFT])
ds4.SetDPadDirection(DualShock4DPadDirection.Northwest);
else if (buttons[(int)Button.DPAD_RIGHT])
ds4.SetDPadDirection(DualShock4DPadDirection.Northeast);
else
ds4.SetDPadDirection(DualShock4DPadDirection.North);
}
if (buttons[(int)Button.DPAD_DOWN]) {
if (buttons[(int)Button.DPAD_LEFT])
ds4.SetDPadDirection(DualShock4DPadDirection.Southwest);
else if (buttons[(int)Button.DPAD_RIGHT])
ds4.SetDPadDirection(DualShock4DPadDirection.Southeast);
else
ds4.SetDPadDirection(DualShock4DPadDirection.South);
}
ds4.SetButtonState(DualShock4Button.Share, buttons[(int)Button.MINUS]);
ds4.SetButtonState(DualShock4Button.Options, buttons[(int)Button.PLUS]);
ds4.SetButtonState(DualShock4SpecialButton.Ps, buttons[(int)Button.HOME]);
ds4.SetButtonState(DualShock4SpecialButton.Touchpad, buttons[(int)Button.CAPTURE]);
ds4.SetButtonState(DualShock4Button.ShoulderLeft, buttons[(int)Button.SHOULDER_1]);
ds4.SetButtonState(DualShock4Button.ShoulderRight, buttons[(int)Button.SHOULDER2_1]);
ds4.SetButtonState(DualShock4Button.ThumbLeft, buttons[(int)Button.STICK]);
ds4.SetButtonState(DualShock4Button.ThumbRight, buttons[(int)Button.STICK2]);
} else {
if (other != null) { // no need for && other != this
ds4.SetButtonState(!swapAB ? DualShock4Button.Cross : DualShock4Button.Circle, buttons[(int)(isLeft ? Button.B : Button.DPAD_DOWN)]);
ds4.SetButtonState(!swapAB ? DualShock4Button.Circle : DualShock4Button.Cross, buttons[(int)(isLeft ? Button.A : Button.DPAD_RIGHT)]);
ds4.SetButtonState(!swapXY ? DualShock4Button.Triangle : DualShock4Button.Square, buttons[(int)(isLeft ? Button.X : Button.DPAD_UP)]);
ds4.SetButtonState(!swapXY ? DualShock4Button.Square : DualShock4Button.Triangle, buttons[(int)(isLeft ? Button.Y : Button.DPAD_LEFT)]);
ds4.SetDPadDirection(DualShock4DPadDirection.None);
if (buttons[(int)(isLeft ? Button.DPAD_UP : Button.X)])
if (buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)])
ds4.SetDPadDirection(DualShock4DPadDirection.Northwest);
else if (buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)])
ds4.SetDPadDirection(DualShock4DPadDirection.Northeast);
else
ds4.SetDPadDirection(DualShock4DPadDirection.North);
if (buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.B)])
if (buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)])
ds4.SetDPadDirection(DualShock4DPadDirection.Southwest);
else if (buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)])
ds4.SetDPadDirection(DualShock4DPadDirection.Southeast);
else
ds4.SetDPadDirection(DualShock4DPadDirection.South);
if (buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)])
ds4.SetDPadDirection(DualShock4DPadDirection.West);
if (buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)])
ds4.SetDPadDirection(DualShock4DPadDirection.East);
ds4.SetButtonState(DualShock4Button.Share, buttons[(int)Button.MINUS]);
ds4.SetButtonState(DualShock4Button.Options, buttons[(int)Button.PLUS]);
ds4.SetButtonState(DualShock4SpecialButton.Ps, buttons[(int)Button.HOME]);
ds4.SetButtonState(DualShock4SpecialButton.Touchpad, buttons[(int)Button.CAPTURE]);
ds4.SetButtonState(DualShock4Button.ShoulderLeft, buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER2_1)]);
ds4.SetButtonState(DualShock4Button.ShoulderRight, buttons[(int)(isLeft ? Button.SHOULDER2_1 : Button.SHOULDER_1)]);
ds4.SetButtonState(DualShock4Button.ThumbLeft, buttons[(int)(isLeft ? Button.STICK : Button.STICK2)]);
ds4.SetButtonState(DualShock4Button.ThumbRight, buttons[(int)(isLeft ? Button.STICK2 : Button.STICK)]);
} else { // single joycon mode
ds4.SetButtonState(!swapAB ? DualShock4Button.Cross : DualShock4Button.Circle, buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.DPAD_RIGHT)]);
ds4.SetButtonState(!swapAB ? DualShock4Button.Circle : DualShock4Button.Cross, buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.DPAD_UP)]);
ds4.SetButtonState(!swapXY ? DualShock4Button.Triangle : DualShock4Button.Square, buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.DPAD_LEFT)]);
ds4.SetButtonState(!swapXY ? DualShock4Button.Square : DualShock4Button.Triangle, buttons[(int)(isLeft ? Button.DPAD_UP : Button.DPAD_DOWN)]);
ds4.SetButtonState(DualShock4Button.Share, buttons[(int)Button.MINUS] | buttons[(int)Button.HOME]);
ds4.SetButtonState(DualShock4Button.Options, buttons[(int)Button.PLUS] | buttons[(int)Button.CAPTURE]);
ds4.SetButtonState(DualShock4Button.ShoulderLeft, buttons[(int)Button.SL]);
ds4.SetButtonState(DualShock4Button.ShoulderRight, buttons[(int)Button.SR]);
ds4.SetButtonState(DualShock4Button.ThumbLeft, buttons[(int)Button.STICK]);
}
}
// overwrite guide button if it's custom-mapped
if (Config.Value("home") != "0")
ds4.SetButtonState(DualShock4SpecialButton.Ps, false);
if (!isSnes) {
if (other != null || isPro) { // no need for && other != this
ds4.SetAxisValue(DualShock4Axis.LeftThumbX, CastStickValueByte((other == this && !isLeft) ? -stick2[0] : -stick[0]));
ds4.SetAxisValue(DualShock4Axis.LeftThumbY, CastStickValueByte((other == this && !isLeft) ? stick2[1] : stick[1]));
ds4.SetAxisValue(DualShock4Axis.RightThumbX, CastStickValueByte((other == this && !isLeft) ? -stick[0] : -stick2[0]));
ds4.SetAxisValue(DualShock4Axis.RightThumbY, CastStickValueByte((other == this && !isLeft) ? stick[1] : stick2[1]));
} else { // single joycon mode
ds4.SetAxisValue(DualShock4Axis.LeftThumbY, CastStickValueByte((isLeft ? 1 : -1) * stick[0]));
ds4.SetAxisValue(DualShock4Axis.LeftThumbX, CastStickValueByte((isLeft ? 1 : -1) * stick[1]));
}
}
if (other != null || isPro) {
byte lval = GyroAnalogSliders ? sliderVal[0] : Byte.MaxValue;
byte rval = GyroAnalogSliders ? sliderVal[1] : Byte.MaxValue;
ds4.SetSliderValue(DualShock4Slider.LeftTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER2_2)] ? lval : 0));
ds4.SetSliderValue(DualShock4Slider.RightTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER2_2 : Button.SHOULDER_2)] ? rval : 0));
} else {
ds4.SetSliderValue(DualShock4Slider.LeftTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER_1)] ? Byte.MaxValue : 0));
ds4.SetSliderValue(DualShock4Slider.RightTrigger, (byte)(buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER_2)] ? Byte.MaxValue : 0));
}
}
// Get Gyro/Accel data
private void ExtractIMUValues(byte[] report_buf, int n = 0) {
@ -1215,11 +990,11 @@ namespace BetterJoyForCemu {
return s;
}
private short CastStickValue(float stick_value) {
private static short CastStickValue(float stick_value) {
return (short)Math.Max(Int16.MinValue, Math.Min(Int16.MaxValue, stick_value * (stick_value > 0 ? Int16.MaxValue : -Int16.MinValue)));
}
private byte CastStickValueByte(float stick_value) {
private static byte CastStickValueByte(float stick_value) {
return (byte)Math.Max(Byte.MinValue, Math.Min(Byte.MaxValue, 127 - stick_value * Byte.MaxValue));
}
@ -1385,5 +1160,271 @@ namespace BetterJoyForCemu {
}
DebugPrint(string.Format(format, tostr), d);
}
private static OutputControllerXbox360InputState MapToXbox360Input(Joycon input)
{
var output = new OutputControllerXbox360InputState();
var swapAB = input.swapAB;
var swapXY = input.swapXY;
var isPro = input.isPro;
var isLeft = input.isLeft;
var isSnes = input.isSnes;
var other = input.other;
var GyroAnalogSliders = input.GyroAnalogSliders;
var buttons = input.buttons;
var stick = input.stick;
var stick2 = input.stick2;
var sliderVal = input.sliderVal;
if (isPro)
{
output.a = buttons[(int)(!swapAB ? Button.B : Button.A)];
output.b = buttons[(int)(!swapAB ? Button.A : Button.B)];
output.y = buttons[(int)(!swapXY ? Button.X : Button.Y)];
output.x = buttons[(int)(!swapXY ? Button.Y : Button.X)];
output.dpad_up = buttons[(int)Button.DPAD_UP];
output.dpad_down = buttons[(int)Button.DPAD_DOWN];
output.dpad_left = buttons[(int)Button.DPAD_LEFT];
output.dpad_right = buttons[(int)Button.DPAD_RIGHT];
output.back = buttons[(int)Button.MINUS];
output.start = buttons[(int)Button.PLUS];
output.guide = buttons[(int)Button.HOME];
output.shoulder_left = buttons[(int)Button.SHOULDER_1];
output.shoulder_right = buttons[(int)Button.SHOULDER2_1];
output.thumb_stick_left = buttons[(int)Button.STICK];
output.thumb_stick_right = buttons[(int)Button.STICK2];
}
else
{
if (other != null)
{ // no need for && other != this
output.a = buttons[(int)(!swapAB ? isLeft ? Button.B : Button.DPAD_DOWN : isLeft ? Button.A : Button.DPAD_RIGHT)];
output.b = buttons[(int)(swapAB ? isLeft ? Button.B : Button.DPAD_DOWN : isLeft ? Button.A : Button.DPAD_RIGHT)];
output.y = buttons[(int)(!swapXY ? isLeft ? Button.X : Button.DPAD_UP : isLeft ? Button.Y : Button.DPAD_LEFT)];
output.x = buttons[(int)(swapXY ? isLeft ? Button.X : Button.DPAD_UP : isLeft ? Button.Y : Button.DPAD_LEFT)];
output.dpad_up = buttons[(int)(isLeft ? Button.DPAD_UP : Button.X)];
output.dpad_down = buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.B)];
output.dpad_left = buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)];
output.dpad_right = buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)];
output.back = buttons[(int)Button.MINUS];
output.start = buttons[(int)Button.PLUS];
output.guide = buttons[(int)Button.HOME];
output.shoulder_left = buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER2_1)];
output.shoulder_right = buttons[(int)(isLeft ? Button.SHOULDER2_1 : Button.SHOULDER_1)];
output.thumb_stick_left = buttons[(int)(isLeft ? Button.STICK : Button.STICK2)];
output.thumb_stick_right = buttons[(int)(isLeft ? Button.STICK2 : Button.STICK)];
}
else
{ // single joycon mode
output.a = buttons[(int)(!swapAB ? isLeft ? Button.DPAD_LEFT : Button.DPAD_RIGHT : isLeft ? Button.DPAD_DOWN : Button.DPAD_UP)];
output.b = buttons[(int)(swapAB ? isLeft ? Button.DPAD_LEFT : Button.DPAD_RIGHT : isLeft ? Button.DPAD_DOWN : Button.DPAD_UP)];
output.y = buttons[(int)(!swapXY ? isLeft ? Button.DPAD_RIGHT : Button.DPAD_LEFT : isLeft ? Button.DPAD_UP : Button.DPAD_DOWN)];
output.x = buttons[(int)(swapXY ? isLeft ? Button.DPAD_RIGHT : Button.DPAD_LEFT : isLeft ? Button.DPAD_UP : Button.DPAD_DOWN)];
output.back = buttons[(int)Button.MINUS] | buttons[(int)Button.HOME];
output.start = buttons[(int)Button.PLUS] | buttons[(int)Button.CAPTURE];
output.shoulder_left = buttons[(int)Button.SL];
output.shoulder_right = buttons[(int)Button.SR];
output.thumb_stick_left = buttons[(int)Button.STICK];
}
}
// overwrite guide button if it's custom-mapped
if (Config.Value("home") != "0")
output.guide = false;
if (!isSnes)
{
if (other != null || isPro)
{ // no need for && other != this
output.axis_left_x = CastStickValue((other == input && !isLeft) ? stick2[0] : stick[0]);
output.axis_left_y = CastStickValue((other == input && !isLeft) ? stick2[1] : stick[1]);
output.axis_right_x = CastStickValue((other == input && !isLeft) ? stick[0] : stick2[0]);
output.axis_right_y = CastStickValue((other == input && !isLeft) ? stick[1] : stick2[1]);
}
else
{ // single joycon mode
output.axis_left_x = CastStickValue((isLeft ? 1 : -1) * stick[0]);
output.axis_left_y = CastStickValue((isLeft ? -1 : 1) * stick[1]);
}
}
if (other != null || isPro)
{
byte lval = GyroAnalogSliders ? sliderVal[0] : Byte.MaxValue;
byte rval = GyroAnalogSliders ? sliderVal[1] : Byte.MaxValue;
output.trigger_left = (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER2_2)] ? lval : 0);
output.trigger_right = (byte)(buttons[(int)(isLeft ? Button.SHOULDER2_2 : Button.SHOULDER_2)] ? rval : 0);
}
else
{
output.trigger_left = (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER_1)] ? Byte.MaxValue : 0);
output.trigger_right = (byte)(buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER_2)] ? Byte.MaxValue : 0);
}
return output;
}
private static OutputControllerDualShock4InputState MapToDualShock4Input(Joycon input)
{
var output = new OutputControllerDualShock4InputState();
var swapAB = input.swapAB;
var swapXY = input.swapXY;
var isPro = input.isPro;
var isLeft = input.isLeft;
var isSnes = input.isSnes;
var other = input.other;
var GyroAnalogSliders = input.GyroAnalogSliders;
var buttons = input.buttons;
var stick = input.stick;
var stick2 = input.stick2;
var sliderVal = input.sliderVal;
if (isPro)
{
output.cross = buttons[(int)(!swapAB ? Button.B : Button.A)];
output.circle = buttons[(int)(!swapAB ? Button.A : Button.B)];
output.triangle = buttons[(int)(!swapXY ? Button.X : Button.Y)];
output.square = buttons[(int)(!swapXY ? Button.Y : Button.X)];
if (buttons[(int)Button.DPAD_UP])
{
if (buttons[(int)Button.DPAD_LEFT])
output.dPad = DpadDirection.Northwest;
else if (buttons[(int)Button.DPAD_RIGHT])
output.dPad = DpadDirection.Northeast;
else
output.dPad = DpadDirection.North;
}
else if (buttons[(int)Button.DPAD_DOWN])
{
if (buttons[(int)Button.DPAD_LEFT])
output.dPad = DpadDirection.Southwest;
else if (buttons[(int)Button.DPAD_RIGHT])
output.dPad = DpadDirection.Southeast;
else
output.dPad = DpadDirection.South;
}
else if (buttons[(int)Button.DPAD_LEFT])
output.dPad = DpadDirection.West;
else if (buttons[(int)Button.DPAD_RIGHT])
output.dPad = DpadDirection.East;
output.share = buttons[(int)Button.MINUS];
output.options = buttons[(int)Button.PLUS];
output.ps = buttons[(int)Button.HOME];
output.touchpad = buttons[(int)Button.CAPTURE];
output.shoulder_left = buttons[(int)Button.SHOULDER_1];
output.shoulder_right = buttons[(int)Button.SHOULDER2_1];
output.thumb_left = buttons[(int)Button.STICK];
output.thumb_right = buttons[(int)Button.STICK2];
}
else
{
if (other != null)
{ // no need for && other != this
output.circle = !swapAB ? buttons[(int)(isLeft ? Button.B : Button.DPAD_DOWN)] : buttons[(int)(isLeft ? Button.A : Button.DPAD_RIGHT)];
output.cross = swapAB ? buttons[(int)(isLeft ? Button.B : Button.DPAD_DOWN)] : buttons[(int)(isLeft ? Button.A : Button.DPAD_RIGHT)];
output.triangle = !swapXY ? buttons[(int)(isLeft ? Button.X : Button.DPAD_UP)] : buttons[(int)(isLeft ? Button.Y : Button.DPAD_LEFT)];
output.triangle = swapXY ? buttons[(int)(isLeft ? Button.X : Button.DPAD_UP)] : buttons[(int)(isLeft ? Button.Y : Button.DPAD_LEFT)];
if (buttons[(int)(isLeft ? Button.DPAD_UP : Button.X)])
if (buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)])
output.dPad = DpadDirection.Northwest;
else if (buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)])
output.dPad = DpadDirection.Northeast;
else
output.dPad = DpadDirection.North;
else if (buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.B)])
if (buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)])
output.dPad = DpadDirection.Southwest;
else if (buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)])
output.dPad = DpadDirection.Southeast;
else
output.dPad = DpadDirection.South;
else if (buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.Y)])
output.dPad = DpadDirection.West;
else if (buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.A)])
output.dPad = DpadDirection.East;
output.share = buttons[(int)Button.MINUS];
output.options = buttons[(int)Button.PLUS];
output.ps = buttons[(int)Button.HOME];
output.touchpad = buttons[(int)Button.CAPTURE];
output.shoulder_left = buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER2_1)];
output.shoulder_right = buttons[(int)(isLeft ? Button.SHOULDER2_1 : Button.SHOULDER_1)];
output.thumb_left = buttons[(int)(isLeft ? Button.STICK : Button.STICK2)];
output.thumb_right = buttons[(int)(isLeft ? Button.STICK2 : Button.STICK)];
}
else
{ // single joycon mode
output.cross = !swapAB ? buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.DPAD_RIGHT)] : buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.DPAD_UP)];
output.circle = swapAB ? buttons[(int)(isLeft ? Button.DPAD_LEFT : Button.DPAD_RIGHT)] : buttons[(int)(isLeft ? Button.DPAD_DOWN : Button.DPAD_UP)];
output.triangle = !swapXY ? buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.DPAD_LEFT)] : buttons[(int)(isLeft ? Button.DPAD_UP : Button.DPAD_DOWN)];
output.square = swapXY ? buttons[(int)(isLeft ? Button.DPAD_RIGHT : Button.DPAD_LEFT)] : buttons[(int)(isLeft ? Button.DPAD_UP : Button.DPAD_DOWN)];
output.square = buttons[(int)Button.MINUS] | buttons[(int)Button.HOME];
output.options = buttons[(int)Button.PLUS] | buttons[(int)Button.CAPTURE];
output.shoulder_left = buttons[(int)Button.SL];
output.shoulder_right = buttons[(int)Button.SR];
output.thumb_left = buttons[(int)Button.STICK];
}
}
// overwrite guide button if it's custom-mapped
if (Config.Value("home") != "0")
output.ps = false;
if (!isSnes)
{
if (other != null || isPro)
{ // no need for && other != this
output.thumb_left_x = CastStickValueByte((other == input && !isLeft) ? -stick2[0] : -stick[0]);
output.thumb_left_y = CastStickValueByte((other == input && !isLeft) ? stick2[1] : stick[1]);
output.thumb_right_x = CastStickValueByte((other == input && !isLeft) ? -stick[0] : -stick2[0]);
output.thumb_right_y = CastStickValueByte((other == input && !isLeft) ? stick[1] : stick2[1]);
}
else
{ // single joycon mode
output.thumb_left_x = CastStickValueByte((isLeft ? 1 : -1) * stick[0]);
output.thumb_left_y = CastStickValueByte((isLeft ? 1 : -1) * stick[1]);
}
}
if (other != null || isPro)
{
byte lval = GyroAnalogSliders ? sliderVal[0] : Byte.MaxValue;
byte rval = GyroAnalogSliders ? sliderVal[1] : Byte.MaxValue;
output.trigger_left_value = (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER2_2)] ? lval : 0);
output.trigger_right_value = (byte)(buttons[(int)(isLeft ? Button.SHOULDER2_2 : Button.SHOULDER_2)] ? rval : 0);
}
else
{
output.trigger_left_value = (byte)(buttons[(int)(isLeft ? Button.SHOULDER_2 : Button.SHOULDER_1)] ? Byte.MaxValue : 0);
output.trigger_right_value = (byte)(buttons[(int)(isLeft ? Button.SHOULDER_1 : Button.SHOULDER_2)] ? Byte.MaxValue : 0);
}
return output;
}
}
}

View file

@ -178,14 +178,14 @@ namespace BetterJoyForCemu {
jc.SetPlayerLED(led);
v.SetPlayerLED(led);
if (v.xin != null) {
v.xin.Disconnect();
v.xin = null;
if (v.out_xbox != null) {
v.out_xbox.Disconnect();
v.out_xbox = null;
}
if (v.ds4 != null) {
v.ds4.Disconnect();
v.ds4 = null;
if (v.out_ds4 != null) {
v.out_ds4.Disconnect();
v.out_ds4 = null;
}
// setting the other joycon's button image
@ -262,21 +262,20 @@ namespace BetterJoyForCemu {
}
void ReenableViGEm(Joycon v) {
if (showAsXInput && v.xin == null) {
v.xin = Program.emClient.CreateXbox360Controller();
if (showAsXInput && v.out_xbox == null) {
v.out_xbox = new Controller.OutputControllerXbox360();
if (toRumble)
v.xin.FeedbackReceived += v.ReceiveRumble;
v.xin.Connect();
v.out_xbox.FeedbackReceived += v.ReceiveRumble;
v.out_xbox.Connect();
}
if (showAsDS4 && v.ds4 == null) {
v.ds4 = Program.emClient.CreateDualShock4Controller();
v.ds4.AutoSubmitReport = false;
if (showAsDS4 && v.out_ds4 == null) {
v.out_ds4 = new Controller.OutputControllerDualShock4();
if (toRumble)
v.ds4.FeedbackReceived += v.Ds4_FeedbackReceived;
v.ds4.Connect();
v.out_ds4.FeedbackReceived += v.Ds4_FeedbackReceived;
v.out_ds4.Connect();
}
}

View file

@ -239,22 +239,22 @@ namespace BetterJoyForCemu {
temp.SetPlayerLED(led);
v.SetPlayerLED(led);
if (temp.xin != null) {
if (temp.out_xbox != null) {
try {
temp.xin.Disconnect();
temp.out_xbox.Disconnect();
} catch (Exception e) {
// it wasn't connected in the first place, go figure
}
}
if (temp.ds4 != null) {
if (temp.out_ds4 != null) {
try {
temp.ds4.Disconnect();
temp.out_ds4.Disconnect();
} catch (Exception e) {
// it wasn't connected in the first place, go figure
}
}
temp.xin = null;
temp.ds4 = null;
temp.out_xbox = null;
temp.out_ds4 = null;
foreach (Button b in form.con)
if (b.Tag == v || b.Tag == temp) {
@ -272,10 +272,10 @@ namespace BetterJoyForCemu {
foreach (Joycon jc in j) { // Connect device straight away
if (jc.state == Joycon.state_.NOT_ATTACHED) {
if (jc.xin != null)
jc.xin.Connect();
if (jc.ds4 != null)
jc.ds4.Connect();
if (jc.out_xbox != null)
jc.out_xbox.Connect();
if (jc.out_ds4 != null)
jc.out_ds4.Connect();
jc.Attach(leds_: jc.LED);
@ -305,12 +305,12 @@ namespace BetterJoyForCemu {
else
v.Detach();
if (v.xin != null) {
v.xin.Disconnect();
if (v.out_xbox != null) {
v.out_xbox.Disconnect();
}
if (v.ds4 != null) {
v.ds4.Disconnect();
if (v.out_ds4 != null) {
v.out_ds4.Disconnect();
}
}