diff --git a/CHUNITHM-Patch-Finder.csproj b/CHUNITHM-Patch-Finder.csproj
index 0bc1558..03096e7 100644
--- a/CHUNITHM-Patch-Finder.csproj
+++ b/CHUNITHM-Patch-Finder.csproj
@@ -9,6 +9,7 @@
+
diff --git a/Converters/HexNumberJsonConverter.cs b/Converters/HexNumberJsonConverter.cs
new file mode 100644
index 0000000..9712ba6
--- /dev/null
+++ b/Converters/HexNumberJsonConverter.cs
@@ -0,0 +1,18 @@
+using Newtonsoft.Json;
+
+namespace CHUNITHM_Patch_Finder.Converters;
+
+public class HexNumberJsonConverter : JsonConverter
+{
+ public override bool CanRead => false;
+
+ public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer)
+ {
+ writer.WriteRawValue($"0x{value:X2}");
+ }
+
+ public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Models/BemaniPatcherNumberPatch.cs b/Models/BemaniPatcherNumberPatch.cs
new file mode 100644
index 0000000..cbff9ce
--- /dev/null
+++ b/Models/BemaniPatcherNumberPatch.cs
@@ -0,0 +1,14 @@
+namespace CHUNITHM_Patch_Finder.Models;
+
+public class BemaniPatcherNumberPatch : BemaniPatcherPatch
+{
+ public override string Type => "number";
+
+ public required int Offset { get; set; }
+
+ public required int Size { get; set; }
+
+ public required int Min { get; set; }
+
+ public required int Max { get; set; }
+}
\ No newline at end of file
diff --git a/Models/BemaniPatcherPatch.cs b/Models/BemaniPatcherPatch.cs
new file mode 100644
index 0000000..7e1dee9
--- /dev/null
+++ b/Models/BemaniPatcherPatch.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CHUNITHM_Patch_Finder.Models;
+
+[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
+public abstract class BemaniPatcherPatch
+{
+ [JsonProperty(Order = -2)]
+ public abstract string? Type { get; }
+
+ [JsonProperty(Order = -2)]
+ public required string Name { get; set; }
+}
\ No newline at end of file
diff --git a/Models/BemaniPatcherStandardPatch.cs b/Models/BemaniPatcherStandardPatch.cs
new file mode 100644
index 0000000..bc08a49
--- /dev/null
+++ b/Models/BemaniPatcherStandardPatch.cs
@@ -0,0 +1,12 @@
+namespace CHUNITHM_Patch_Finder.Models;
+
+public class BemaniPatcherStandardPatch : BemaniPatcherPatch
+{
+ public override string? Type => null;
+
+ public string? Tooltip { get; set; } = null;
+
+ public string? Danger { get; set; } = null;
+
+ public List Patches { get; set; } = [];
+}
\ No newline at end of file
diff --git a/Models/BemaniPatcherStandardPatchEntry.cs b/Models/BemaniPatcherStandardPatchEntry.cs
new file mode 100644
index 0000000..497098c
--- /dev/null
+++ b/Models/BemaniPatcherStandardPatchEntry.cs
@@ -0,0 +1,10 @@
+namespace CHUNITHM_Patch_Finder.Models;
+
+public class BemaniPatcherStandardPatchEntry
+{
+ public required int Offset { get; set; }
+
+ public required int[] Off { get; set; }
+
+ public required int[] On { get; set; }
+}
\ No newline at end of file
diff --git a/Pattern.cs b/Models/Pattern.cs
similarity index 80%
rename from Pattern.cs
rename to Models/Pattern.cs
index 9dcf2fe..ee7b499 100644
--- a/Pattern.cs
+++ b/Models/Pattern.cs
@@ -1,4 +1,4 @@
-namespace CHUNITHM_Patch_Finder;
+namespace CHUNITHM_Patch_Finder.Models;
public record Pattern
{
diff --git a/PatternPatch.cs b/Models/PatternPatch.cs
similarity index 76%
rename from PatternPatch.cs
rename to Models/PatternPatch.cs
index 0a97e67..61e064c 100644
--- a/PatternPatch.cs
+++ b/Models/PatternPatch.cs
@@ -1,4 +1,4 @@
-namespace CHUNITHM_Patch_Finder;
+namespace CHUNITHM_Patch_Finder.Models;
public record PatternPatch
{
diff --git a/Program.cs b/Program.cs
index d40e4d8..d2a8df3 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,8 +1,9 @@
// See https://aka.ms/new-console-template for more information
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using CHUNITHM_Patch_Finder;
+using CHUNITHM_Patch_Finder.Converters;
+using CHUNITHM_Patch_Finder.Models;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
using Reloaded.Memory.Sigscan;
using Reloaded.Memory.Sigscan.Definitions.Structs;
using YamlDotNet.Serialization;
@@ -22,7 +23,7 @@ var patches =
File.ReadAllText("patterns.yaml"));
var binary = File.ReadAllBytes(args[0]);
var scanner = new Scanner(binary);
-var exportedPatches = new JsonArray();
+var exportedPatches = new List();
// Other patches
foreach (var patch in patches)
@@ -45,42 +46,25 @@ foreach (var patch in patches)
Console.WriteLine($"No offset found for patch {patch.Name}");
continue;
}
-
- var patchObject = new JsonObject()
+
+ var patchObject = new BemaniPatcherStandardPatch
{
- { "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()
+ Name = patch.Name,
+ Tooltip = patch.Tooltip,
+ Danger = patch.Danger,
+ Patches = patch.Patches.Select(p =>
{
- { "offset", matches[signature].Offset + p.Offset },
- { "off", off },
- { "on", on },
- };
-
- patchArray.Add(pObject);
- }
+ var signature = (p.Signature ?? patch.Signature)!;
+
+ return new BemaniPatcherStandardPatchEntry
+ {
+ Offset = matches[signature].Offset + p.Offset,
+ Off = p.Off,
+ On = p.On,
+ };
+ }).ToList()
+ };
- patchObject.Add("patches", patchArray);
exportedPatches.Add(patchObject);
}
@@ -100,15 +84,14 @@ if (Path.GetFileName(args[0]) == "chusanApp.exe")
var trackCountAddress = offset.Offset + 5 + trackCountRelativeAddress;
Console.WriteLine($"Found track count function at {trackCountAddress:X}");
-
- var patch = new JsonObject
+
+ var patch = new BemaniPatcherNumberPatch
{
- { "type", "number" },
- { "name", "Maximum tracks" },
- { "offset", trackCountAddress + 1 },
- { "size", 4 },
- { "min", 3 },
- { "max", 12 }
+ Name = "Maximum tracks",
+ Offset = trackCountAddress + 1,
+ Size = 4,
+ Min = 3,
+ Max = 12,
};
exportedPatches.Add(patch);
@@ -119,12 +102,18 @@ if (Path.GetFileName(args[0]) == "chusanApp.exe")
}
}
+var settings = new JsonSerializerSettings
+{
+ ContractResolver = new DefaultContractResolver
+ {
+ NamingStrategy = new CamelCaseNamingStrategy(),
+ },
+ Converters = [new HexNumberJsonConverter()],
+ Formatting = Formatting.Indented,
+};
File.WriteAllText(
"patches.json",
- JsonSerializer.Serialize(exportedPatches, new JsonSerializerOptions(JsonSerializerOptions.Default)
- {
- WriteIndented = true
- }));
+ JsonConvert.SerializeObject(exportedPatches, settings));
Console.WriteLine("Wrote patches to patches.json");
\ No newline at end of file
diff --git a/patterns.yaml b/patterns.yaml
index 8ec6167..529c82d 100644
--- a/patterns.yaml
+++ b/patterns.yaml
@@ -17,6 +17,7 @@
off: [0x01]
on: [0x00]
- name: "Force 2 channel audio output"
+ tooltip: "May cause bass overload"
signature: "56 E8 ?? ?? ?? ?? 83 C4 04 85 C0 ?? ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ??"
patches:
- offset: 0x0B
@@ -67,17 +68,16 @@
- offset: 0x0D
off: [0x01]
on: [0x00]
-- name: "Disable 1080p check"
- signature: "81 BC 24 B8 02 00 00 80 07 00 00 75 1F 81 BC 24 BC 02 00 00 38 04 00 00 75 12"
- patches:
- - offset: 0x00
+- name: "Bypass 1080p/120Hz monitor check"
+ patches:
+ # 1080p check
+ - signature: "81 BC 24 B8 02 00 00 80 07 00 00 75 1F 81 BC 24 BC 02 00 00 38 04 00 00 75 12"
+ offset: 0x00
off: [0x81, 0xBC, 0x24, 0xB8, 0x02, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x75, 0x1F, 0x81, 0xBC, 0x24, 0xBC, 0x02, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00, 0x75, 0x12]
on: [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90]
-- name: "Force 120Hz check"
- tooltip: "Check to make the 120Hz check always pass (do not use with CVT mode)"
- signature: "50 56 6A 00 FF D7 ?? ?? 74 3F"
- patches:
- - offset: 0x06
+ # 120Hz check
+ - signature: "50 56 6A 00 FF D7 ?? ?? 74 3F"
+ offset: 0x06
off: [0x85, 0xC0]
on: [0xEB, 0x30]
- name: "Bypass LED board check"