private int CheckPointer(int offset) { int ptr = SNES.ToPC(rom.Read24(offset)); if (ptr < 0x80000 || ptr > rom.romSize) { // does not seem to be a valid pointer. return(-1); } ptr -= 4; var str = rom.ReadBlock(ptr, 4); if (!(str[0] == (byte)'t' && str[1] == (byte)'o' && str[2] == (byte)'o' && str[3] == (byte)'l')) { // okay, does not seem legit. return(-1); } return(ptr); }
private static void BuildLibrary() { if (config.VerboseMode) { Console.WriteLine("Building external library..."); Console.WriteLine(); } int fileCount = 0; bool binaryMode = false; var files = Directory.GetFiles("library/", "*.asm", SearchOption.AllDirectories); string fullPath = Path.GetFullPath("library/"); repeat: foreach (var asmFile in files) { int start; int end; string baseFolder = Path.GetDirectoryName(asmFile) + "/"; string fileName = Path.GetFileName(asmFile); string fileNameExt = Path.GetFileNameWithoutExtension(asmFile); string fullFilePath = Path.GetFullPath(asmFile); string labelLevel = fullFilePath.Substring(fullPath.Length) .Replace(" ", "_").Replace("/", "_").Replace("\\", "_"); int s = labelLevel.LastIndexOf('.'); if (config.VerboseMode && binaryMode) { Console.WriteLine("Processing binary file '{0}':", fileName); } else if (config.VerboseMode) { Console.WriteLine("Processing file '{0}':", fileName); } if (s != -1) { labelLevel = labelLevel.Substring(0, s); } if (!binaryMode) { if (!CompileFile(File.ReadAllText(asmFile), baseFolder, fileName, "library", false, out start, out end, false, null)) { return; } } else { string baseAssembly = labelLevel + ":\r\nincbin \"" + fileName + "\"\r\n"; if (!CompileFile(baseAssembly, baseFolder, fileName, "library", false, out start, out end, false, null)) { return; } } if (config.VerboseMode) { Console.WriteLine(" Inserted at ${0:X6} (PC: 0x{1:x})", start, SNES.ToPCHeadered(start, rom.containsHeader)); Console.WriteLine(" Insert size: {0} (0x{0:X}) bytes", end - start + 8); } totalInsertSize += end - start + 8; var labels = Asar.getlabels().ToList(); int copyl = 0; for (int i = 0; i < labels.Count; ++i) { if (labels[i].Name != labelLevel) { var copy = labels[i]; copy.Name = labelLevel + "_" + copy.Name; labels[i] = copy; } if (labelList.Any(x => x.Name == labels[i].Name)) { Console.WriteLine(" {0} - error: label redefinition [{1}].", fileName, labels[i].Name); error = true; return; } if (!labels[i].Name.Contains(":")) { labelList.Add(labels[i]); copyl++; } if (labels[i].Location >= end || labels[i].Location < start) { labels.RemoveAt(i); --i; } } if (config.VerboseMode) { if (copyl == 1) { Console.WriteLine(" Processed one label."); } else { Console.WriteLine(" Processed {0} labels.", copyl); } } if (labels.Count == 0) { Console.WriteLine(" {0}: error: file contains no label within freespace area.", fileName); error = true; return; } if (!protPointerList.Contains(labels[0].Location)) { protPointerList.Add(labels[0].Location); } else { Console.WriteLine(" {0}: wtf error: Library included file is already protected.", fileName); error = true; return; } if (config.VerboseMode) { Console.WriteLine(); } fileCount++; } if (!binaryMode) { binaryMode = true; files = Directory.GetFiles("library/", "*.*", SearchOption.AllDirectories) .Where(x => !x.EndsWith(".asm", StringComparison.InvariantCultureIgnoreCase)).ToArray(); goto repeat; } if (fileCount == 0) { return; } if (fileCount == 1 && config.VerboseMode) { Console.WriteLine("Processed one library file."); } else if (config.VerboseMode) { Console.WriteLine("Processed {0} library files.", fileCount); } }
static void Main(string[] args) { Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); mainDirectory = Environment.CurrentDirectory + "/"; pathList = new string[3]; pathList[0] = mainDirectory; pathList[1] = mainDirectory + "asm/work/"; pathList[2] = mainDirectory + "asm/"; // this is for compatibility with old patches. if (!Asar.init()) { Console.WriteLine("Could not initialize or find asar.dll"); Console.WriteLine("Please redownload the program."); Pause(); return; } if (args.Length == 0 || args.Length > 2) { Console.WriteLine("Usage: UberASMTool [code list] [ROM]"); Console.WriteLine("If ROM is not specified, UberASM Tool will search for the one in the code list."); Console.WriteLine("If code list is not specified, UberASM Tool will try loading 'list.txt'."); Console.WriteLine(); if (args.Length > 2) { Pause(); return; } } UberConfigParser parser = new UberConfigParser(); if (args.Length == 2) { parser.OverrideROM = args[1]; try { parser.LoadListFile(args[0]); } catch (Exception ex) { Console.WriteLine("Can't read {0}: {1}.", args[0], ex.Message); Pause(); return; } } else if (args.Length == 1) { parser.OverrideROM = null; try { parser.LoadListFile(args[0]); } catch (Exception ex) { Console.WriteLine("Can't read {0}: {1}.", args[0], ex.Message); Pause(); return; } } else if (File.Exists("list.txt")) { parser.LoadListFile("list.txt"); } else { Console.WriteLine("list.txt not found."); Pause(); return; } Console.WriteLine(); if (!parser.ParseList()) { Console.WriteLine("Could not parse list file!"); Console.WriteLine(parser.GetLogs()); Pause(); return; } config = parser.Build(); if (config.ROMPath == null) { Console.WriteLine("ROM file not given."); Pause(); return; } try { rom = new ROM(config.ROMPath); rom.Init(); SNES.DetectAddressing(rom.romType & 255); } catch (Exception ex) { Console.WriteLine("Error: {0}", ex.Message); Pause(); return; } CleanPreviousRun(); if (error) { Pause(); return; } BuildLibrary(); if (error) { Pause(); return; } GenerateLibrary(); BuildAsm("overworld", 7, 1, "OW_init_table", "OW_asm_table", "OW_nmi_table", null); BuildAsm("gamemode", 256, 2, "gamemode_init_table", "gamemode_main_table", "gamemode_nmi_table", null); BuildAsm("level", 512, 0, "level_init_table", "level_asm_table", "level_nmi_table", "level_load_table"); BuildOther(); if (error) { Pause(); return; } if (config.VerboseMode) { Console.WriteLine("Total files insert size: {0} (0x{0:X4}) bytes", totalInsertSize); } if (Asar.patch(mainDirectory + "asm/work/main.asm", ref rom.romData, pathList)) { PrintWarningsAndErrors(""); var prints = Asar.getprints(); bool printed = false; for (int i = 0; i < prints.Length; ++i) { if (i + 1 != prints.Length) { Console.WriteLine(prints[i]); } else if (int.TryParse(prints[i], out int insertSize) && config.VerboseMode) { Console.WriteLine("Main patch insert size: {0} (0x{0:X4}) bytes", insertSize); Console.WriteLine(); Console.WriteLine("Total: {0} (0x{0:X4}) bytes", insertSize + totalInsertSize); Console.WriteLine(); printed = true; } } if (config.VerboseMode && !printed) { Console.WriteLine(); } Console.WriteLine("Codes inserted successfully."); rom.Save(); WriteRestoreComment(); } else { PrintWarningsAndErrors(""); Console.WriteLine("Some errors occured while applying main patch. Process aborted."); Console.WriteLine("Your ROM wasn't modified."); } Pause(); }
private static void BuildAsm(string asmPath, int maxItems, int mode, string initTable, string mainTable, string nmiTable, string loadTable) { if (error) { return; } int total = 0; if (config.VerboseMode) { Console.WriteLine("Building {0} ASM...", asmPath.ToUpper()[0] + asmPath.Substring(1)); Console.WriteLine(); } string baseFile = "asm/base/" + asmPath + ".asm"; string baseTempFile = "asm/work/" + asmPath + ".asm"; string baseFolder = asmPath + "/"; string assemblyData = File.ReadAllText(baseFile); StringBuilder initPointerList = new StringBuilder(); StringBuilder mainPointerList = new StringBuilder(); StringBuilder nmiPointerList = new StringBuilder(); StringBuilder loadPointerList = new StringBuilder(); for (int i = 0; i < maxItems; ++i) { initPointerList.Append("dl "); mainPointerList.Append("dl "); nmiPointerList.Append("dl "); loadPointerList.Append("dl "); if (config.FileASMList[mode][i] == null || config.FileASMList[mode][i].Length == 0) { initPointerList.Append("null_pointer"); mainPointerList.Append("null_pointer"); nmiPointerList.Append("null_pointer"); loadPointerList.Append("null_pointer"); } else { int nAsmInLevel = config.FileASMList[mode][i].Length; bool multiple = nAsmInLevel > 1; List <Code> codePaths = new List <Code>(); for (int j = 0; j < nAsmInLevel; j++) { codePaths.Add(config.CodeList[config.FileASMList[mode][i][j]]); } var code = codePaths[0]; string levelContents = null; if (!multiple) { try { levelContents = File.ReadAllText(baseFolder + code.Path); } catch (Exception ex) { Console.WriteLine("Error while reading file: " + ex.Message); error = true; return; } } if (config.VerboseMode) { Console.WriteLine("Processing file '{0}':", code.Path); } if (!code.Inserted) { if (!CompileFile(levelContents, baseFolder, code.Path, baseFolder, true, out int startPc, out int endPc, multiple, multiple ? codePaths.Select(x => x.Path) : null, loadTable != null)) { return; } if (endPc - startPc < 0) { Console.WriteLine(" {0}: error: Negative insert size. " + "Did you change program counter without pushpc/pullpc?", code.Path); error = true; return; } else if (endPc - startPc == 0) { Console.WriteLine(" {0}: error: Null (0 byte insert size) file.", code.Path); error = true; return; } if (config.VerboseMode) { Console.WriteLine(" Inserted at ${0:X6} (PC: 0x{1:x})", startPc, SNES.ToPCHeadered(startPc, rom.containsHeader)); Console.WriteLine(" Insert size: {0} (0x{0:X}) bytes", endPc - startPc + 8); } totalInsertSize += endPc - startPc + 8; var pointers = GetPointers(loadTable != null); if (pointers == null) { if (loadTable == null) { Console.WriteLine(" {0}: error: Missing init/main/nmi label.", code.Path); } else { Console.WriteLine(" {0}: error: Missing load/init/main/nmi label.", code.Path); } error = true; return; } int combo = 0; if (pointers[0] == -1) { initPointerList.Append("null_pointer"); } else if (pointers[0] >= endPc || pointers[0] < startPc) { Console.WriteLine(" {0}: error: INIT label outside free space range.", code.Path); error = true; return; } else { code.Init = pointers[0]; initPointerList.AppendFormat("${0:X6}", pointers[0]); combo |= 1; } if (pointers[1] == -1) { mainPointerList.Append("null_pointer"); } else if (pointers[1] >= endPc || pointers[1] < startPc) { Console.WriteLine(" {0}: error: MAIN label outside free space range.", code.Path); error = true; return; } else { code.Main = pointers[1]; mainPointerList.AppendFormat("${0:X6}", pointers[1]); combo |= 2; } if (pointers[3] == -1) { loadPointerList.Append("null_pointer"); } else if (pointers[3] >= endPc || pointers[3] < startPc) { Console.WriteLine(" {0}: error: LOAD label outside free space range.", code.Path); error = true; return; } else { code.Load = pointers[3]; loadPointerList.AppendFormat("${0:X6}", pointers[3]); combo |= 8; } if (pointers[2] == -1) { nmiPointerList.Append("null_pointer"); } else if (pointers[2] >= endPc || pointers[2] < startPc) { Console.WriteLine(" {0}: error: NMI label outside free space range.", code.Path); error = true; return; } else { code.Nmi = pointers[2]; nmiPointerList.AppendFormat("${0:X6}", pointers[2]); enableNmi[mode] = true; combo |= 4; } if (config.VerboseMode) { Console.Write($" INIT: {PrintPointer(code.Init)}"); if (combo >= 2) { Console.Write($" - MAIN: {PrintPointer(code.Main)}"); } if (combo >= 4) { Console.Write($" - NMI: {PrintPointer(code.Nmi)}"); } if (combo >= 8) { Console.Write($" - LOAD: {PrintPointer(code.Load)}"); } Console.WriteLine(); } code.Inserted = true; } else { if (code.Init == -1) { initPointerList.Append("null_pointer"); } else { initPointerList.AppendFormat("${0:X6}", code.Init); } if (code.Main == -1) { mainPointerList.Append("null_pointer"); } else { mainPointerList.AppendFormat("${0:X6}", code.Main); } if (code.Load == -1) { loadPointerList.Append("null_pointer"); } else { loadPointerList.AppendFormat("${0:X6}", code.Load); } if (code.Nmi == -1) { nmiPointerList.Append("null_pointer"); } else { nmiPointerList.AppendFormat("${0:X6}", code.Nmi); enableNmi[mode] = true; } if (config.VerboseMode) { Console.WriteLine(" Insert size: zero bytes"); } } if (config.VerboseMode) { Console.WriteLine(); } total++; } initPointerList.AppendLine(); mainPointerList.AppendLine(); nmiPointerList.AppendLine(); loadPointerList.AppendLine(); } InsertTable(ref assemblyData, initTable, initPointerList.ToString()); InsertTable(ref assemblyData, mainTable, mainPointerList.ToString()); if (loadTable != null) { InsertTable(ref assemblyData, loadTable, loadPointerList.ToString()); } if (enableNmi[mode]) { InsertTable(ref assemblyData, nmiTable, nmiPointerList.ToString()); } if (!FileUtils.ForceCreate(baseTempFile, assemblyData)) { Console.WriteLine(" Error: access denied while creating base temp file."); error = true; return; } if (config.VerboseMode) { if (total == 0) { return; } else if (total == 1) { Console.WriteLine("Total one file processed."); Console.WriteLine(); } else { Console.WriteLine("Total {0} files processed.", total); Console.WriteLine(); } } }