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); } } } }
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); }
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()); }
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()); }
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; }
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}"); } } }
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); }
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}"); } }
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); }
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); }
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); } } }
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); }
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)); } } }
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); }
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); }); } }
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); } } }