Example #1
0
 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..])))
Example #2
0
        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);
        }
Example #3
0
        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;
            }
        }