예제 #1
0
        internal static void FirstParse(BinaryReader br, DisassemblyTask task)
        {
            InitRelocationLabels(br, task);

            foreach (Section s in task.Sections.Values)
            {
                if (s.IsCode)
                {
                    FirstParse(br, s);
                }
            }
            //complete the label list
            RemoveFalseFunctions();

            List <(N64Ptr start, N64Ptr end)> textSections = GetTextSectionRanges(task);

            foreach (var addr in RelocationLabels.Values)
            {
                if (!Symbols.ContainsKey(addr))
                {
                    if (textSections.Exists(x => x.start >= addr && addr < x.end))
                    {
                        Symbols[addr] = new Label(Label.Type.LBL, addr);
                    }
                    else
                    {
                        Symbols[addr] = new Label(Label.Type.VAR, addr);
                    }
                }
            }
        }
예제 #2
0
        private static void OverlayPreprocess(DisassemblyTask task, Stream file, OverlayRecord ovlInfo)
        {
            var overlay = new Overlay();

            if (ovlInfo.VRom.Size != 0)
            {
                BinaryReader br = new BinaryReader(file);
                overlay = new Overlay(br);
            }
            task.Relocations = overlay.Relocations;

            N64Ptr fstart = task.VRam.Start;

            Section text   = new Section("text", fstart, fstart, overlay.TextSize, 0, true);
            Section data   = new Section("data", fstart, text.VRam + text.Size, overlay.DataSize, 0);
            Section rodata = new Section("rodata", fstart, data.VRam + data.Size, overlay.RodataSize, 0);
            long    off    = task.VRam.Start + task.VRom.Size;

            task.HeaderAndReloc = new N64PtrRange(task.VRam.Start + overlay.header_offset, off);
            Section bss = new Section("bss", fstart, off, overlay.BssSize, 0);

            task.Sections.Values.Add(text);
            task.Sections.Values.Add(data);
            task.Sections.Values.Add(rodata);
            task.Sections.Values.Add(bss);
        }
예제 #3
0
        static void DisassembleRom(RomVersion version, string path, Func <DisassemblyTask, bool> filter)
        {
            Console.WriteLine($"{version} {path}");
            Console.Write("Initializing task list:  ");
            Rom rom = Rom.New(path, version);
            List <DisassemblyTask> taskList = DisassemblyTask.CreateTaskList(rom);

            taskList = taskList.Where(filter).Where(x => x.VRom.End > 0).ToList();

            if (taskList.Count == 0)
            {
                Console.WriteLine("Error: No tasks to process!");
                return;
            }

            Console.WriteLine("DONE!");
            Console.Write($"Loading symbol table from file: ");
            LoadFunctionDatabase(version);

            Console.WriteLine("DONE!");
            Console.WriteLine("Disassembling files: ");

            Stream getFile(FileAddress x) => rom.Files.GetFile(x);

            DisassembleTasks(rom.Version, taskList, getFile);
            DumpFoundFunctions(rom.Version, Disassemble.GetFunctions());
        }
예제 #4
0
        static void DisassembleRom(RomVersion ver, string path)
        {
            Rom rom;

            Console.Write("Initializing task list:  ");
            if (ver.Game == Game.OcarinaOfTime)
            {
                rom = new ORom(path, ver);
            }
            else
            {
                rom = new MRom(path, ver);
            }

            List <DisassemblyTask> taskList = DisassemblyTask.CreateTaskList(rom);

            taskList = taskList.Where(x => x.VRom.End > 0).ToList();
            Console.WriteLine("DONE!");
            Console.Write($"Building symbol table: ");
            Stream getFile(FileAddress x) => rom.Files.GetFile(x);

            LoadFunctionDatabase(ver);
            GetSymbols(taskList, rom.Version, getFile);

            Console.WriteLine("DONE!");
            Console.WriteLine("Disassembling files: ");

            DisassembleTasks(rom.Version, taskList, getFile);
            DumpFoundFunctions(rom.Version, Disassemble.GetFunctions());
        }
예제 #5
0
        private static void InitRelocationLabels(BinaryReader br, DisassemblyTask task)
        {
            N64Ptr hi_addr = 0;

            Rel_Parse = true;

            N64Ptr start = task.VRam.Start;
            List <(N64Ptr start, N64Ptr end)> textSections = GetTextSectionRanges(task);

            foreach (var reloc in task.Relocations)
            {
                N64Ptr relAddr = task.VRam.Start + reloc.Offset;
                br.BaseStream.Position = reloc.Offset;

                if (reloc.RelocType == Reloc.R_MIPS_HI16 ||
                    reloc.RelocType == Reloc.R_MIPS_LO16)
                {
                    GetOP(br.ReadBigInt32());
                    if (reloc.RelocType == Reloc.R_MIPS_HI16)
                    {
                        hi_addr = relAddr;
                    }
                    else if (reloc.RelocType == Reloc.R_MIPS_LO16)
                    {
                        //Fixes bug where gcc generates a R_MIPS_HI16
                        //after LO16 that is part of the same chain of LO16s
                        if (!RelocationLabels.ContainsKey(hi_addr))
                        {
                            RelocationLabels[hi_addr] = Rel_Label_Addr;
                        }
                        RelocationLabels[relAddr] = Rel_Label_Addr;
                    }
                }

                else if (reloc.RelocType == Reloc.R_MIPS32)
                {
                    N64Ptr ptr = br.ReadBigInt32();

                    if (textSections.Exists(x => x.start >= ptr && ptr < x.end))
                    {
                        AddLabel(ptr, false);
                    }
                    else
                    {
                        Symbols[ptr] = new Label(Label.Type.VAR, ptr);
                    }
                }
            }

            Rel_Parse = false;
            br.BaseStream.Position = 0;
        }
예제 #6
0
        static void OverlayTest(RomVersion ver, string testOvl)
        {
            PathUtil.TryGetRomLocation(ver, out string path);
            Rom rom   = Rom.New(path, ver);
            var tasks = DisassemblyTask.CreateTaskList(rom);

            Disassemble.PrintRelocations = true;
            Disassemble.GccOutput        = true;

            var task = tasks.SingleOrDefault(x => x.Name == testOvl || x.Name == $"ovl_{testOvl}");

            if (task == null)
            {
                Console.WriteLine("Cannot find overlay");
                return;
            }
            //var taskbss = tasks.Where(x => x.Sections["bss"]?.Size > 0).ToList();

            var reader = new BinaryReader(rom.Files.GetFile(task.VRom));

            //using (StreamWriter sw = new StreamWriter("__test.txt"))
            //{
            //    foreach (var rel in task.Map.Relocations.Where(x => x.SectionId == Overlay.RelocationWord.Section.text))
            //    {
            //        reader.BaseStream.Position = rel.Offset;
            //        sw.WriteLine($"{rel.Offset:X6}: {rel.RelocType}  {GetOP(reader.ReadBigInt32())}");
            //    }
            //}

            using (StreamWriter sw = new StreamWriter($"__{testOvl}.txt"))
            {
                BinaryReader br = new BinaryReader(rom.Files.GetFile(task.VRom));
                Disassemble.FirstParse(br, task);
                if (Disassemble.GccOutput)
                {
                    sw.WriteLine("#include <mips.h>");
                    sw.WriteLine(".set noreorder");
                    sw.WriteLine(".set noat");
                    sw.WriteLine();
                }
                Disassemble.Task(sw, br, task);
            }

            using (StreamWriter sw = new StreamWriter($"__{testOvl}_f.txt"))
            {
                foreach (var item in Disassemble.Symbols.OrderBy(x => x.Key))
                {
                    sw.WriteLine($"{item.Value.ToString()} = 0x{item.Key}");
                }
            }
        }
예제 #7
0
        private static List <(N64Ptr start, N64Ptr end)> GetTextSectionRanges(DisassemblyTask task)
        {
            List <(N64Ptr start, N64Ptr end)> textSections = new List <(N64Ptr start, N64Ptr end)>();

            foreach (var section in task.Sections.Values)
            {
                if (section.IsCode)
                {
                    textSections.Add((section.VRam, section.Size));
                }
            }

            return(textSections);
        }
예제 #8
0
 internal static void Task(StreamWriter sw, BinaryReader br, DisassemblyTask task)
 {
     if (MipsToC)
     {
         var header = new string[]
         {
             ".include \"macro.inc\"",
             "",
             "# assembler directives",
             ".set noat      # allow manual use of $at",
             ".set noreorder # don't insert nops after branches",
             ".set gp=64     # allow use of 64-bit general purposee registers",
             ""
         };
         foreach (var item in header)
         {
             sw.WriteLine(item);
         }
     }
     else if (GccOutput)
     {
         sw.WriteLine("#include <mips.h>");
         sw.WriteLine(".set noreorder");
         sw.WriteLine(".set noat");
         sw.WriteLine();
     }
     foreach (Section section in task.Sections.Values.OrderBy(x => x.VRam))
     {
         if (section.IsCode)
         {
             TextDisassembly(sw, br, section);
         }
         else if (section.Name == "bss")
         {
             Bss(sw, section);
         }
         else
         {
             DataDisassembly(sw, br, section, task.Relocations.Where(x => x.RelocType == Reloc.R_MIPS32));
         }
     }
     if (MipsToC && task.HeaderAndReloc != null)
     {
         sw.WriteLine();
         sw.WriteLine($".section .rodata");
         sw.WriteLine($"D_{task.HeaderAndReloc.Start}:");
         sw.WriteLine($".incbin \"baserom/{task.Name}\", 0x{task.HeaderAndReloc.Start - task.VRam.Start:X}, 0x{task.HeaderAndReloc.Size:X}");
     }
 }
예제 #9
0
        static void MMDebugTest()
        {
            RomVersion ver = MRom.Build.DBG;

            PathUtil.TryGetRomLocation(ver, out string path);
            Rom             rom  = new MRom(path, ver);
            DisassemblyTask task = null;

            Disassemble.PrintRelocations = true;

            using StreamWriter sw = File.CreateText("__code.txt");
            using BinaryReader br = new BinaryReader(rom.Files.GetFile(task.VRom));
            Disassemble.FirstParse(br, task);
            Disassemble.Task(sw, br, task);
        }
예제 #10
0
        private static DisassemblyTask New(List <JDmaData> dmadata, int index, OverlayRecord ovlInfo,
                                           OvlType nameClass)
        {
            string name = GetTaskName(dmadata, index, ovlInfo, nameClass);

            DisassemblyTask task = new DisassemblyTask()
            {
                Name = name,
                VRam = ovlInfo.VRam,
                VRom = ovlInfo.VRom,
            };

            task.PreparseActions.Add(input => {
                OverlayPreprocess(task, input, ovlInfo);
            });
            return(task);
        }
예제 #11
0
        private static void GetActorSymbolNames(DisassemblyTask task, Rom rom, ActorOverlayRecord ovlRec)
        {
            ActorInit actorInfo = new ActorInit();

            if (ovlRec.VRamActorInfo == 0)
            {
                return;
            }

            N64Ptr  startAddr;
            RomFile file;

            if (ovlRec.VRom.Size == 0)
            {
                file = rom.Files.GetFile(ORom.FileList.code);
                Addresser.TryGetRam(ORom.FileList.code, rom.Version, out int code_start);
                startAddr = (code_start | 0x80000000);
            }
            else
            {
                file      = rom.Files.GetFile(ovlRec.VRom);
                startAddr = ovlRec.VRam.Start;
            }

            file.Stream.Position = ovlRec.VRamActorInfo - startAddr;
            actorInfo            = new ActorInit(new BinaryReader(file));

            BindSymbol(ovlRec.VRamActorInfo, Label.Type.VAR, "InitVars");
            BindSymbol(actorInfo.init_func, Label.Type.FUNC, "Init");
            BindSymbol(actorInfo.draw_func, Label.Type.FUNC, "Draw");
            BindSymbol(actorInfo.update_func, Label.Type.FUNC, "Update");
            BindSymbol(actorInfo.dest_func, Label.Type.FUNC, "Destructor");

            void BindSymbol(N64Ptr ptr, Label.Type type, string name)
            {
                if (ptr != 0)
                {
                    var func = new Label(type, ptr, true)
                    {
                        Name = $"{task.Name}_{name}"
                    };
                    task.Functions.Add(func);
                }
            }
        }
예제 #12
0
        public static DisassemblyTask New(JFileInfo file)
        {
            FileAddress ptr  = file.Ram.Convert();
            var         task = new DisassemblyTask()
            {
                Name = file.File,
                VRam = new N64PtrRange(ptr.Start, ptr.End),
                VRom = file.Rom.Convert()
            };

            foreach (var item in file.Sections)
            {
                var     ram     = item.Ram.Convert();
                Section section = new Section(item.Name, task.VRam.Start, ram.Start, ram.Size, item.Subsection, item.IsCode);
                task.Sections.Values.Add(section);
            }
            return(task);
        }
예제 #13
0
 internal static void Task(StreamWriter sw, BinaryReader br, DisassemblyTask task)
 {
     foreach (Section section in task.Sections.Values.OrderBy(x => x.VRam))
     {
         if (section.IsCode)
         {
             TextDisassembly(sw, br, section);
         }
         else if (section.Name == "bss")
         {
             Bss(sw, section);
         }
         else
         {
             DataDisassembly(sw, br, section, task.Relocations.Where(x => x.RelocType == Reloc.R_MIPS32));
         }
     }
 }
예제 #14
0
        private static DisassemblyTask New(List <JOcaBase.JDmaData> dmadata, Rom rom, int index,
                                           OverlayRecord ovlInfo, OvlType nameClass)
        {
            RomFile      file; //what we're going to disassemble
            BinaryReader FileReader;
            ActorInit    actorInfo = new ActorInit();

            var    overlay   = new Overlay();
            var    dmaRecord = dmadata.SingleOrDefault(x => x.VRomStart == ovlInfo.VRom.Start && ovlInfo.VRom.Start != 0);
            string name      = (dmaRecord != null)? dmaRecord.Filename : $"{nameClass}_{index:X4}";

            if (ovlInfo.VRom.Size != 0)
            {
                file       = rom.Files.GetFile(ovlInfo.VRom);
                FileReader = new BinaryReader(file);
                overlay    = new Overlay(FileReader);
            }

            DisassemblyTask task = new DisassemblyTask()
            {
                Name        = name,
                VRam        = ovlInfo.VRam,
                VRom        = ovlInfo.VRom,
                Relocations = overlay.Relocations
            };

            N64Ptr fstart = task.VRam.Start;

            Section text   = new Section("text", fstart, fstart, overlay.TextSize, 0, true);
            Section data   = new Section("data", fstart, text.VRam + text.Size, overlay.DataSize, 0);
            Section rodata = new Section("rodata", fstart, data.VRam + data.Size, overlay.RodataSize, 0);
            long    off    = ovlInfo.VRam.Start + ovlInfo.VRom.Size;
            Section bss    = new Section("bss", fstart, off, overlay.BssSize, 0);

            task.Sections.Values.Add(text);
            task.Sections.Values.Add(data);
            task.Sections.Values.Add(rodata);
            task.Sections.Values.Add(bss);
            return(task);
        }
예제 #15
0
        private static void GetActorSymbolNames(DisassemblyTask task, Rom rom, ActorOverlayRecord ovlRec)
        {
            if (ovlRec.VRamActorInit == 0)
            {
                return;
            }

            if (ovlRec.VRom.Size == 0)
            {
                RomFile file = rom.Files.GetFile(ORom.FileList.code);
                Addresser.TryGetRam(ORom.FileList.code, rom.Version, out N64Ptr code_start);
                N64Ptr startAddr = code_start;

                GetActorInfoSymbols(task, startAddr, ovlRec.VRamActorInit, file);
            }
            else
            {
                task.PreparseActions.Add(file => {
                    GetActorInfoSymbols(task, ovlRec.VRam.Start, ovlRec.VRamActorInit, file);
                });
            }
        }
예제 #16
0
        private static void GetActorInfoSymbols(DisassemblyTask task, N64Ptr startAddr, N64Ptr vramActorInfo, Stream file)
        {
            file.Position = vramActorInfo - startAddr;
            ActorInit actorInfo = new ActorInit(new BinaryReader(file));

            BindSymbol(vramActorInfo, Label.Type.VAR, "InitVars");
            BindSymbol(actorInfo.init_func, Label.Type.FUNC, "Init");
            BindSymbol(actorInfo.draw_func, Label.Type.FUNC, "Draw");
            BindSymbol(actorInfo.update_func, Label.Type.FUNC, "Update");
            BindSymbol(actorInfo.dest_func, Label.Type.FUNC, "Destructor");

            void BindSymbol(N64Ptr ptr, Label.Type type, string name)
            {
                if (ptr != 0)
                {
                    var func = new Label(type, ptr, true, Disassemble.MipsToC)
                    {
                        Name = $"{task.Name}_{name}"
                    };
                    task.Functions.Add(func);
                }
            }
        }