[+] ADX HID input

This commit is contained in:
Clansty 2025-01-24 00:22:22 +08:00
parent cdce738543
commit a43999bfa5
No known key found for this signature in database
GPG Key ID: 3A6BE8BAF2EDE134
5 changed files with 263 additions and 1 deletions

View File

@ -47,7 +47,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fody" Version="6.8.1">
<PackageReference Include="Fody" Version="6.9.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@ -125,4 +125,17 @@
<Reference Include="System.Numerics" Private="true" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fody" Version="6.9.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="hidlibrary" Version="3.3.40" />
<PackageReference Include="ILMerge.Fody" Version="1.24.0" />
</ItemGroup>
<ItemGroup>
<Content Include="FodyWeavers.xml" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ILMerge>
<IncludeAssemblies>hidlibrary|Numerics</IncludeAssemblies>
<NamespacePrefix>$AquaMai.Mods$_</NamespacePrefix>
</ILMerge>
</Weavers>

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ILMerge" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="IncludeAssemblies" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A regular expression matching the assembly names to include in merging.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ExcludeAssemblies" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A regular expression matching the assembly names to exclude from merging.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="IncludeResources" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A regular expression matching the resource names to include in merging.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ExcludeResources" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A regular expression matching the resource names to exclude from merging.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="HideImportedTypes" type="xs:boolean" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A switch to control whether the imported types are hidden (made private) or keep their visibility unchanged. Default is 'true'</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="NamespacePrefix" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A string that is used as prefix for the namespace of the imported types.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="FullImport" type="xs:boolean" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A switch to control whether to import the full assemblies or only the referenced types. Default is 'false'</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CompactMode" type="xs:boolean" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>A switch to enable compacting of the target assembly by skipping properties, events and unused methods. Default is 'false'</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A regular expression matching the assembly names to include in merging.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A regular expression matching the assembly names to exclude from merging.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeResources" type="xs:string">
<xs:annotation>
<xs:documentation>A regular expression matching the resource names to include in merging.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeResources" type="xs:string">
<xs:annotation>
<xs:documentation>A regular expression matching the resource names to exclude from merging.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="HideImportedTypes" type="xs:boolean">
<xs:annotation>
<xs:documentation>A switch to control whether the imported types are hidden (made private) or keep their visibility unchanged. Default is 'true'</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="NamespacePrefix" type="xs:string">
<xs:annotation>
<xs:documentation>A string that is used as prefix for the namespace of the imported types.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="FullImport" type="xs:boolean">
<xs:annotation>
<xs:documentation>A switch to control whether to import the full assemblies or only the referenced types. Default is 'false'</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CompactMode" type="xs:boolean">
<xs:annotation>
<xs:documentation>A switch to enable compacting of the target assembly by skipping properties, events and unused methods. Default is 'false'</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -0,0 +1,131 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using AMDaemon;
using AquaMai.Config.Attributes;
using HarmonyLib;
using HidLibrary;
using MelonLoader;
using UnityEngine;
namespace AquaMai.Mods.GameSystem;
[ConfigSection(
en: "Input using ADX HID firmware (do not enable if you are not using ADX's HID firmware, be sure to delete the existing HID related DLL when enabled)",
zh: "使用 ADX HID 固件的自定义输入(如果你没有使用 ADX 的 HID 固件,请不要启用。启用时请务必删除现有 HID 相关 DLL")]
public class HidInput
{
private static HidDevice adxController1P = null;
private static HidDevice adxController2P = null;
private static byte[] inputBuf1P = new byte[32];
private static byte[] inputBuf2P = new byte[32];
private static void HidInputThread()
{
MelonLogger.Msg("[HidInput] ======= HID Input Start =======");
while (true)
{
if (adxController1P != null)
{
var report1P = adxController1P.Read();
if (report1P.Status == HidDeviceData.ReadStatus.Success)
inputBuf1P = report1P.Data;
}
if (adxController2P != null)
{
var report2P = adxController2P.Read();
if (report2P.Status == HidDeviceData.ReadStatus.Success)
inputBuf2P = report2P.Data;
}
#if DEBUG
MelonLogger.Msg("[HidInput] 1P: " + string.Join(",", inputBuf1P));
#endif
// Thread.Sleep(10); // Sleep for a short time to avoid CPU overload
}
}
public static void OnBeforePatch()
{
adxController1P = HidDevices.Enumerate(0x2E3C, 0x5750).FirstOrDefault();
adxController2P = HidDevices.Enumerate(0x2E4C, 0x5750).FirstOrDefault();
if (adxController1P == null)
{
MelonLogger.Msg("[HidInput] Open HID 1P Failed");
}
else
{
MelonLogger.Msg("[HidInput] Open HID 1P OK");
}
if (adxController2P == null)
{
MelonLogger.Msg("[HidInput] Open HID 2P Failed");
}
else
{
MelonLogger.Msg("[HidInput] Open HID 2P OK");
}
if (adxController1P != null || adxController2P != null)
{
Thread hidThread = new Thread(HidInputThread);
hidThread.Start();
}
}
private static bool GetPushedByButton(int playerNo, InputId inputId)
{
if (inputId.Value == "test") return inputBuf1P[13] == 1 || inputBuf2P[13] == 1;
if (inputId.Value == "service") return inputBuf1P[11] == 1 || inputBuf2P[13] == 1;
if (inputId.Value == "select" && playerNo == 0) return inputBuf1P[10] == 1 || inputBuf2P[10] == 1;
if (inputId.Value == "select" && playerNo == 1) return inputBuf1P[12] == 1 || inputBuf2P[12] == 1;
var buf = playerNo == 0 ? inputBuf1P : inputBuf2P;
if (inputId.Value == "button_01") return buf[5] == 1;
if (inputId.Value == "button_02") return buf[4] == 1;
if (inputId.Value == "button_03") return buf[3] == 1;
if (inputId.Value == "button_04") return buf[2] == 1;
if (inputId.Value == "button_05") return buf[9] == 1;
if (inputId.Value == "button_06") return buf[8] == 1;
if (inputId.Value == "button_07") return buf[7] == 1;
if (inputId.Value == "button_08") return buf[6] == 1;
return false;
}
[HarmonyPatch]
public static class Hook
{
public static IEnumerable<MethodBase> TargetMethods()
{
var jvsSwitch = typeof(IO.Jvs).GetNestedType("JvsSwitch", BindingFlags.NonPublic | BindingFlags.Public);
return [jvsSwitch.GetMethod("Execute")];
}
public static bool Prefix(int ____playerNo, InputId ____inputId, ref bool ____isStateOnOld2, ref bool ____isStateOnOld, ref bool ____isStateOn, ref bool ____isTriggerOn, ref bool ____isTriggerOff, KeyCode ____subKey)
{
var flag = GetPushedByButton(____playerNo, ____inputId);
// 不影响键盘
if (!flag) return true;
var isStateOnOld2 = ____isStateOnOld;
var isStateOnOld = ____isStateOn;
if (isStateOnOld2 && !isStateOnOld)
{
return true;
}
____isStateOn = true;
____isTriggerOn = !isStateOnOld;
____isTriggerOff = false;
____isStateOnOld2 = isStateOnOld2;
____isStateOnOld = isStateOnOld;
return false;
}
}
}