Formatting clean-up and calibration addition cleanup.
This commit is contained in:
parent
fa926f479f
commit
a12518886c
7 changed files with 1215 additions and 1259 deletions
|
@ -44,8 +44,9 @@
|
|||
<!-- Should prevent any more issues of the controller being unusable after the program (even though this can be fixed if you read the README) -->
|
||||
<!-- Default: true -->
|
||||
<add key="PurgeAffectedDevices" value="true" />
|
||||
<!-- Determines whether or not the program will use mannually calibrate gyro data for non-original controller. -->
|
||||
<!-- When "true", click "Calibrate" button once to get gyro calibrate data.-->
|
||||
<!-- Determines whether or not to enable (experimental - currently default controller to pro) support for 3rd-party controllers. Adds a "Calibrate" button. -->
|
||||
<!-- When "true", click "Calibrate" button once to get gyro calibrate data .-->
|
||||
<!-- When enabled, can only calibrate one controller at a time. -->
|
||||
<!-- Default: false -->
|
||||
<add key="NonOriginalController" value="false" />
|
||||
</appSettings>
|
||||
|
|
|
@ -6,85 +6,89 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterJoyForCemu {
|
||||
public static class Config { // stores dynamic configuration, including
|
||||
const string PATH = "settings";
|
||||
static Dictionary<string, bool> variables = new Dictionary<string, bool>();
|
||||
public static class Config { // stores dynamic configuration, including
|
||||
const string PATH = "settings";
|
||||
static Dictionary<string, bool> variables = new Dictionary<string, bool>();
|
||||
|
||||
public static void Init(List<KeyValuePair<string, float[]>> caliData) {
|
||||
variables["ProgressiveScan"] = true;
|
||||
variables["StartInTray"] = false;
|
||||
const int settingsNum = 2; // currently - ProgressiveScan, StartInTray
|
||||
|
||||
if (File.Exists(PATH)) {
|
||||
using (StreamReader file = new StreamReader(PATH)) {
|
||||
string line = String.Empty;
|
||||
int lineNO = 0;
|
||||
while ((line = file.ReadLine()) != null) {
|
||||
string[] vs = line.Split();
|
||||
try {
|
||||
if (lineNO < 2){
|
||||
variables[vs[0]] = Boolean.Parse(vs[1]);
|
||||
} else {
|
||||
caliData.Clear();
|
||||
for (int i = 0; i < vs.Length; i++){
|
||||
string[] caliArr = vs[i].Split(',');
|
||||
float[] newArr = new float[6];
|
||||
for (int j = 1; j < caliArr.Length; j++){
|
||||
newArr[j-1] = float.Parse(caliArr[j]);
|
||||
}
|
||||
caliData.Add(new KeyValuePair<string, float[]>(
|
||||
caliArr[0],
|
||||
newArr
|
||||
));
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
lineNO++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
using (StreamWriter file = new StreamWriter(PATH)) {
|
||||
foreach (string k in variables.Keys)
|
||||
file.WriteLine(String.Format("{0} {1}", k, variables[k]));
|
||||
string caliStr = "";
|
||||
for(int i = 0; i < caliData.Count; i++){
|
||||
string space = " ";
|
||||
if (i == 0) space = "";
|
||||
caliStr += space + caliData[i].Key + "," + String.Join(",", caliData[i].Value);
|
||||
}
|
||||
file.WriteLine(caliStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void Init(List<KeyValuePair<string, float[]>> caliData) {
|
||||
variables["ProgressiveScan"] = true;
|
||||
variables["StartInTray"] = false;
|
||||
|
||||
public static bool Value(string key) {
|
||||
if (!variables.ContainsKey("ProgressiveScan") && !variables.ContainsKey("StartInTray")) {
|
||||
return false;
|
||||
}
|
||||
return variables[key];
|
||||
}
|
||||
if (File.Exists(PATH)) {
|
||||
using (StreamReader file = new StreamReader(PATH)) {
|
||||
string line = String.Empty;
|
||||
int lineNO = 0;
|
||||
while ((line = file.ReadLine()) != null) {
|
||||
string[] vs = line.Split();
|
||||
try {
|
||||
if (lineNO < settingsNum) { // load in basic settings
|
||||
variables[vs[0]] = Boolean.Parse(vs[1]);
|
||||
} else { // load in calibration presets
|
||||
caliData.Clear();
|
||||
for (int i = 0; i < vs.Length; i++) {
|
||||
string[] caliArr = vs[i].Split(',');
|
||||
float[] newArr = new float[6];
|
||||
for (int j = 1; j < caliArr.Length; j++) {
|
||||
newArr[j - 1] = float.Parse(caliArr[j]);
|
||||
}
|
||||
caliData.Add(new KeyValuePair<string, float[]>(
|
||||
caliArr[0],
|
||||
newArr
|
||||
));
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
lineNO++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
using (StreamWriter file = new StreamWriter(PATH)) {
|
||||
foreach (string k in variables.Keys)
|
||||
file.WriteLine(String.Format("{0} {1}", k, variables[k]));
|
||||
string caliStr = "";
|
||||
for (int i = 0; i < caliData.Count; i++) {
|
||||
string space = " ";
|
||||
if (i == 0) space = "";
|
||||
caliStr += space + caliData[i].Key + "," + String.Join(",", caliData[i].Value);
|
||||
}
|
||||
file.WriteLine(caliStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveCaliData(List<KeyValuePair<string, float[]>> caliData){
|
||||
string[] txt = File.ReadAllLines(PATH);
|
||||
string caliStr = "";
|
||||
for (int i = 0; i < caliData.Count; i++){
|
||||
string space = " ";
|
||||
if (i == 0) space = "";
|
||||
caliStr += space + caliData[i].Key + "," + String.Join(",", caliData[i].Value);
|
||||
}
|
||||
txt[2] = caliStr;
|
||||
File.WriteAllLines(PATH, txt);
|
||||
}
|
||||
public static bool Value(string key) {
|
||||
if (!variables.ContainsKey("ProgressiveScan") && !variables.ContainsKey("StartInTray")) {
|
||||
return false;
|
||||
}
|
||||
return variables[key];
|
||||
}
|
||||
|
||||
public static void Save(string key, bool value) {
|
||||
variables[key] = value;
|
||||
string[] txt = File.ReadAllLines(PATH);
|
||||
int NO = 0;
|
||||
foreach (string k in variables.Keys)
|
||||
{
|
||||
txt[NO] = String.Format("{0} {1}", k, variables[k]);
|
||||
NO++;
|
||||
}
|
||||
File.WriteAllLines(PATH, txt);
|
||||
}
|
||||
}
|
||||
public static void SaveCaliData(List<KeyValuePair<string, float[]>> caliData) {
|
||||
string[] txt = File.ReadAllLines(PATH);
|
||||
if (txt.Length < settingsNum + 1) // no custom calibrations yet
|
||||
Array.Resize(ref txt, txt.Length + 1);
|
||||
|
||||
string caliStr = "";
|
||||
for (int i = 0; i < caliData.Count; i++) {
|
||||
string space = " ";
|
||||
if (i == 0) space = "";
|
||||
caliStr += space + caliData[i].Key + "," + String.Join(",", caliData[i].Value);
|
||||
}
|
||||
txt[2] = caliStr;
|
||||
File.WriteAllLines(PATH, txt);
|
||||
}
|
||||
|
||||
public static void Save(string key, bool value) {
|
||||
variables[key] = value;
|
||||
string[] txt = File.ReadAllLines(PATH);
|
||||
int NO = 0;
|
||||
foreach (string k in variables.Keys) {
|
||||
txt[NO] = String.Format("{0} {1}", k, variables[k]);
|
||||
NO++;
|
||||
}
|
||||
File.WriteAllLines(PATH, txt);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
4
BetterJoyForCemu/MainForm.Designer.cs
generated
4
BetterJoyForCemu/MainForm.Designer.cs
generated
|
@ -331,10 +331,6 @@
|
|||
this.AutoCalibrate.Text = "Calibrate";
|
||||
this.AutoCalibrate.UseVisualStyleBackColor = true;
|
||||
this.AutoCalibrate.Click += new System.EventHandler(this.StartCalibrate);
|
||||
if (!this.nonOriginal)
|
||||
{
|
||||
this.AutoCalibrate.Hide();
|
||||
}
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
|
|
|
@ -15,391 +15,367 @@ using System.Xml.Linq;
|
|||
|
||||
namespace BetterJoyForCemu {
|
||||
public partial class MainForm : Form {
|
||||
public bool nonOriginal = Boolean.Parse(ConfigurationManager.AppSettings["NonOriginalController"]);
|
||||
public List<Button> con, loc;
|
||||
public bool calibrate;
|
||||
public List<KeyValuePair<string,float[]>> caliData;
|
||||
private Timer countDown;
|
||||
private int count;
|
||||
public List<int> xG;
|
||||
public List<int> yG;
|
||||
public List<int> zG;
|
||||
public List<int> xA;
|
||||
public List<int> yA;
|
||||
public List<int> zA;
|
||||
public bool nonOriginal = Boolean.Parse(ConfigurationManager.AppSettings["NonOriginalController"]);
|
||||
public List<Button> con, loc;
|
||||
public bool calibrate;
|
||||
public List<KeyValuePair<string, float[]>> caliData;
|
||||
private Timer countDown;
|
||||
private int count;
|
||||
public List<int> xG, yG, zG, xA, yA, zA;
|
||||
|
||||
public MainForm() {
|
||||
xG = new List<int>();
|
||||
yG = new List<int>();
|
||||
zG = new List<int>();
|
||||
xA = new List<int>();
|
||||
yA = new List<int>();
|
||||
zA = new List<int>();
|
||||
caliData = new List<KeyValuePair<string, float[]>> {
|
||||
new KeyValuePair<string, float[]>("0", new float[6] {0,0,0,-710,0,0})
|
||||
};
|
||||
xG = new List<int>(); yG = new List<int>(); zG = new List<int>();
|
||||
xA = new List<int>(); yA = new List<int>(); zA = new List<int>();
|
||||
caliData = new List<KeyValuePair<string, float[]>> {
|
||||
new KeyValuePair<string, float[]>("0", new float[6] {0,0,0,-710,0,0})
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
con = new List<Button> { con1, con2, con3, con4 };
|
||||
loc = new List<Button> { loc1, loc2, loc3, loc4 };
|
||||
if (!nonOriginal)
|
||||
AutoCalibrate.Hide();
|
||||
|
||||
//list all options
|
||||
string[] myConfigs = ConfigurationManager.AppSettings.AllKeys;
|
||||
Size childSize = new Size(87, 20);
|
||||
for (int i = 0; i != myConfigs.Length; i++)
|
||||
{
|
||||
tableLayoutPanel1.RowCount++;
|
||||
tableLayoutPanel1.Controls.Add(new Label() { Text = myConfigs[i], TextAlign=ContentAlignment.BottomLeft, AutoEllipsis=true, Size = childSize }, 0, i);
|
||||
con = new List<Button> { con1, con2, con3, con4 };
|
||||
loc = new List<Button> { loc1, loc2, loc3, loc4 };
|
||||
|
||||
var value = ConfigurationManager.AppSettings[myConfigs[i]];
|
||||
Control childControl;
|
||||
if (value == "true" || value == "false")
|
||||
{
|
||||
childControl = new CheckBox() { Checked = Boolean.Parse(value), Size= childSize };
|
||||
}
|
||||
else
|
||||
{
|
||||
childControl = new TextBox() { Text = value, Size = childSize };
|
||||
}
|
||||
//list all options
|
||||
string[] myConfigs = ConfigurationManager.AppSettings.AllKeys;
|
||||
Size childSize = new Size(87, 20);
|
||||
for (int i = 0; i != myConfigs.Length; i++) {
|
||||
tableLayoutPanel1.RowCount++;
|
||||
tableLayoutPanel1.Controls.Add(new Label() { Text = myConfigs[i], TextAlign = ContentAlignment.BottomLeft, AutoEllipsis = true, Size = childSize }, 0, i);
|
||||
|
||||
tableLayoutPanel1.Controls.Add(childControl, 1, i);
|
||||
childControl.MouseClick += cbBox_Changed;
|
||||
}
|
||||
}
|
||||
var value = ConfigurationManager.AppSettings[myConfigs[i]];
|
||||
Control childControl;
|
||||
if (value == "true" || value == "false") {
|
||||
childControl = new CheckBox() { Checked = Boolean.Parse(value), Size = childSize };
|
||||
} else {
|
||||
childControl = new TextBox() { Text = value, Size = childSize };
|
||||
}
|
||||
|
||||
private void HideToTray() {
|
||||
this.WindowState = FormWindowState.Minimized;
|
||||
notifyIcon.Visible = true;
|
||||
notifyIcon.ShowBalloonTip(1);
|
||||
this.ShowInTaskbar = false;
|
||||
this.Hide();
|
||||
}
|
||||
tableLayoutPanel1.Controls.Add(childControl, 1, i);
|
||||
childControl.MouseClick += cbBox_Changed;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowFromTray() {
|
||||
this.Show();
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
this.ShowInTaskbar = true;
|
||||
this.FormBorderStyle = FormBorderStyle.FixedSingle;
|
||||
this.Icon = Properties.Resources.betterjoyforcemu_icon;
|
||||
notifyIcon.Visible = false;
|
||||
}
|
||||
private void HideToTray() {
|
||||
this.WindowState = FormWindowState.Minimized;
|
||||
notifyIcon.Visible = true;
|
||||
notifyIcon.ShowBalloonTip(1);
|
||||
this.ShowInTaskbar = false;
|
||||
this.Hide();
|
||||
}
|
||||
|
||||
private void ShowFromTray() {
|
||||
this.Show();
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
this.ShowInTaskbar = true;
|
||||
this.FormBorderStyle = FormBorderStyle.FixedSingle;
|
||||
this.Icon = Properties.Resources.betterjoyforcemu_icon;
|
||||
notifyIcon.Visible = false;
|
||||
}
|
||||
|
||||
private void MainForm_Resize(object sender, EventArgs e) {
|
||||
if (this.WindowState == FormWindowState.Minimized) {
|
||||
HideToTray();
|
||||
HideToTray();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) {
|
||||
ShowFromTray();
|
||||
ShowFromTray();
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e) {
|
||||
Config.Init(caliData);
|
||||
Config.Init(caliData);
|
||||
|
||||
Program.Start();
|
||||
Program.Start();
|
||||
|
||||
passiveScanBox.Checked = Config.Value("ProgressiveScan");
|
||||
startInTrayBox.Checked = Config.Value("StartInTray");
|
||||
passiveScanBox.Checked = Config.Value("ProgressiveScan");
|
||||
startInTrayBox.Checked = Config.Value("StartInTray");
|
||||
|
||||
if (Config.Value("StartInTray")) {
|
||||
HideToTray();
|
||||
}
|
||||
else {
|
||||
ShowFromTray();
|
||||
}
|
||||
}
|
||||
|
||||
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) {
|
||||
try {
|
||||
Program.Stop();
|
||||
Environment.Exit(0);
|
||||
} catch { }
|
||||
}
|
||||
|
||||
private void exitToolStripMenuItem_Click(object sender, EventArgs e) { // this does not work, for some reason. Fix before release
|
||||
try {
|
||||
Program.Stop();
|
||||
Close();
|
||||
Environment.Exit(0);
|
||||
} catch { }
|
||||
if (Config.Value("StartInTray")) {
|
||||
HideToTray();
|
||||
} else {
|
||||
ShowFromTray();
|
||||
}
|
||||
}
|
||||
|
||||
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
|
||||
linkLabel1.LinkVisited = true;
|
||||
System.Diagnostics.Process.Start("http://paypal.me/DavidKhachaturov/5");
|
||||
}
|
||||
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) {
|
||||
try {
|
||||
Program.Stop();
|
||||
Environment.Exit(0);
|
||||
} catch { }
|
||||
}
|
||||
|
||||
private void passiveScanBox_CheckedChanged(object sender, EventArgs e) {
|
||||
Config.Save("ProgressiveScan", passiveScanBox.Checked);
|
||||
}
|
||||
private void exitToolStripMenuItem_Click(object sender, EventArgs e) { // this does not work, for some reason. Fix before release
|
||||
try {
|
||||
Program.Stop();
|
||||
Close();
|
||||
Environment.Exit(0);
|
||||
} catch { }
|
||||
}
|
||||
|
||||
public void AppendTextBox(string value) { // https://stackoverflow.com/questions/519233/writing-to-a-textbox-from-another-thread
|
||||
if (InvokeRequired) {
|
||||
this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
|
||||
return;
|
||||
}
|
||||
console.AppendText(value);
|
||||
}
|
||||
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
|
||||
linkLabel1.LinkVisited = true;
|
||||
System.Diagnostics.Process.Start("http://paypal.me/DavidKhachaturov/5");
|
||||
}
|
||||
|
||||
bool toRumble = Boolean.Parse(ConfigurationManager.AppSettings["EnableRumble"]);
|
||||
bool showAsXInput = Boolean.Parse(ConfigurationManager.AppSettings["ShowAsXInput"]);
|
||||
private void passiveScanBox_CheckedChanged(object sender, EventArgs e) {
|
||||
Config.Save("ProgressiveScan", passiveScanBox.Checked);
|
||||
}
|
||||
|
||||
public void locBtnClick(object sender, EventArgs e) {
|
||||
Button bb = sender as Button;
|
||||
public void AppendTextBox(string value) { // https://stackoverflow.com/questions/519233/writing-to-a-textbox-from-another-thread
|
||||
if (InvokeRequired) {
|
||||
this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
|
||||
return;
|
||||
}
|
||||
console.AppendText(value);
|
||||
}
|
||||
|
||||
if (bb.Tag.GetType() == typeof(Button)) {
|
||||
Button button = bb.Tag as Button;
|
||||
bool toRumble = Boolean.Parse(ConfigurationManager.AppSettings["EnableRumble"]);
|
||||
bool showAsXInput = Boolean.Parse(ConfigurationManager.AppSettings["ShowAsXInput"]);
|
||||
|
||||
if (button.Tag.GetType() == typeof(Joycon)) {
|
||||
Joycon v = (Joycon) button.Tag;
|
||||
v.SetRumble(20.0f, 400.0f, 1.0f, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void locBtnClick(object sender, EventArgs e) {
|
||||
Button bb = sender as Button;
|
||||
|
||||
public void conBtnClick(object sender, EventArgs e) {
|
||||
Button button = sender as Button;
|
||||
if (bb.Tag.GetType() == typeof(Button)) {
|
||||
Button button = bb.Tag as Button;
|
||||
|
||||
if (button.Tag.GetType() == typeof(Joycon)) {
|
||||
Joycon v = (Joycon)button.Tag;
|
||||
if (button.Tag.GetType() == typeof(Joycon)) {
|
||||
Joycon v = (Joycon)button.Tag;
|
||||
v.SetRumble(20.0f, 400.0f, 1.0f, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v.other == null && !v.isPro) { // needs connecting to other joycon (so messy omg)
|
||||
bool succ = false;
|
||||
foreach (Joycon jc in Program.mgr.j) {
|
||||
if (!jc.isPro && jc.isLeft != v.isLeft && jc != v && jc.other == null) {
|
||||
v.other = jc;
|
||||
jc.other = v;
|
||||
public void conBtnClick(object sender, EventArgs e) {
|
||||
Button button = sender as Button;
|
||||
|
||||
//Set both Joycon LEDs to the one with the lowest ID
|
||||
byte led = jc.LED <= v.LED ? jc.LED : v.LED;
|
||||
jc.LED = led;
|
||||
v.LED = led;
|
||||
jc.SetLED(led);
|
||||
v.SetLED(led);
|
||||
if (button.Tag.GetType() == typeof(Joycon)) {
|
||||
Joycon v = (Joycon)button.Tag;
|
||||
|
||||
v.xin.Dispose();
|
||||
v.xin = null;
|
||||
if (v.other == null && !v.isPro) { // needs connecting to other joycon (so messy omg)
|
||||
bool succ = false;
|
||||
foreach (Joycon jc in Program.mgr.j) {
|
||||
if (!jc.isPro && jc.isLeft != v.isLeft && jc != v && jc.other == null) {
|
||||
v.other = jc;
|
||||
jc.other = v;
|
||||
|
||||
foreach (Button b in con)
|
||||
if (b.Tag == jc)
|
||||
b.BackgroundImage = jc.isLeft ? Properties.Resources.jc_left : Properties.Resources.jc_right;
|
||||
//Set both Joycon LEDs to the one with the lowest ID
|
||||
byte led = jc.LED <= v.LED ? jc.LED : v.LED;
|
||||
jc.LED = led;
|
||||
v.LED = led;
|
||||
jc.SetLED(led);
|
||||
v.SetLED(led);
|
||||
|
||||
succ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
v.xin.Dispose();
|
||||
v.xin = null;
|
||||
|
||||
if (succ)
|
||||
foreach (Button b in con)
|
||||
if (b.Tag == v)
|
||||
b.BackgroundImage = v.isLeft ? Properties.Resources.jc_left : Properties.Resources.jc_right;
|
||||
} else if (v.other != null && !v.isPro) { // needs disconnecting from other joycon
|
||||
if (v.xin == null) {
|
||||
ReenableXinput(v);
|
||||
v.xin.Connect();
|
||||
}
|
||||
foreach (Button b in con)
|
||||
if (b.Tag == jc)
|
||||
b.BackgroundImage = jc.isLeft ? Properties.Resources.jc_left : Properties.Resources.jc_right;
|
||||
|
||||
if (v.other.xin == null) {
|
||||
ReenableXinput(v.other);
|
||||
v.other.xin.Connect();
|
||||
}
|
||||
succ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
button.BackgroundImage = v.isLeft ? Properties.Resources.jc_left_s : Properties.Resources.jc_right_s;
|
||||
if (succ)
|
||||
foreach (Button b in con)
|
||||
if (b.Tag == v)
|
||||
b.BackgroundImage = v.isLeft ? Properties.Resources.jc_left : Properties.Resources.jc_right;
|
||||
} else if (v.other != null && !v.isPro) { // needs disconnecting from other joycon
|
||||
if (v.xin == null) {
|
||||
ReenableXinput(v);
|
||||
v.xin.Connect();
|
||||
}
|
||||
|
||||
foreach (Button b in con)
|
||||
if (b.Tag == v.other)
|
||||
b.BackgroundImage = v.other.isLeft ? Properties.Resources.jc_left_s : Properties.Resources.jc_right_s;
|
||||
if (v.other.xin == null) {
|
||||
ReenableXinput(v.other);
|
||||
v.other.xin.Connect();
|
||||
}
|
||||
|
||||
//Set original Joycon LEDs
|
||||
v.other.LED = (byte)(0x1 << v.other.PadId);
|
||||
v.LED = (byte)(0x1 << v.PadId);
|
||||
v.other.SetLED(v.other.LED);
|
||||
v.SetLED(v.LED);
|
||||
button.BackgroundImage = v.isLeft ? Properties.Resources.jc_left_s : Properties.Resources.jc_right_s;
|
||||
|
||||
v.other.other = null;
|
||||
v.other = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (Button b in con)
|
||||
if (b.Tag == v.other)
|
||||
b.BackgroundImage = v.other.isLeft ? Properties.Resources.jc_left_s : Properties.Resources.jc_right_s;
|
||||
|
||||
private void startInTrayBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Config.Save("StartInTray", startInTrayBox.Checked);
|
||||
}
|
||||
//Set original Joycon LEDs
|
||||
v.other.LED = (byte)(0x1 << v.other.PadId);
|
||||
v.LED = (byte)(0x1 << v.PadId);
|
||||
v.other.SetLED(v.other.LED);
|
||||
v.SetLED(v.LED);
|
||||
|
||||
private void btn_open3rdP_Click(object sender, EventArgs e) {
|
||||
_3rdPartyControllers partyForm = new _3rdPartyControllers();
|
||||
partyForm.ShowDialog();
|
||||
}
|
||||
v.other.other = null;
|
||||
v.other = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
Application.Restart();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
private void startInTrayBox_CheckedChanged(object sender, EventArgs e) {
|
||||
Config.Save("StartInTray", startInTrayBox.Checked);
|
||||
}
|
||||
|
||||
void ReenableXinput(Joycon v) {
|
||||
if (showAsXInput) {
|
||||
v.xin = new Xbox360Controller(Program.emClient);
|
||||
private void btn_open3rdP_Click(object sender, EventArgs e) {
|
||||
_3rdPartyControllers partyForm = new _3rdPartyControllers();
|
||||
partyForm.ShowDialog();
|
||||
}
|
||||
|
||||
if (toRumble)
|
||||
v.xin.FeedbackReceived += v.ReceiveRumble;
|
||||
v.report = new Xbox360Report();
|
||||
}
|
||||
}
|
||||
private void button1_Click(object sender, EventArgs e) {
|
||||
Application.Restart();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void label2_Click(object sender, EventArgs e)
|
||||
{
|
||||
rightPanel.Visible = !rightPanel.Visible;
|
||||
foldLbl.Text = rightPanel.Visible ? "<" : ">";
|
||||
}
|
||||
void ReenableXinput(Joycon v) {
|
||||
if (showAsXInput) {
|
||||
v.xin = new Xbox360Controller(Program.emClient);
|
||||
|
||||
private void cbBox_Changed(object sender, EventArgs e)
|
||||
{
|
||||
var coord = tableLayoutPanel1.GetPositionFromControl(sender as Control);
|
||||
if (toRumble)
|
||||
v.xin.FeedbackReceived += v.ReceiveRumble;
|
||||
v.report = new Xbox360Report();
|
||||
}
|
||||
}
|
||||
|
||||
var valCtl = tableLayoutPanel1.GetControlFromPosition(coord.Column, coord.Row);
|
||||
var KeyCtl = tableLayoutPanel1.GetControlFromPosition(coord.Column - 1, coord.Row).Text;
|
||||
private void label2_Click(object sender, EventArgs e) {
|
||||
rightPanel.Visible = !rightPanel.Visible;
|
||||
foldLbl.Text = rightPanel.Visible ? "<" : ">";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
var settings = configFile.AppSettings.Settings;
|
||||
if (sender.GetType() == typeof(CheckBox) && settings[KeyCtl] != null)
|
||||
{
|
||||
settings[KeyCtl].Value = ((CheckBox)valCtl).Checked.ToString().ToLower();
|
||||
}
|
||||
else if (sender.GetType() == typeof(TextBox) && settings[KeyCtl] != null)
|
||||
{
|
||||
settings[KeyCtl].Value = ((TextBox)valCtl).Text.ToLower();
|
||||
}
|
||||
configFile.Save(ConfigurationSaveMode.Modified);
|
||||
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
|
||||
}
|
||||
catch (ConfigurationErrorsException)
|
||||
{
|
||||
Console.WriteLine("Error writing app settings");
|
||||
Trace.WriteLine(String.Format("rw {0}, column {1}, {2}, {3}", coord.Row, coord.Column, sender.GetType(), KeyCtl));
|
||||
}
|
||||
}
|
||||
private void StartCalibrate(object sender, EventArgs e){
|
||||
if(Program.mgr.j.Count == 0){
|
||||
this.console.Text = "Please connect to a controller.";
|
||||
return;
|
||||
}
|
||||
if (Program.mgr.j.Count > 1){
|
||||
this.console.Text = "Please only use one controller.";
|
||||
return;
|
||||
}
|
||||
this.AutoCalibrate.Enabled = false;
|
||||
countDown = new Timer();
|
||||
this.count = 4;
|
||||
this.CountDown(null, null);
|
||||
countDown.Tick += new EventHandler(CountDown);
|
||||
countDown.Interval = 1000;
|
||||
countDown.Enabled = true;
|
||||
}
|
||||
private void cbBox_Changed(object sender, EventArgs e) {
|
||||
var coord = tableLayoutPanel1.GetPositionFromControl(sender as Control);
|
||||
|
||||
private void StartGetData(){
|
||||
this.xG.Clear();
|
||||
this.yG.Clear();
|
||||
this.zG.Clear();
|
||||
this.xA.Clear();
|
||||
this.yA.Clear();
|
||||
this.zA.Clear();
|
||||
countDown = new Timer();
|
||||
this.count = 3;
|
||||
this.calibrate = true;
|
||||
countDown.Tick += new EventHandler(CalcData);
|
||||
countDown.Interval = 1000;
|
||||
countDown.Enabled = true;
|
||||
}
|
||||
var valCtl = tableLayoutPanel1.GetControlFromPosition(coord.Column, coord.Row);
|
||||
var KeyCtl = tableLayoutPanel1.GetControlFromPosition(coord.Column - 1, coord.Row).Text;
|
||||
|
||||
private void CountDown(object sender, EventArgs e){
|
||||
if(this.count == 0){
|
||||
this.console.Text = "Calibrating...";
|
||||
countDown.Stop();
|
||||
this.StartGetData();
|
||||
} else {
|
||||
this.console.Text = "Plese keep controller flat." + "\r\n";
|
||||
this.console.Text += "Calibrate will start in " + this.count + " seconds.";
|
||||
this.count--;
|
||||
}
|
||||
}
|
||||
private void CalcData(object sender, EventArgs e){
|
||||
if (this.count == 0){
|
||||
countDown.Stop();
|
||||
this.calibrate = false;
|
||||
string serNum = Program.mgr.j.First().serial_number;
|
||||
int serIndex = this.findSer(serNum);
|
||||
float[] Arr = new float[6] { 0,0,0,0,0,0};
|
||||
if(serIndex == -1){
|
||||
this.caliData.Add(new KeyValuePair<string, float[]>(
|
||||
serNum,
|
||||
Arr
|
||||
));
|
||||
} else {
|
||||
Arr = this.caliData[serIndex].Value;
|
||||
}
|
||||
Random rnd = new Random();
|
||||
Arr[0] = (float)quickselect_median(this.xG, rnd.Next);
|
||||
Arr[1] = (float)quickselect_median(this.yG, rnd.Next);
|
||||
Arr[2] = (float)quickselect_median(this.zG, rnd.Next);
|
||||
Arr[3] = (float)quickselect_median(this.xA, rnd.Next);
|
||||
Arr[4] = (float)quickselect_median(this.yA, rnd.Next);
|
||||
Arr[5] = (float)quickselect_median(this.zA, rnd.Next) - 4010; //Joycon.cs acc_sen 16384
|
||||
this.console.Text = "Calibrate completed!!!" + "\r\n";
|
||||
Config.SaveCaliData(this.caliData);
|
||||
Program.mgr.j.First().getActiveData();
|
||||
this.AutoCalibrate.Enabled = true;
|
||||
} else {
|
||||
this.count--;
|
||||
}
|
||||
try {
|
||||
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
|
||||
var settings = configFile.AppSettings.Settings;
|
||||
if (sender.GetType() == typeof(CheckBox) && settings[KeyCtl] != null) {
|
||||
settings[KeyCtl].Value = ((CheckBox)valCtl).Checked.ToString().ToLower();
|
||||
} else if (sender.GetType() == typeof(TextBox) && settings[KeyCtl] != null) {
|
||||
settings[KeyCtl].Value = ((TextBox)valCtl).Text.ToLower();
|
||||
}
|
||||
configFile.Save(ConfigurationSaveMode.Modified);
|
||||
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
|
||||
} catch (ConfigurationErrorsException) {
|
||||
Console.WriteLine("Error writing app settings");
|
||||
Trace.WriteLine(String.Format("rw {0}, column {1}, {2}, {3}", coord.Row, coord.Column, sender.GetType(), KeyCtl));
|
||||
}
|
||||
}
|
||||
private void StartCalibrate(object sender, EventArgs e) {
|
||||
if (Program.mgr.j.Count == 0) {
|
||||
this.console.Text = "Please connect a single pro controller.";
|
||||
return;
|
||||
}
|
||||
if (Program.mgr.j.Count > 1) {
|
||||
this.console.Text = "Please calibrate one controller at a time (disconnect others).";
|
||||
return;
|
||||
}
|
||||
this.AutoCalibrate.Enabled = false;
|
||||
countDown = new Timer();
|
||||
this.count = 4;
|
||||
this.CountDown(null, null);
|
||||
countDown.Tick += new EventHandler(CountDown);
|
||||
countDown.Interval = 1000;
|
||||
countDown.Enabled = true;
|
||||
}
|
||||
|
||||
}
|
||||
private double quickselect_median(List<int> l, Func<int,int> pivot_fn){
|
||||
int ll = l.Count;
|
||||
if (ll % 2 == 1){
|
||||
return this.quickselect(l, ll / 2, pivot_fn);
|
||||
} else {
|
||||
return 0.5 * (quickselect(l, ll / 2 - 1, pivot_fn) + quickselect(l, ll / 2, pivot_fn));
|
||||
}
|
||||
}
|
||||
private void StartGetData() {
|
||||
this.xG.Clear(); this.yG.Clear(); this.zG.Clear();
|
||||
this.xA.Clear(); this.yA.Clear(); this.zA.Clear();
|
||||
countDown = new Timer();
|
||||
this.count = 3;
|
||||
this.calibrate = true;
|
||||
countDown.Tick += new EventHandler(CalcData);
|
||||
countDown.Interval = 1000;
|
||||
countDown.Enabled = true;
|
||||
}
|
||||
|
||||
private int quickselect(List<int> l, int k, Func<int,int> pivot_fn){
|
||||
if (l.Count == 1 && k == 0){
|
||||
return l[0];
|
||||
}
|
||||
int pivot = l[pivot_fn(l.Count)];
|
||||
List<int> lows = l.Where(x => x < pivot).ToList();
|
||||
List<int> highs = l.Where(x => x > pivot).ToList();
|
||||
List<int> pivots = l.Where(x => x == pivot).ToList();
|
||||
if (k < lows.Count){
|
||||
return quickselect(lows, k, pivot_fn);
|
||||
} else if(k < (lows.Count + pivots.Count)){
|
||||
return pivots[0];
|
||||
} else {
|
||||
return quickselect(highs, k - lows.Count - pivots.Count, pivot_fn);
|
||||
}
|
||||
}
|
||||
private void CountDown(object sender, EventArgs e) {
|
||||
if (this.count == 0) {
|
||||
this.console.Text = "Calibrating...";
|
||||
countDown.Stop();
|
||||
this.StartGetData();
|
||||
} else {
|
||||
this.console.Text = "Plese keep the controller flat." + "\r\n";
|
||||
this.console.Text += "Calibration will start in " + this.count + " seconds.";
|
||||
this.count--;
|
||||
}
|
||||
}
|
||||
private void CalcData(object sender, EventArgs e) {
|
||||
if (this.count == 0) {
|
||||
countDown.Stop();
|
||||
this.calibrate = false;
|
||||
string serNum = Program.mgr.j.First().serial_number;
|
||||
int serIndex = this.findSer(serNum);
|
||||
float[] Arr = new float[6] { 0, 0, 0, 0, 0, 0 };
|
||||
if (serIndex == -1) {
|
||||
this.caliData.Add(new KeyValuePair<string, float[]>(
|
||||
serNum,
|
||||
Arr
|
||||
));
|
||||
} else {
|
||||
Arr = this.caliData[serIndex].Value;
|
||||
}
|
||||
Random rnd = new Random();
|
||||
Arr[0] = (float)quickselect_median(this.xG, rnd.Next);
|
||||
Arr[1] = (float)quickselect_median(this.yG, rnd.Next);
|
||||
Arr[2] = (float)quickselect_median(this.zG, rnd.Next);
|
||||
Arr[3] = (float)quickselect_median(this.xA, rnd.Next);
|
||||
Arr[4] = (float)quickselect_median(this.yA, rnd.Next);
|
||||
Arr[5] = (float)quickselect_median(this.zA, rnd.Next) - 4010; //Joycon.cs acc_sen 16384
|
||||
this.console.Text += "Calibration completed!!!" + "\r\n";
|
||||
Config.SaveCaliData(this.caliData);
|
||||
Program.mgr.j.First().getActiveData();
|
||||
this.AutoCalibrate.Enabled = true;
|
||||
} else {
|
||||
this.count--;
|
||||
}
|
||||
|
||||
public float[] activeCaliData(string serNum){
|
||||
for (int i = 0; i < this.caliData.Count; i++){
|
||||
if (this.caliData[i].Key == serNum){
|
||||
return this.caliData[i].Value;
|
||||
}
|
||||
}
|
||||
return this.caliData[0].Value;
|
||||
}
|
||||
}
|
||||
private double quickselect_median(List<int> l, Func<int, int> pivot_fn) {
|
||||
int ll = l.Count;
|
||||
if (ll % 2 == 1) {
|
||||
return this.quickselect(l, ll / 2, pivot_fn);
|
||||
} else {
|
||||
return 0.5 * (quickselect(l, ll / 2 - 1, pivot_fn) + quickselect(l, ll / 2, pivot_fn));
|
||||
}
|
||||
}
|
||||
|
||||
private int findSer(string serNum){
|
||||
for(int i = 0; i < this.caliData.Count; i++){
|
||||
if(this.caliData[i].Key== serNum){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private int quickselect(List<int> l, int k, Func<int, int> pivot_fn) {
|
||||
if (l.Count == 1 && k == 0) {
|
||||
return l[0];
|
||||
}
|
||||
int pivot = l[pivot_fn(l.Count)];
|
||||
List<int> lows = l.Where(x => x < pivot).ToList();
|
||||
List<int> highs = l.Where(x => x > pivot).ToList();
|
||||
List<int> pivots = l.Where(x => x == pivot).ToList();
|
||||
if (k < lows.Count) {
|
||||
return quickselect(lows, k, pivot_fn);
|
||||
} else if (k < (lows.Count + pivots.Count)) {
|
||||
return pivots[0];
|
||||
} else {
|
||||
return quickselect(highs, k - lows.Count - pivots.Count, pivot_fn);
|
||||
}
|
||||
}
|
||||
|
||||
public float[] activeCaliData(string serNum) {
|
||||
for (int i = 0; i < this.caliData.Count; i++) {
|
||||
if (this.caliData[i].Key == serNum) {
|
||||
return this.caliData[i].Value;
|
||||
}
|
||||
}
|
||||
return this.caliData[0].Value;
|
||||
}
|
||||
|
||||
private int findSer(string serNum) {
|
||||
for (int i = 0; i < this.caliData.Count; i++) {
|
||||
if (this.caliData[i].Key == serNum) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,412 +24,410 @@ using System.Windows.Forms;
|
|||
using System.ServiceProcess;
|
||||
|
||||
namespace BetterJoyForCemu {
|
||||
public class JoyconManager {
|
||||
public bool EnableIMU = true;
|
||||
public bool EnableLocalize = false;
|
||||
|
||||
private const ushort vendor_id = 0x57e;
|
||||
private const ushort vendor_id_ = 0x057e;
|
||||
private const ushort product_l = 0x2006;
|
||||
private const ushort product_r = 0x2007;
|
||||
private const ushort product_pro = 0x2009;
|
||||
|
||||
public List<Joycon> j; // Array of all connected Joy-Cons
|
||||
static JoyconManager instance;
|
||||
|
||||
public MainForm form;
|
||||
|
||||
System.Timers.Timer controllerCheck;
|
||||
|
||||
bool useHIDG = Boolean.Parse(ConfigurationManager.AppSettings["UseHIDG"]);
|
||||
|
||||
public static JoyconManager Instance {
|
||||
get { return instance; }
|
||||
}
|
||||
|
||||
public void Awake() {
|
||||
instance = this;
|
||||
j = new List<Joycon>();
|
||||
HIDapi.hid_init();
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
controllerCheck = new System.Timers.Timer(2000); // check every 2 seconds
|
||||
controllerCheck.Elapsed += CheckForNewControllersTime;
|
||||
controllerCheck.Start();
|
||||
}
|
||||
|
||||
bool ControllerAlreadyAdded(string path) {
|
||||
foreach (Joycon v in j)
|
||||
if (v.path == path)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CleanUp() { // removes dropped controllers from list
|
||||
List<Joycon> rem = new List<Joycon>();
|
||||
for (int i = 0; i < j.Count; i++) {
|
||||
Joycon v = j[i];
|
||||
if (v.state == Joycon.state_.DROPPED) {
|
||||
if (v.other != null)
|
||||
v.other.other = null; // The other of the other is the joycon itself
|
||||
|
||||
v.Detach(); rem.Add(v);
|
||||
|
||||
foreach (Button b in form.con) {
|
||||
if (b.Enabled & b.Tag == v) {
|
||||
b.Invoke(new MethodInvoker(delegate {
|
||||
b.BackColor = System.Drawing.Color.FromArgb(0x00, System.Drawing.SystemColors.Control);
|
||||
b.Enabled = false;
|
||||
b.BackgroundImage = Properties.Resources.cross;
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
form.AppendTextBox("Removed dropped controller to list. Can be reconnected.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Joycon v in rem)
|
||||
j.Remove(v);
|
||||
}
|
||||
|
||||
void CheckForNewControllersTime(Object source, ElapsedEventArgs e) {
|
||||
if (Config.Value("ProgressiveScan")) {
|
||||
CheckForNewControllers();
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckForNewControllers() {
|
||||
CleanUp();
|
||||
|
||||
// move all code for initializing devices here and well as the initial code from Start()
|
||||
bool isLeft = false;
|
||||
IntPtr ptr = HIDapi.hid_enumerate(vendor_id, 0x0);
|
||||
IntPtr top_ptr = ptr;
|
||||
|
||||
hid_device_info enumerate; // Add device to list
|
||||
bool foundNew = false;
|
||||
while (ptr != IntPtr.Zero) {
|
||||
enumerate = (hid_device_info)Marshal.PtrToStructure(ptr, typeof(hid_device_info));
|
||||
if (form.nonOriginal)
|
||||
{
|
||||
enumerate.product_id = product_pro;
|
||||
}
|
||||
|
||||
if ((enumerate.product_id == product_l || enumerate.product_id == product_r || enumerate.product_id == product_pro) && !ControllerAlreadyAdded(enumerate.path)) {
|
||||
switch (enumerate.product_id) {
|
||||
case product_l:
|
||||
isLeft = true;
|
||||
form.AppendTextBox("Left Joy-Con connected.\r\n"); break;
|
||||
case product_r:
|
||||
isLeft = false;
|
||||
form.AppendTextBox("Right Joy-Con connected.\r\n"); break;
|
||||
case product_pro:
|
||||
isLeft = true;
|
||||
form.AppendTextBox("Pro controller connected.\r\n"); break;
|
||||
default:
|
||||
form.AppendTextBox("Non Joy-Con Nintendo input device skipped.\r\n"); break;
|
||||
}
|
||||
|
||||
// Add controller to block-list for HidGuardian
|
||||
if (useHIDG) {
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/add/");
|
||||
string postData = @"hwids=HID\" + enumerate.path.Split('#')[1].ToUpper();
|
||||
var data = Encoding.UTF8.GetBytes(postData);
|
||||
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
|
||||
request.ContentLength = data.Length;
|
||||
|
||||
using (var stream = request.GetRequestStream())
|
||||
stream.Write(data, 0, data.Length);
|
||||
|
||||
try {
|
||||
var response = (HttpWebResponse)request.GetResponse();
|
||||
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
|
||||
} catch {
|
||||
form.AppendTextBox("Unable to add controller to block-list.\r\n");
|
||||
}
|
||||
} else { // Remove affected devices from list
|
||||
try {
|
||||
HttpWebResponse r1 = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/purge/").GetResponse();
|
||||
} catch { }
|
||||
}
|
||||
// -------------------- //
|
||||
|
||||
IntPtr handle = HIDapi.hid_open_path(enumerate.path);
|
||||
try {
|
||||
HIDapi.hid_set_nonblocking(handle, 1);
|
||||
} catch {
|
||||
form.AppendTextBox("Unable to open path to device - are you using the correct (64 vs 32-bit) version for your PC?\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
j.Add(new Joycon(handle, EnableIMU, EnableLocalize & EnableIMU, 0.05f, isLeft, enumerate.path, enumerate.serial_number, j.Count, enumerate.product_id == product_pro));
|
||||
|
||||
foundNew = true;
|
||||
j.Last().form = form;
|
||||
|
||||
if (j.Count < 5) {
|
||||
int ii = -1;
|
||||
foreach (Button v in form.con) {
|
||||
ii++;
|
||||
if (!v.Enabled) {
|
||||
System.Drawing.Bitmap temp;
|
||||
switch (enumerate.product_id) {
|
||||
case (product_l):
|
||||
temp = Properties.Resources.jc_left_s; break;
|
||||
case (product_r):
|
||||
temp = Properties.Resources.jc_right_s; break;
|
||||
case (product_pro):
|
||||
temp = Properties.Resources.pro; break;
|
||||
default:
|
||||
temp = Properties.Resources.cross; break;
|
||||
}
|
||||
|
||||
v.Invoke(new MethodInvoker(delegate {
|
||||
v.Tag = j.Last(); // assign controller to button
|
||||
v.Enabled = true;
|
||||
v.Click += new EventHandler(form.conBtnClick);
|
||||
v.BackgroundImage = temp;
|
||||
}));
|
||||
|
||||
form.loc[ii].Invoke(new MethodInvoker(delegate {
|
||||
form.loc[ii].Tag = v;
|
||||
form.loc[ii].Click += new EventHandler(form.locBtnClick);
|
||||
}));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] mac = new byte[6];
|
||||
for (int n = 0; n < 6; n++)
|
||||
mac[n] = byte.Parse(enumerate.serial_number.Substring(n * 2, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
j[j.Count - 1].PadMacAddress = new PhysicalAddress(mac);
|
||||
}
|
||||
|
||||
ptr = enumerate.next;
|
||||
}
|
||||
|
||||
if (foundNew) { // attempt to auto join-up joycons on connection
|
||||
Joycon temp = null;
|
||||
foreach (Joycon v in j) {
|
||||
if (!v.isPro) {
|
||||
if (temp == null)
|
||||
temp = v;
|
||||
else if (temp.isLeft != v.isLeft && v.other == null) {
|
||||
temp.other = v;
|
||||
v.other = temp;
|
||||
|
||||
//Set both Joycon LEDs to the one with the lowest ID
|
||||
byte led = temp.LED <= v.LED ? temp.LED : v.LED;
|
||||
temp.LED = led;
|
||||
v.LED = led;
|
||||
temp.SetLED(led);
|
||||
v.SetLED(led);
|
||||
|
||||
temp.xin.Dispose();
|
||||
temp.xin = null;
|
||||
|
||||
foreach (Button b in form.con)
|
||||
if (b.Tag == v || b.Tag == temp) {
|
||||
Joycon tt = (b.Tag == v) ? v : (b.Tag == temp) ? temp : v;
|
||||
b.BackgroundImage = tt.isLeft ? Properties.Resources.jc_left : Properties.Resources.jc_right;
|
||||
}
|
||||
|
||||
temp = null; // repeat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HIDapi.hid_free_enumeration(top_ptr);
|
||||
|
||||
foreach (Joycon jc in j) { // Connect device straight away
|
||||
if (jc.state == Joycon.state_.NOT_ATTACHED) {
|
||||
if (jc.xin != null)
|
||||
jc.xin.Connect();
|
||||
|
||||
jc.Attach(leds_: jc.LED);
|
||||
jc.Begin();
|
||||
if (form.nonOriginal)
|
||||
{
|
||||
jc.getActiveData();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
for (int i = 0; i < j.Count; ++i)
|
||||
j[i].Update();
|
||||
}
|
||||
|
||||
public void OnApplicationQuit() {
|
||||
foreach (Joycon v in j) {
|
||||
v.Detach();
|
||||
|
||||
if (v.xin != null) {
|
||||
v.xin.Disconnect();
|
||||
v.xin.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
controllerCheck.Stop();
|
||||
HIDapi.hid_exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Custom timer class because system timers have a limit of 15.6ms
|
||||
class HighResTimer {
|
||||
double interval = 0;
|
||||
double frequency = 0;
|
||||
|
||||
Thread thread;
|
||||
|
||||
public delegate void ActionDelegate();
|
||||
ActionDelegate func;
|
||||
|
||||
bool run = false;
|
||||
|
||||
public HighResTimer(double f, ActionDelegate a) {
|
||||
frequency = f;
|
||||
interval = 1.0 / f;
|
||||
|
||||
func = a;
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
run = true;
|
||||
thread = new Thread(new ThreadStart(Run));
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
void Run() {
|
||||
while (run) {
|
||||
func();
|
||||
int timeToSleep = (int)(interval * 1000);
|
||||
Thread.Sleep(timeToSleep);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop() {
|
||||
run = false;
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
public static PhysicalAddress btMAC = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 });
|
||||
public static UdpServer server;
|
||||
static double pollsPerSecond = 120.0;
|
||||
|
||||
public static ViGEmClient emClient;
|
||||
|
||||
private static readonly HttpClient client = new HttpClient();
|
||||
|
||||
public static JoyconManager mgr;
|
||||
static HighResTimer timer;
|
||||
static string pid;
|
||||
|
||||
static MainForm form;
|
||||
|
||||
static bool useHIDG = Boolean.Parse(ConfigurationManager.AppSettings["UseHIDG"]);
|
||||
|
||||
public static void Start() {
|
||||
pid = Process.GetCurrentProcess().Id.ToString(); // get current process id for HidCerberus.Srv
|
||||
|
||||
if (useHIDG) {
|
||||
try {
|
||||
var HidCerberusService = new ServiceController("HidCerberus Service");
|
||||
if (HidCerberusService.Status == ServiceControllerStatus.Stopped) {
|
||||
form.console.Text += "HidGuardian was stopped. Starting...\r\n";
|
||||
|
||||
try {
|
||||
HidCerberusService.Start();
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to start HidGuardian - everything should work fine without it, but if you need it, run the app again as an admin.\r\n";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to start HidGuardian - everything should work fine without it, but if you need it, install it properly as admin.\r\n";
|
||||
}
|
||||
|
||||
HttpWebResponse response;
|
||||
if (Boolean.Parse(ConfigurationManager.AppSettings["PurgeWhitelist"])) {
|
||||
try {
|
||||
response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/purge/").GetResponse(); // remove all programs allowed to see controller
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to purge whitelist.\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/add/" + pid).GetResponse(); // add BetterJoyForCemu to allowed processes
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to add program to whitelist.\r\n";
|
||||
}
|
||||
} else {
|
||||
form.console.Text += "HidGuardian is disabled.\r\n";
|
||||
}
|
||||
|
||||
emClient = new ViGEmClient(); // Manages emulated XInput
|
||||
|
||||
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
|
||||
// Get local BT host MAC
|
||||
if (nic.NetworkInterfaceType != NetworkInterfaceType.FastEthernetFx && nic.NetworkInterfaceType != NetworkInterfaceType.Wireless80211) {
|
||||
if (nic.Name.Split()[0] == "Bluetooth") {
|
||||
btMAC = nic.GetPhysicalAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mgr = new JoyconManager();
|
||||
mgr.form = form;
|
||||
mgr.Awake();
|
||||
mgr.CheckForNewControllers();
|
||||
mgr.Start();
|
||||
|
||||
server = new UdpServer(mgr.j);
|
||||
server.form = form;
|
||||
|
||||
server.Start(IPAddress.Parse(ConfigurationManager.AppSettings["IP"]), Int32.Parse(ConfigurationManager.AppSettings["Port"]));
|
||||
timer = new HighResTimer(pollsPerSecond, new HighResTimer.ActionDelegate(mgr.Update));
|
||||
timer.Start();
|
||||
|
||||
form.console.Text += "All systems go\r\n";
|
||||
}
|
||||
|
||||
public static void Stop() {
|
||||
try {
|
||||
HttpWebResponse response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/remove/" + pid).GetResponse();
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to remove program from whitelist.\r\n";
|
||||
}
|
||||
|
||||
if (Boolean.Parse(ConfigurationManager.AppSettings["PurgeAffectedDevices"])) {
|
||||
try {
|
||||
HttpWebResponse r1 = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/purge/").GetResponse();
|
||||
} catch { }
|
||||
}
|
||||
|
||||
server.Stop();
|
||||
timer.Stop();
|
||||
mgr.OnApplicationQuit();
|
||||
|
||||
form.console.Text += "";
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
form = new MainForm();
|
||||
Application.Run(form);
|
||||
}
|
||||
}
|
||||
public class JoyconManager {
|
||||
public bool EnableIMU = true;
|
||||
public bool EnableLocalize = false;
|
||||
|
||||
private const ushort vendor_id = 0x57e;
|
||||
private const ushort vendor_id_ = 0x057e;
|
||||
private const ushort product_l = 0x2006;
|
||||
private const ushort product_r = 0x2007;
|
||||
private const ushort product_pro = 0x2009;
|
||||
|
||||
public List<Joycon> j; // Array of all connected Joy-Cons
|
||||
static JoyconManager instance;
|
||||
|
||||
public MainForm form;
|
||||
|
||||
System.Timers.Timer controllerCheck;
|
||||
|
||||
bool useHIDG = Boolean.Parse(ConfigurationManager.AppSettings["UseHIDG"]);
|
||||
|
||||
public static JoyconManager Instance {
|
||||
get { return instance; }
|
||||
}
|
||||
|
||||
public void Awake() {
|
||||
instance = this;
|
||||
j = new List<Joycon>();
|
||||
HIDapi.hid_init();
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
controllerCheck = new System.Timers.Timer(2000); // check every 2 seconds
|
||||
controllerCheck.Elapsed += CheckForNewControllersTime;
|
||||
controllerCheck.Start();
|
||||
}
|
||||
|
||||
bool ControllerAlreadyAdded(string path) {
|
||||
foreach (Joycon v in j)
|
||||
if (v.path == path)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CleanUp() { // removes dropped controllers from list
|
||||
List<Joycon> rem = new List<Joycon>();
|
||||
for (int i = 0; i < j.Count; i++) {
|
||||
Joycon v = j[i];
|
||||
if (v.state == Joycon.state_.DROPPED) {
|
||||
if (v.other != null)
|
||||
v.other.other = null; // The other of the other is the joycon itself
|
||||
|
||||
v.Detach(); rem.Add(v);
|
||||
|
||||
foreach (Button b in form.con) {
|
||||
if (b.Enabled & b.Tag == v) {
|
||||
b.Invoke(new MethodInvoker(delegate {
|
||||
b.BackColor = System.Drawing.Color.FromArgb(0x00, System.Drawing.SystemColors.Control);
|
||||
b.Enabled = false;
|
||||
b.BackgroundImage = Properties.Resources.cross;
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
form.AppendTextBox("Removed dropped controller to list. Can be reconnected.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Joycon v in rem)
|
||||
j.Remove(v);
|
||||
}
|
||||
|
||||
void CheckForNewControllersTime(Object source, ElapsedEventArgs e) {
|
||||
if (Config.Value("ProgressiveScan")) {
|
||||
CheckForNewControllers();
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckForNewControllers() {
|
||||
CleanUp();
|
||||
|
||||
// move all code for initializing devices here and well as the initial code from Start()
|
||||
bool isLeft = false;
|
||||
IntPtr ptr = HIDapi.hid_enumerate(vendor_id, 0x0);
|
||||
IntPtr top_ptr = ptr;
|
||||
|
||||
hid_device_info enumerate; // Add device to list
|
||||
bool foundNew = false;
|
||||
while (ptr != IntPtr.Zero) {
|
||||
enumerate = (hid_device_info)Marshal.PtrToStructure(ptr, typeof(hid_device_info));
|
||||
if (form.nonOriginal) {
|
||||
enumerate.product_id = product_pro;
|
||||
}
|
||||
|
||||
if ((enumerate.product_id == product_l || enumerate.product_id == product_r || enumerate.product_id == product_pro) && !ControllerAlreadyAdded(enumerate.path)) {
|
||||
switch (enumerate.product_id) {
|
||||
case product_l:
|
||||
isLeft = true;
|
||||
form.AppendTextBox("Left Joy-Con connected.\r\n"); break;
|
||||
case product_r:
|
||||
isLeft = false;
|
||||
form.AppendTextBox("Right Joy-Con connected.\r\n"); break;
|
||||
case product_pro:
|
||||
isLeft = true;
|
||||
form.AppendTextBox("Pro controller connected.\r\n"); break;
|
||||
default:
|
||||
form.AppendTextBox("Non Joy-Con Nintendo input device skipped.\r\n"); break;
|
||||
}
|
||||
|
||||
// Add controller to block-list for HidGuardian
|
||||
if (useHIDG) {
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/add/");
|
||||
string postData = @"hwids=HID\" + enumerate.path.Split('#')[1].ToUpper();
|
||||
var data = Encoding.UTF8.GetBytes(postData);
|
||||
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
|
||||
request.ContentLength = data.Length;
|
||||
|
||||
using (var stream = request.GetRequestStream())
|
||||
stream.Write(data, 0, data.Length);
|
||||
|
||||
try {
|
||||
var response = (HttpWebResponse)request.GetResponse();
|
||||
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
|
||||
} catch {
|
||||
form.AppendTextBox("Unable to add controller to block-list.\r\n");
|
||||
}
|
||||
} else { // Remove affected devices from list
|
||||
try {
|
||||
HttpWebResponse r1 = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/purge/").GetResponse();
|
||||
} catch { }
|
||||
}
|
||||
// -------------------- //
|
||||
|
||||
IntPtr handle = HIDapi.hid_open_path(enumerate.path);
|
||||
try {
|
||||
HIDapi.hid_set_nonblocking(handle, 1);
|
||||
} catch {
|
||||
form.AppendTextBox("Unable to open path to device - are you using the correct (64 vs 32-bit) version for your PC?\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
j.Add(new Joycon(handle, EnableIMU, EnableLocalize & EnableIMU, 0.05f, isLeft, enumerate.path, enumerate.serial_number, j.Count, enumerate.product_id == product_pro));
|
||||
|
||||
foundNew = true;
|
||||
j.Last().form = form;
|
||||
|
||||
if (j.Count < 5) {
|
||||
int ii = -1;
|
||||
foreach (Button v in form.con) {
|
||||
ii++;
|
||||
if (!v.Enabled) {
|
||||
System.Drawing.Bitmap temp;
|
||||
switch (enumerate.product_id) {
|
||||
case (product_l):
|
||||
temp = Properties.Resources.jc_left_s; break;
|
||||
case (product_r):
|
||||
temp = Properties.Resources.jc_right_s; break;
|
||||
case (product_pro):
|
||||
temp = Properties.Resources.pro; break;
|
||||
default:
|
||||
temp = Properties.Resources.cross; break;
|
||||
}
|
||||
|
||||
v.Invoke(new MethodInvoker(delegate {
|
||||
v.Tag = j.Last(); // assign controller to button
|
||||
v.Enabled = true;
|
||||
v.Click += new EventHandler(form.conBtnClick);
|
||||
v.BackgroundImage = temp;
|
||||
}));
|
||||
|
||||
form.loc[ii].Invoke(new MethodInvoker(delegate {
|
||||
form.loc[ii].Tag = v;
|
||||
form.loc[ii].Click += new EventHandler(form.locBtnClick);
|
||||
}));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] mac = new byte[6];
|
||||
for (int n = 0; n < 6; n++)
|
||||
mac[n] = byte.Parse(enumerate.serial_number.Substring(n * 2, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
j[j.Count - 1].PadMacAddress = new PhysicalAddress(mac);
|
||||
}
|
||||
|
||||
ptr = enumerate.next;
|
||||
}
|
||||
|
||||
if (foundNew) { // attempt to auto join-up joycons on connection
|
||||
Joycon temp = null;
|
||||
foreach (Joycon v in j) {
|
||||
if (!v.isPro) {
|
||||
if (temp == null)
|
||||
temp = v;
|
||||
else if (temp.isLeft != v.isLeft && v.other == null) {
|
||||
temp.other = v;
|
||||
v.other = temp;
|
||||
|
||||
//Set both Joycon LEDs to the one with the lowest ID
|
||||
byte led = temp.LED <= v.LED ? temp.LED : v.LED;
|
||||
temp.LED = led;
|
||||
v.LED = led;
|
||||
temp.SetLED(led);
|
||||
v.SetLED(led);
|
||||
|
||||
temp.xin.Dispose();
|
||||
temp.xin = null;
|
||||
|
||||
foreach (Button b in form.con)
|
||||
if (b.Tag == v || b.Tag == temp) {
|
||||
Joycon tt = (b.Tag == v) ? v : (b.Tag == temp) ? temp : v;
|
||||
b.BackgroundImage = tt.isLeft ? Properties.Resources.jc_left : Properties.Resources.jc_right;
|
||||
}
|
||||
|
||||
temp = null; // repeat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HIDapi.hid_free_enumeration(top_ptr);
|
||||
|
||||
foreach (Joycon jc in j) { // Connect device straight away
|
||||
if (jc.state == Joycon.state_.NOT_ATTACHED) {
|
||||
if (jc.xin != null)
|
||||
jc.xin.Connect();
|
||||
|
||||
jc.Attach(leds_: jc.LED);
|
||||
jc.Begin();
|
||||
if (form.nonOriginal) {
|
||||
jc.getActiveData();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
for (int i = 0; i < j.Count; ++i)
|
||||
j[i].Update();
|
||||
}
|
||||
|
||||
public void OnApplicationQuit() {
|
||||
foreach (Joycon v in j) {
|
||||
v.Detach();
|
||||
|
||||
if (v.xin != null) {
|
||||
v.xin.Disconnect();
|
||||
v.xin.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
controllerCheck.Stop();
|
||||
HIDapi.hid_exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Custom timer class because system timers have a limit of 15.6ms
|
||||
class HighResTimer {
|
||||
double interval = 0;
|
||||
double frequency = 0;
|
||||
|
||||
Thread thread;
|
||||
|
||||
public delegate void ActionDelegate();
|
||||
ActionDelegate func;
|
||||
|
||||
bool run = false;
|
||||
|
||||
public HighResTimer(double f, ActionDelegate a) {
|
||||
frequency = f;
|
||||
interval = 1.0 / f;
|
||||
|
||||
func = a;
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
run = true;
|
||||
thread = new Thread(new ThreadStart(Run));
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
void Run() {
|
||||
while (run) {
|
||||
func();
|
||||
int timeToSleep = (int)(interval * 1000);
|
||||
Thread.Sleep(timeToSleep);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop() {
|
||||
run = false;
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
public static PhysicalAddress btMAC = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 });
|
||||
public static UdpServer server;
|
||||
static double pollsPerSecond = 120.0;
|
||||
|
||||
public static ViGEmClient emClient;
|
||||
|
||||
private static readonly HttpClient client = new HttpClient();
|
||||
|
||||
public static JoyconManager mgr;
|
||||
static HighResTimer timer;
|
||||
static string pid;
|
||||
|
||||
static MainForm form;
|
||||
|
||||
static bool useHIDG = Boolean.Parse(ConfigurationManager.AppSettings["UseHIDG"]);
|
||||
|
||||
public static void Start() {
|
||||
pid = Process.GetCurrentProcess().Id.ToString(); // get current process id for HidCerberus.Srv
|
||||
|
||||
if (useHIDG) {
|
||||
try {
|
||||
var HidCerberusService = new ServiceController("HidCerberus Service");
|
||||
if (HidCerberusService.Status == ServiceControllerStatus.Stopped) {
|
||||
form.console.Text += "HidGuardian was stopped. Starting...\r\n";
|
||||
|
||||
try {
|
||||
HidCerberusService.Start();
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to start HidGuardian - everything should work fine without it, but if you need it, run the app again as an admin.\r\n";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to start HidGuardian - everything should work fine without it, but if you need it, install it properly as admin.\r\n";
|
||||
}
|
||||
|
||||
HttpWebResponse response;
|
||||
if (Boolean.Parse(ConfigurationManager.AppSettings["PurgeWhitelist"])) {
|
||||
try {
|
||||
response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/purge/").GetResponse(); // remove all programs allowed to see controller
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to purge whitelist.\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/add/" + pid).GetResponse(); // add BetterJoyForCemu to allowed processes
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to add program to whitelist.\r\n";
|
||||
}
|
||||
} else {
|
||||
form.console.Text += "HidGuardian is disabled.\r\n";
|
||||
}
|
||||
|
||||
emClient = new ViGEmClient(); // Manages emulated XInput
|
||||
|
||||
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
|
||||
// Get local BT host MAC
|
||||
if (nic.NetworkInterfaceType != NetworkInterfaceType.FastEthernetFx && nic.NetworkInterfaceType != NetworkInterfaceType.Wireless80211) {
|
||||
if (nic.Name.Split()[0] == "Bluetooth") {
|
||||
btMAC = nic.GetPhysicalAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mgr = new JoyconManager();
|
||||
mgr.form = form;
|
||||
mgr.Awake();
|
||||
mgr.CheckForNewControllers();
|
||||
mgr.Start();
|
||||
|
||||
server = new UdpServer(mgr.j);
|
||||
server.form = form;
|
||||
|
||||
server.Start(IPAddress.Parse(ConfigurationManager.AppSettings["IP"]), Int32.Parse(ConfigurationManager.AppSettings["Port"]));
|
||||
timer = new HighResTimer(pollsPerSecond, new HighResTimer.ActionDelegate(mgr.Update));
|
||||
timer.Start();
|
||||
|
||||
form.console.Text += "All systems go\r\n";
|
||||
}
|
||||
|
||||
public static void Stop() {
|
||||
try {
|
||||
HttpWebResponse response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/remove/" + pid).GetResponse();
|
||||
} catch (Exception e) {
|
||||
form.console.Text += "Unable to remove program from whitelist.\r\n";
|
||||
}
|
||||
|
||||
if (Boolean.Parse(ConfigurationManager.AppSettings["PurgeAffectedDevices"])) {
|
||||
try {
|
||||
HttpWebResponse r1 = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/purge/").GetResponse();
|
||||
} catch { }
|
||||
}
|
||||
|
||||
server.Stop();
|
||||
timer.Stop();
|
||||
mgr.OnApplicationQuit();
|
||||
|
||||
form.console.Text += "";
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
form = new MainForm();
|
||||
Application.Run(form);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -281,7 +281,7 @@ namespace BetterJoyForCemu {
|
|||
}
|
||||
}
|
||||
|
||||
public void Start(IPAddress ip, int port=26760) {
|
||||
public void Start(IPAddress ip, int port = 26760) {
|
||||
if (running) {
|
||||
if (udpSock != null) {
|
||||
udpSock.Close();
|
||||
|
@ -316,56 +316,56 @@ namespace BetterJoyForCemu {
|
|||
}
|
||||
}
|
||||
|
||||
bool swapAB = Boolean.Parse(ConfigurationManager.AppSettings["SwapAB"]);
|
||||
bool swapXY = Boolean.Parse(ConfigurationManager.AppSettings["SwapXY"]);
|
||||
private bool ReportToBuffer(Joycon hidReport, byte[] outputData, ref int outIdx) {
|
||||
bool swapAB = Boolean.Parse(ConfigurationManager.AppSettings["SwapAB"]);
|
||||
bool swapXY = Boolean.Parse(ConfigurationManager.AppSettings["SwapXY"]);
|
||||
private bool ReportToBuffer(Joycon hidReport, byte[] outputData, ref int outIdx) {
|
||||
outputData[outIdx] = 0;
|
||||
|
||||
bool isLeft = hidReport.isLeft;
|
||||
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_LEFT : Joycon.Button.Y)) outputData[outIdx] |= 0x80;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_DOWN : Joycon.Button.B)) outputData[outIdx] |= 0x40;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_RIGHT : Joycon.Button.A)) outputData[outIdx] |= 0x20;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_UP : Joycon.Button.X)) outputData[outIdx] |= 0x10;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_LEFT : Joycon.Button.Y)) outputData[outIdx] |= 0x80;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_DOWN : Joycon.Button.B)) outputData[outIdx] |= 0x40;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_RIGHT : Joycon.Button.A)) outputData[outIdx] |= 0x20;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_UP : Joycon.Button.X)) outputData[outIdx] |= 0x10;
|
||||
|
||||
if (hidReport.GetButton(Joycon.Button.PLUS)) outputData[outIdx] |= 0x08;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.STICK2 : Joycon.Button.STICK)) outputData[outIdx] |= 0x04;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.STICK : Joycon.Button.STICK2)) outputData[outIdx] |= 0x02;
|
||||
if (hidReport.GetButton(Joycon.Button.MINUS)) outputData[outIdx] |= 0x01;
|
||||
if (hidReport.GetButton(Joycon.Button.PLUS)) outputData[outIdx] |= 0x08;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.STICK2 : Joycon.Button.STICK)) outputData[outIdx] |= 0x04;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.STICK : Joycon.Button.STICK2)) outputData[outIdx] |= 0x02;
|
||||
if (hidReport.GetButton(Joycon.Button.MINUS)) outputData[outIdx] |= 0x01;
|
||||
|
||||
outputData[++outIdx] = 0;
|
||||
|
||||
if (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT) : (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP))) outputData[outIdx] |= 0x80;
|
||||
if (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN) : (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT))) outputData[outIdx] |= 0x40;
|
||||
if (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT) : (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN))) outputData[outIdx] |= 0x20;
|
||||
if (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP) : (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT))) outputData[outIdx] |= 0x10;
|
||||
if (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT) : (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP))) outputData[outIdx] |= 0x80;
|
||||
if (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN) : (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT))) outputData[outIdx] |= 0x40;
|
||||
if (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT) : (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN))) outputData[outIdx] |= 0x20;
|
||||
if (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP) : (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT))) outputData[outIdx] |= 0x10;
|
||||
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER2_1 : Joycon.Button.SHOULDER_1)) outputData[outIdx] |= 0x08;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER_1 : Joycon.Button.SHOULDER2_1)) outputData[outIdx] |= 0x04;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER2_2 : Joycon.Button.SHOULDER_2)) outputData[outIdx] |= 0x02;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER_2 : Joycon.Button.SHOULDER2_2)) outputData[outIdx] |= 0x01;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER2_1 : Joycon.Button.SHOULDER_1)) outputData[outIdx] |= 0x08;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER_1 : Joycon.Button.SHOULDER2_1)) outputData[outIdx] |= 0x04;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER2_2 : Joycon.Button.SHOULDER_2)) outputData[outIdx] |= 0x02;
|
||||
if (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER_2 : Joycon.Button.SHOULDER2_2)) outputData[outIdx] |= 0x01;
|
||||
|
||||
outputData[++outIdx] = (hidReport.GetButton(Joycon.Button.HOME)) ? (byte)1 : (byte)0;
|
||||
outputData[++outIdx] = 0; // no touch pad
|
||||
|
||||
float[] leftStick = hidReport.GetStick(); // 127 is 0
|
||||
outputData[++outIdx] = (byte) (Math.Max(0, Math.Min(255, 127 + leftStick[0] * 127)));
|
||||
outputData[++outIdx] = (byte) (Math.Max(0, Math.Min(255, 127 + leftStick[1] * 127)));
|
||||
outputData[++outIdx] = (byte)(Math.Max(0, Math.Min(255, 127 + leftStick[0] * 127)));
|
||||
outputData[++outIdx] = (byte)(Math.Max(0, Math.Min(255, 127 + leftStick[1] * 127)));
|
||||
|
||||
float[] rightStick = hidReport.GetStick2(); // 127 is 0
|
||||
outputData[++outIdx] = (byte)(Math.Max(0, Math.Min(255, 127 + rightStick[0] * 127)));
|
||||
outputData[++outIdx] = (byte)(Math.Max(0, Math.Min(255, 127 + rightStick[1] * 127)));
|
||||
|
||||
//we don't have analog buttons so just use the Button enums (which give either 0 or 0xFF)
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_LEFT : Joycon.Button.Y)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_DOWN : Joycon.Button.B)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_RIGHT : Joycon.Button.A)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_UP : Joycon.Button.X)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_LEFT : Joycon.Button.Y)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_DOWN : Joycon.Button.B)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_RIGHT : Joycon.Button.A)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.DPAD_UP : Joycon.Button.X)) ? (byte)0xFF : (byte)0;
|
||||
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT) : (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN) : (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT) : (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP) : (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT) : (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN) : (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapAB ? (isLeft ? Joycon.Button.A : Joycon.Button.DPAD_RIGHT) : (isLeft ? Joycon.Button.B : Joycon.Button.DPAD_DOWN))) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(!swapXY ? (isLeft ? Joycon.Button.X : Joycon.Button.DPAD_UP) : (isLeft ? Joycon.Button.Y : Joycon.Button.DPAD_LEFT))) ? (byte)0xFF : (byte)0;
|
||||
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER2_1 : Joycon.Button.SHOULDER_1)) ? (byte)0xFF : (byte)0;
|
||||
outputData[++outIdx] = (hidReport.GetButton(isLeft ? Joycon.Button.SHOULDER_1 : Joycon.Button.SHOULDER2_1)) ? (byte)0xFF : (byte)0;
|
||||
|
|
Loading…
Add table
Reference in a new issue