예제 #1
0
        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);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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();
        }
예제 #4
0
        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();
                }
            }
        }