public static void WriteResourceTable(MjoScript script, Stream s) { using var writer = new CsvWriter(new StreamWriter(s), CultureInfo.InvariantCulture); writer.WriteField("Key"); writer.WriteField("Value"); writer.NextRecord(); foreach ((string key, string value) in script.ExternalizedStrings.OrderBy(pair => int.Parse(pair.Key[1..])))
public static MjoScript DisassembleScript(BinaryReader reader) { string signature = reader.ReadSizedString(16); bool isEncrypted = signature == "MajiroObjX1.000\0"; Debug.Assert(isEncrypted ^ (signature == "MajiroObjV1.000\0")); uint entryPointOffset = reader.ReadUInt32(); uint readMarkSize = reader.ReadUInt32(); int functionCount = reader.ReadInt32(); var functionIndex = new List <FunctionIndexEntry>(functionCount); for (int i = 0; i < functionCount; i++) { functionIndex.Add(new FunctionIndexEntry { NameHash = reader.ReadUInt32(), Offset = reader.ReadUInt32() }); } int byteCodeSize = reader.ReadInt32(); var byteCode = reader.ReadBytes(byteCodeSize); if (isEncrypted) { Crc.Crypt32(byteCode); } using var ms = new MemoryStream(byteCode); var script = new MjoScript { Representation = MjoScriptRepresentation.InstructionList, Instructions = new List <Instruction>(), EntryPointOffset = entryPointOffset, FunctionIndex = functionIndex, EnableReadMark = readMarkSize != 0 }; try { DisassembleByteCode(ms, script.Instructions); } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Failed to disassemble script: " + e.Message); if (script.Instructions.Any()) { Console.WriteLine("Last parsed instructions:"); for (int i = Math.Max(0, script.Instructions.Count - 5); i < script.Instructions.Count; i++) { PrintInstruction(script.Instructions[i], IColoredWriter.Console); } } throw; } script.SanityCheck(); return(script); }
public static void PrintScript(MjoScript script, IColoredWriter writer) { writer.ForegroundColor = ConsoleColor.DarkYellow; writer.Write("readmark "); writer.ForegroundColor = script.EnableReadMark ? ConsoleColor.Green : ConsoleColor.Red; writer.WriteLine(script.EnableReadMark ? "enable" : "disable"); //writer.ForegroundColor = ConsoleColor.DarkYellow; //writer.Write("entrypoint "); //writer.ForegroundColor = ConsoleColor.Blue; //writer.WriteLine($"${script.EntryPointFunction.NameHash:x8}"); writer.ResetColor(); writer.WriteLine(); switch (script.Representation) { case MjoScriptRepresentation.ControlFlowGraph: bool first = true; foreach (var function in script.Functions) { if (!first) { writer.WriteLine(); } first = false; PrintFunction(function, writer); } break; default: foreach (var functionEntry in script.FunctionIndex) { writer.ForegroundColor = ConsoleColor.DarkYellow; writer.Write("index "); writer.ForegroundColor = ConsoleColor.Blue; writer.Write($"${functionEntry.NameHash:x8} "); writer.ForegroundColor = ConsoleColor.DarkGray; writer.Write($"0x{functionEntry.Offset:x4}"); if (functionEntry.Offset == script.EntryPointOffset) { writer.ForegroundColor = ConsoleColor.DarkYellow; writer.Write(" entrypoint"); } writer.ResetColor(); writer.WriteLine(); } writer.WriteLine(); foreach (var instruction in script.Instructions) { PrintInstruction(instruction, writer); } break; } }