Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions GT7Plugin/Cryptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,36 @@ namespace GT7Plugin
/// <summary>
/// Used to decrypt packets from GT7's Simulator Interface.
/// </summary>
public class Cryptor
public class SimulatorInterfaceCryptorGT7
{
private Salsa20 _salsa;

public const string Key = "Simulator Interface Packet GT7 ver 0.0";

public Cryptor()
public uint XorKey { get; set; } = 0xDEADBEAF;

public SimulatorInterfaceCryptorGT7(SimInterfacePacketType packetType)
{
_salsa = new Salsa20(Encoding.ASCII.GetBytes(Key), 0x26);
switch (packetType)
{
case SimInterfacePacketType.PacketType2:
XorKey = 0xDEADBEEF;
break;

case SimInterfacePacketType.PacketType3:
XorKey = 0x55FABB4F;
break;
}

_salsa = new Salsa20(Encoding.ASCII.GetBytes(Key), Key.Length);
}

public void Decrypt(Span<byte> bytes)
{
_salsa.Set(0);

int iv1 = BinaryPrimitives.ReadInt32LittleEndian(bytes.Slice(0x40)); // Seed IV is always located there
int iv2 = (int)(iv1 ^ 0xDEADBEAF); // Notice DEADBEAF, not DEADBEEF
int iv2 = (int)(iv1 ^ XorKey);

Span<byte> iv = stackalloc byte[8];
BinaryPrimitives.WriteInt32LittleEndian(iv, iv2);
Expand Down
4 changes: 3 additions & 1 deletion GT7Plugin/GT7Output.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace GT7Plugin
{
internal class GT7Output
internal struct GT7Output
{
public float Yaw;
public float Pitch;
Expand All @@ -24,5 +24,7 @@ internal class GT7Output
public float OnTrack;
public float IsPaused;
public float Loading;
public float InRace;
public float CentripetalAcceleration;
}
}
109 changes: 39 additions & 70 deletions GT7Plugin/GT7Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Net.Sockets;
using System.Numerics;
using System.Reflection;

Expand All @@ -17,9 +18,11 @@ namespace GT7Plugin
{
[Export(typeof(Game))]
[ExportMetadata("Name", "Gran Turismo 7")]
[ExportMetadata("Version", "1.3")]
[ExportMetadata("Version", "1.4")]
public class GT7Plugin : Game
{
#region Standard Properties

private IProfileManager controller;
private IMainFormDispatcher dispatcher;

Expand All @@ -33,90 +36,57 @@ public class GT7Plugin : Game

public string AUTHOR => "Trevor Jones";

public Stream Logo => ResourceHelper.GetStream("logo.png");

public Stream SmallLogo => ResourceHelper.GetStream("recent.png");

public Stream Background => ResourceHelper.GetStream("wide.png");

public string Description => ResourceHelper.GetString("description.html");
public string Description => ResourceHelper.Description;
public Stream Logo => ResourceHelper.Logo;
public Stream SmallLogo => ResourceHelper.SmallLogo;
public Stream Background => ResourceHelper.Background;

private string defProfilejson => ResourceHelper.GetString("Default.yawglprofile");
public List<Profile_Component> DefaultProfile() => dispatcher.JsonToComponents(ResourceHelper.DefaultProfile);
public LedEffect DefaultLED() => new LedEffect(EFFECT_TYPE.KNIGHT_RIDER, 0, [YawColor.WHITE], 0);
public Dictionary<string, ParameterInfo[]> GetFeatures() => null;


public Type GetConfigBody() => typeof(Config);

public LedEffect DefaultLED() => dispatcher.JsonToLED(defProfilejson);
private Config settings;

public List<Profile_Component> DefaultProfile() => dispatcher.JsonToComponents(defProfilejson);
#endregion

private UDPListener listener;
private Cryptor cryptor;
private FieldInfo[] fields = typeof(GT7Output).GetFields();
private bool _seenPacket = false;
private Vector3 _previous_local_velocity = new Vector3(0, 0, 0);
private const float _samplerate = 1 / 60f;



public void Exit() => listener?.Stop();

public Dictionary<string, ParameterInfo[]> GetFeatures() => new();
public string[] GetInputData() => InputHelper.GetValues<GT7Output>(default).Keys();

public string[] GetInputData() => fields.Select(f => f.Name).ToArray();

private int inputPort = 33740;


public void Init()
{


inputPort = dispatcher.GetConfigObject<Config>().Port;
listener = new UDPListener(inputPort);
cryptor = new Cryptor();
this.settings = dispatcher.GetConfigObject<Config>();
listener = new UDPListener(SimInterfacePacketType.PacketType2, settings.Port);
listener.OnPacketReceived += Listener_OnPacketReceived;
suspStopwatch.Restart();
}

private void Listener_OnPacketReceived(object sender, byte[] buffer)
{
cryptor.Decrypt(buffer);
var sp = new SimulatorPacket();
sp.Read(buffer);

if (sp.Flags.HasFlag(SimulatorFlags.CarOnTrack) && !sp.Flags.HasFlag(SimulatorFlags.Paused) && !sp.Flags.HasFlag(SimulatorFlags.LoadingOrProcessing))
// after race finishes game still sends telemetry, checking the laps to detect when actually racing
bool preRace = sp.LapsInRace == 0 && sp.LapCount == 0;
bool raceFinished = sp.LapCount > sp.LapsInRace;
bool inRace = !preRace && !raceFinished;

if (inRace && sp.Flags.HasFlag(SimulatorFlags.CarOnTrack) && !sp.Flags.HasFlag(SimulatorFlags.Paused) && !sp.Flags.HasFlag(SimulatorFlags.LoadingOrProcessing))
{
ReadFunction(sp);

}

_seenPacket = _seenPacket || true;

}

private void ReadFunction(SimulatorPacket sp)
{
var Q = new Quaternion(new Vector3(sp.RotationX, sp.RotationY, sp.RotationZ), sp.RelativeOrientationToNorth);
var local_velocity = Maths.WorldtoLocal(Q, new Vector3(sp.VelocityX, sp.VelocityY, sp.VelocityZ));


var sway = CalculateCentripetalAcceleration(local_velocity, new Vector3(sp.AngularVelocityX, sp.AngularVelocityY, sp.AngularVelocityZ));
var surge = 0f;
var heave = 0f;

if (_seenPacket)
{
var delta_velocity = local_velocity - _previous_local_velocity;

surge = delta_velocity.Z / _samplerate / 9.81f;
heave = delta_velocity.Y / _samplerate / 9.81f;
}



_previous_local_velocity = local_velocity;


var (pitch, yaw, roll) = Q.ToPitchYawRoll(); // Q.ToEuler(true);


var (pitch, yaw, roll) = sp.Rotation.ToPitchYawRoll();

bool updateSusp = false;

Expand All @@ -129,17 +99,19 @@ private void ReadFunction(SimulatorPacket sp)
var output = new GT7Output()
{
Yaw = yaw,
Pitch = pitch,
Pitch = -pitch,
Roll = roll,
Sway = sway,
Surge = surge,
Heave = heave,
Sway = sp.Sway ?? 0f,
Surge = -sp.Surge ?? 0f,
Heave = sp.Heave ?? 0f,
Kph = sp.MetersPerSecond * 3.6f,
MaxKph = sp.CalculatedMaxSpeed * 3.6f,
RPM = sp.EngineRPM,
OnTrack = sp.Flags.HasFlag(SimulatorFlags.CarOnTrack) ? 1 : 0,
IsPaused = sp.Flags.HasFlag(SimulatorFlags.Paused) ? 1 : 0,
Loading = sp.Flags.HasFlag(SimulatorFlags.LoadingOrProcessing) ? 1 : 0
Loading = sp.Flags.HasFlag(SimulatorFlags.LoadingOrProcessing) ? 1 : 0,
InRace = sp.LapsInRace > 0 ? 1 : 0,
CentripetalAcceleration = CalculateCentripetalAcceleration(Maths.WorldtoLocal(sp.Rotation, sp.Velocity), sp.AngularVelocity)
};

if (updateSusp)
Expand All @@ -150,10 +122,10 @@ private void ReadFunction(SimulatorPacket sp)
output.TireRR_SusHeight = sp.TireRR_SusHeight;
}

for (int i = 0; i < fields.Length; i++)
{
controller.SetInput(i, Convert.ToSingle(fields[i].GetValue(output)));
}

foreach (var (i, key, value) in InputHelper.GetValues(output).WithIndex())
controller.SetInput(i, value);

}

public void PatchGame()
Expand All @@ -175,9 +147,6 @@ public float CalculateCentripetalAcceleration(Vector3 velocity, Vector3 angularV

}

public Type GetConfigBody()
{
return typeof(Config);
}

}
}
4 changes: 2 additions & 2 deletions GT7Plugin/GT7Plugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AssemblyVersion>1.3.0.0</AssemblyVersion>
<FileVersion>1.3.0.0</FileVersion>
<AssemblyVersion>1.4.0.0</AssemblyVersion>
<FileVersion>1.4.0.0</FileVersion>
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
</PropertyGroup>

Expand Down
Loading