using System.Runtime.InteropServices;
using System.Text.Json;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Plugins;
internal static class CruiseControlAcceptance
{
internal static async Task LoadAsync(int pid,string package,string report)
{
package=Path.GetFullPath(package);report=Path.GetFullPath(report);if(File.Exists(report))throw new IOException("Use a fresh original SCO control report.");
using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(20));var token=timeout.Token;
var hello=await new NavigationPipeClient(pid).CallAsync(new{op="describe"},token);
if(hello.GetProperty("processId").GetInt32()!=pid||hello.GetProperty("gameSha256").GetString()!=NativeSystemLocationReader.GameSha256)
throw new InvalidDataException("Original SCO control game identity differs.");
var library=NativeLibrary.Load(Path.Combine(package,"XFEEDInteraction.dll"));
var test=Marshal.GetDelegateForFunctionPointer<Probe>(NativeLibrary.GetExport(library,"XFECruiseControlSelfTest"));
var start=Marshal.GetDelegateForFunctionPointer<Start>(NativeLibrary.GetExport(library,"XFEInteractionStart"));
var masks=Enumerable.Range(0,8).Select(_=>test()).ToArray();
if(masks.Any(mask=>mask!=4095)||start(0)!=0||start(nuint.MaxValue)!=0)throw new InvalidDataException("Original SCO controller fixtures failed.");
await RuntimeInteractionModule.LoadAsync(pid,NativeSystemLocationReader.GameSha256,hello.GetProperty("owningThread").GetInt32(),package,token);
var observed=await new NavigationPipeClient(pid,NativeCruiseControlChannel.Service).CallAsync(new{op="watch"},token);
await File.WriteAllTextAsync(report,JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,pid,loadProtocolPassed=true,fixtureMasks=masks,
actualScoSampleReady=observed.GetProperty("sampleReady").GetBoolean(),controlQualified=observed.GetProperty("overchargeControlQualified").GetBoolean(),
observed,inputsSentByProbe=0},ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{pid,loadProtocolPassed=true,controlQualified=observed.GetProperty("overchargeControlQualified").GetBoolean(),report,inputsSentByProbe=0}));
}
internal static async Task ReadAsync(int pid,string report,bool watch)
{
if(File.Exists(report))throw new IOException("Preserve existing original SCO evidence.");
var observed=await new NavigationPipeClient(pid,NativeCruiseControlChannel.Service).CallAsync(new{op=watch?"watch":"read"});
await File.WriteAllTextAsync(report,JsonSerializer.Serialize(observed,ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{pid,report,inputsSentByProbe=0}));
}
internal static async Task DeactivateAsync(int pid,string service,string report)
{
if(service is not("CruiseControl0514a" or "CruiseControl0514b" or "CruiseControl0514c" or "CruiseControl0514d")||File.Exists(report))throw new IOException("Use a known module and preserve previous SCO evidence.");
var observed=await new NavigationPipeClient(pid,service).CallAsync(new{op="deactivate"});
if(observed.GetProperty("enabled").GetBoolean()||observed.GetProperty("owned").GetBoolean())throw new InvalidDataException("Original SCO hook did not deactivate.");
await File.WriteAllTextAsync(report,JsonSerializer.Serialize(observed,ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{pid,service,report,deactivated=true,inputsSentByProbe=0}));
}
[UnmanagedFunctionPointer(CallingConvention.Winapi)]private delegate uint Probe();
[UnmanagedFunctionPointer(CallingConvention.Winapi)]private delegate uint Start(nuint thread);
}
using System.Runtime.InteropServices;
using System.Text.Json;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Plugins;
internal static class CruiseControlAcceptance
{
internal static async Task LoadAsync(int pid,string package,string report)
{
package=Path.GetFullPath(package);report=Path.GetFullPath(report);if(File.Exists(report))throw new IOException("Use a fresh original SCO control report.");
using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(20));var token=timeout.Token;
var hello=await new NavigationPipeClient(pid).CallAsync(new{op="describe"},token);
if(hello.GetProperty("processId").GetInt32()!=pid||hello.GetProperty("gameSha256").GetString()!=NativeSystemLocationReader.GameSha256)
throw new InvalidDataException("Original SCO control game identity differs.");
var library=NativeLibrary.Load(Path.Combine(package,"XFEEDInteraction.dll"));
var test=Marshal.GetDelegateForFunctionPointer<Probe>(NativeLibrary.GetExport(library,"XFECruiseControlSelfTest"));
var start=Marshal.GetDelegateForFunctionPointer<Start>(NativeLibrary.GetExport(library,"XFEInteractionStart"));
var masks=Enumerable.Range(0,8).Select(_=>test()).ToArray();
if(masks.Any(mask=>mask!=4095)||start(0)!=0||start(nuint.MaxValue)!=0)throw new InvalidDataException("Original SCO controller fixtures failed.");
await RuntimeInteractionModule.LoadAsync(pid,NativeSystemLocationReader.GameSha256,hello.GetProperty("owningThread").GetInt32(),package,token);
var observed=await new NavigationPipeClient(pid,NativeCruiseControlChannel.Service).CallAsync(new{op="watch"},token);
await File.WriteAllTextAsync(report,JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,pid,loadProtocolPassed=true,fixtureMasks=masks,
actualScoSampleReady=observed.GetProperty("sampleReady").GetBoolean(),controlQualified=observed.GetProperty("overchargeControlQualified").GetBoolean(),
observed,inputsSentByProbe=0},ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{pid,loadProtocolPassed=true,controlQualified=observed.GetProperty("overchargeControlQualified").GetBoolean(),report,inputsSentByProbe=0}));
}
internal static async Task ReadAsync(int pid,string report,bool watch)
{
if(File.Exists(report))throw new IOException("Preserve existing original SCO evidence.");
var observed=await new NavigationPipeClient(pid,NativeCruiseControlChannel.Service).CallAsync(new{op=watch?"watch":"read"});
await File.WriteAllTextAsync(report,JsonSerializer.Serialize(observed,ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{pid,report,inputsSentByProbe=0}));
}
internal static async Task DeactivateAsync(int pid,string service,string report)
{
if(service is not("CruiseControl0514a" or "CruiseControl0514b" or "CruiseControl0514c" or "CruiseControl0514d")||File.Exists(report))throw new IOException("Use a known module and preserve previous SCO evidence.");
var observed=await new NavigationPipeClient(pid,service).CallAsync(new{op="deactivate"});
if(observed.GetProperty("enabled").GetBoolean()||observed.GetProperty("owned").GetBoolean())throw new InvalidDataException("Original SCO hook did not deactivate.");
await File.WriteAllTextAsync(report,JsonSerializer.Serialize(observed,ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{pid,service,report,deactivated=true,inputsSentByProbe=0}));
}
[UnmanagedFunctionPointer(CallingConvention.Winapi)]private delegate uint Probe();
[UnmanagedFunctionPointer(CallingConvention.Winapi)]private delegate uint Start(nuint thread);
}