// See https://aka.ms/new-console-template for more information using System.Text.Json; using System.Text.Json.Nodes; using CHUNITHM_Patch_Finder; using Reloaded.Memory.Sigscan; using Reloaded.Memory.Sigscan.Definitions.Structs; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; if (args.Length < 1) { Console.WriteLine($"Usage: {Environment.ProcessPath} "); Environment.Exit(22); // EINVAL } var deserializer = new DeserializerBuilder() .WithNamingConvention(LowerCaseNamingConvention.Instance) .Build(); var patches = deserializer.Deserialize( File.ReadAllText("patterns.yaml")); var binary = File.ReadAllBytes(args[0]); var scanner = new Scanner(binary); var exportedPatches = new JsonArray(); // Other patches foreach (var patch in patches) { var signatures = patch.Patches.Select(p => p.Signature ?? patch.Signature).ToList(); if (signatures.Any(s => s == null)) { Console.WriteLine($"[ERROR] No signature provided for patch {patch.Name}"); continue; } var matches = signatures .Zip(scanner.FindPatternsCached(signatures)!) .GroupBy(p => p.First) .ToDictionary(g => g.Key, g => g.First().Second); if (matches.Any(p => !p.Value.Found)) { Console.WriteLine($"No offset found for patch {patch.Name}"); continue; } var patchObject = new JsonObject() { { "name", patch.Name }, }; if (patch.Tooltip != null) patchObject.Add("tooltip", patch.Tooltip); else if (patch.Danger != null) patchObject.Add("danger", patch.Danger); var patchArray = new JsonArray(); foreach (var p in patch.Patches) { var signature = (p.Signature ?? patch.Signature)!; var off = new JsonArray(); var on = new JsonArray(); foreach (var b in p.Off) off.Add(b); foreach (var b in p.On) on.Add(b); var pObject = new JsonObject() { { "offset", matches[signature].Offset + p.Offset }, { "off", off }, { "on", on }, }; patchArray.Add(pObject); } patchObject.Add("patches", patchArray); exportedPatches.Add(patchObject); } // max track count patch if (Path.GetFileName(args[0]) == "chusanApp.exe") { var offset = scanner .FindPatterns([ "E8 ?? ?? ?? ?? 8D ?? 78 8B F0", // SDHD 2.00-2.20 "E8 ?? ?? ?? ?? 8B 4C 24 24 8B F0", // SDGS 1.30 ]) .FirstOrDefault(o => o.Found, new PatternScanResult(-1)); if (offset.Found) { var trackCountRelativeAddress = BitConverter.ToInt32(binary, offset.Offset + 1); var trackCountAddress = offset.Offset + 5 + trackCountRelativeAddress; Console.WriteLine($"Found track count function at {trackCountAddress:X}"); var patch = new JsonObject { { "type", "number" }, { "name", "Maximum tracks" }, { "offset", trackCountAddress + 1 }, { "size", 4 }, { "min", 3 }, { "max", 12 } }; exportedPatches.Add(patch); } else { Console.WriteLine("Track count function not found"); } } File.WriteAllText( "patches.json", JsonSerializer.Serialize(exportedPatches, new JsonSerializerOptions(JsonSerializerOptions.Default) { WriteIndented = true })); Console.WriteLine("Wrote patches to patches.json");