diff --git a/DMDisassembler/Program.cs b/DMDisassembler/Program.cs index b5791d7d95..58be41ff93 100644 --- a/DMDisassembler/Program.cs +++ b/DMDisassembler/Program.cs @@ -86,6 +86,7 @@ static void Main(string[] args) { case "d": case "decompile": Decompile(split); break; case "stats": Stats(GetArg()); break; + case "dump-types": DumpTypes(); break; case "test-all": TestAll(); break; case "dump-all": DumpAll(); break; case "help": { @@ -119,6 +120,7 @@ private static void PrintHelp([CanBeNull] string command) { Console.WriteLine("Prints various statistics. Usage: stats [type]"); Console.WriteLine("Options for [type]:"); Console.WriteLine("procs-by-type : Prints the number of proc declarations (not overrides) on each type in descending order"); + Console.WriteLine("subtypes-by-type : Prints the number of direct-descendant subtypes on each type in descending order"); Console.WriteLine("opcode-count : Prints the number of occurrences for each opcode in descending order"); break; } @@ -139,6 +141,7 @@ void AllCommands() { Console.WriteLine("list procs|globals : List all globals, or all procs on a selected type"); Console.WriteLine("decompile|d [name] : Decompiles the proc on the selected type"); Console.WriteLine("stats [type] : Prints various stats about the game. Use \"help stats\" for more info"); + Console.WriteLine("dump-types : Writes a list of every type to a file"); Console.WriteLine("dump-all : Decompiles every proc and writes the output to a file"); Console.WriteLine("test-all : Tries to decompile every single proc to check for issues with this disassembler; not for production use"); } @@ -155,6 +158,10 @@ private static void Stats([CanBeNull] string statType) { ProcsByType(); return; } + case "subtypes-by-type": { + SubtypesByType(); + return; + } case "opcode-count": { OpcodeCount(); return; @@ -189,6 +196,40 @@ void ProcsByType() { } } + void SubtypesByType() { + Console.WriteLine("Counting all subtypes by type. This may take a moment."); + Dictionary typeIdToSubtypeCount = new Dictionary(TypesById.Count); + + foreach (DMType type in TypesById) { + var parent = type.Json.Parent; + if (parent is null) continue; + + if (typeIdToSubtypeCount.TryGetValue(parent.Value, out var count)) { + typeIdToSubtypeCount[parent.Value] = count + 1; + } else { + typeIdToSubtypeCount[parent.Value] = 1; + } + } + + var outputFile = Path.ChangeExtension(JsonFile, ".txt")!; + var name = Path.GetFileName(outputFile); + var path = Path.GetDirectoryName(outputFile)!; + outputFile = Path.Combine(path, $"__od_subtypes-by-type_{name}"); + using StreamWriter writer = new StreamWriter(outputFile, append: false, encoding: Encoding.UTF8, bufferSize: 65536); + + writer.WriteLine("Type: Subtype Count"); + foreach (var pair in typeIdToSubtypeCount.OrderByDescending(kvp => kvp.Value)) { + var type = TypesById[pair.Key]; + if (pair.Key == 0) { + writer.WriteLine($": {pair.Value:n0}"); + } else { + writer.WriteLine($"{type.Path}: {pair.Value:n0}"); + } + } + + Console.WriteLine($"Successfully dumped subtypes-by-type to {outputFile}"); + } + void OpcodeCount() { Console.WriteLine("Counting all opcode occurrences. This may take a moment."); Dictionary opcodeToCount = new Dictionary(); @@ -374,6 +415,22 @@ private static int TestAll() { return errored; } + private static void DumpTypes() { + Console.WriteLine("Dumping all types. This may take a moment."); + + var outputFile = Path.ChangeExtension(JsonFile, ".txt")!; + var name = Path.GetFileName(outputFile); + var path = Path.GetDirectoryName(outputFile)!; + outputFile = Path.Combine(path, $"__od_types_{name}"); + using StreamWriter writer = new StreamWriter(outputFile, append: false, encoding: Encoding.UTF8, bufferSize: 65536); + + foreach (DMType type in TypesById) { + writer.WriteLine(type.Path); + } + + Console.WriteLine($"Successfully dumped {TypesById.Count:n0} types to {outputFile}"); + } + private static void DumpAll() { Console.WriteLine("Dumping all procs. This may take a moment."); int errored = 0, all = 0; @@ -394,7 +451,7 @@ private static void DumpAll() { ++all; } - var procCount = errored > 0 ? $"{all - errored}/{all} ({errored} failed procs)" : $"all {all}"; + var procCount = errored > 0 ? $"{(all - errored):n0}/{all:n0} ({errored:n0} failed procs)" : $"all {all:n0}"; Console.WriteLine($"Successfully dumped {procCount} procs to {outputFile}"); }