コード例 #1
0
    public void RunMonoMod()
    {
        Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0");

        if (this.verbosity > 0)
        {
            Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1");
        }

        using (MonoModder mm = new MonoModder()
        {
            InputPath = this.assemblyPath,
            OutputPath = AssemblyTmpPath,
        })
        {
            // read assembly
            mm.Read();

            // read Seshat.dll
            mm.ReadMod(this.seshatPath);
            mm.MapDependencies();

            // autopatch
            mm.AutoPatch();

            // write assembly
            mm.Write();
        }
    }
コード例 #2
0
        /// <summary>
        /// Perform the actual patching of Assembly-CSharp.dll in the Risk of Rain 2 managed folder
        /// </summary>
        /// <param name="modPath">The path to the Assembly-CSharp.HexiDave.mm.dll file</param>
        private static void PatchWithMod(string modPath)
        {
            // Ensure that we have an Assembly-CSharp.dll.original file to work from
            FileUtilities.EnsureBackup();

            // Get a temporary file to write the new assembly to
            var outputPath = Path.GetTempFileName();

            // Setup MonoModder to patch the original Assembly-CSharp.dll
            using (var monoModder = new MonoModder
            {
                InputPath = FileUtilities.BackupAssemblyPath,
                OutputPath = outputPath
            })
            {
                // Read the assembly
                monoModder.Read();

                // Read the patch
                monoModder.ReadMod(modPath);

                // Ensure all the assembly references are still set
                monoModder.MapDependencies();

                // Re-write assembly with patch functions
                monoModder.AutoPatch();

                // Spit the file out
                monoModder.Write();
            }

            // Clear the assembly in RoR2's managed folder
            File.Delete(FileUtilities.AssemblyPath);

            // Move the patched assembly into place
            File.Move(outputPath, FileUtilities.AssemblyPath);

            // Make sure any dependencies are moved
            // TODO: Maybe remove this, but still tinkering
            var filesToInclude = new[]
            {
                "Mono.Cecil.dll"
            };

            foreach (var fileName in filesToInclude)
            {
                var moveToPath = $@"{FileUtilities.ManagedPath}\{fileName}";

                if (!File.Exists(moveToPath))
                {
                    File.Move(fileName, moveToPath);
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Patches an assembly located in Managed.
        /// </summary>
        /// <param name="pathToPatch"></param>
        /// <param name="assemblyName"></param>
        public void PatchAssembly(string pathToPatch, string assemblyName, string[] dependencies)
        {
            string assemblyPath = FindAssemblyByName(assemblyName);

            if (assemblyPath == string.Empty)
            {
                return;
            }

            string outputPath = Path.Combine(Directory.GetParent(assemblyPath).FullName, Path.GetFileNameWithoutExtension(assemblyPath) + "-NEW.dll");

            Console.WriteLine(assemblyPath);
            Console.WriteLine(outputPath);

            using (MonoModder mm = new MonoModder()
            {
                InputPath = assemblyPath,
                OutputPath = outputPath
            }) {
                mm.LogVerboseEnabled = true;
                mm.Read();
                //Force everything to be public
                mm.PublicEverything = true;

                //Read in the patch
                mm.ReadMod(pathToPatch);

                mm.MapDependencies();
                mm.DependencyDirs.Add(Directory.GetParent(Assembly.GetExecutingAssembly().FullName).FullName);

                mm.AutoPatch();

                mm.Write();
            }

            File.Delete(assemblyPath);
            File.Copy(outputPath, assemblyPath);
            File.Delete(outputPath);

            string managedPath = Directory.GetParent(assemblyPath).FullName;

            foreach (string s in dependencies)
            {
                string dependencyDestination = Path.Combine(managedPath, Path.GetFileName(s));

                if (File.Exists(dependencyDestination))
                {
                    File.Delete(dependencyDestination);
                }
                File.Copy(s, dependencyDestination);
            }
        }
コード例 #4
0
 public static void LoadPatch(Stream stream)
 {
     try {
         ModLogger.Log("rtpatcher", "Loading new patch");
         // Reload main assembly.
         Modder.Module = null;
         Modder.Read();
         // Add new mod to mods list.
         Modder.ReadMod(stream);
         ModRelinker.AssemblyRelinkMap[Modder.Mods[Modder.Mods.Count - 1].Assembly.Name.Name] = ModRelinker.AssemblyRelinkedCache["Assembly-CSharp"];
         Modder.MapDependencies();
         // Auto-patch and then feed Harmony.
         ModLogger.Log("rtpatcher", $"Applying new patch {Modder.Mods[Modder.Mods.Count - 1].Assembly.Name.Name}");
         Modder.AutoPatch();
         MMHarmony.PatchAll();
     } catch (Exception e) {
         ModLogger.Log("rtpatcher", $"Failed patching: {e}");
         return;
     }
 }
コード例 #5
0
        public void Patch()
        {
            // Load the assembly to check if it needs to be patched first
            string assemblyPath       = Path.Combine(_assemblyDirectory, AssemblyName);
            string assemblyBackupPath = assemblyPath.Replace(AssemblyName, AssemblyBackupName);

            if (!IsPatchingNeeded(assemblyPath))
            {
                Console.WriteLine("Game is already patched, no further action required.");
                return;
            }

            // Copy the required assemblies to the game directory
            foreach (var assemblyName in PatchAssemblies)
            {
                File.Copy(assemblyName, Path.Combine(_assemblyDirectory, assemblyName), true);
            }
            File.Copy(assemblyPath, assemblyBackupPath, true);

            // Run MonoMod
            Console.WriteLine("Patching game...");
            using (MonoModder mm = new MonoModder()
            {
                InputPath = assemblyBackupPath,
                OutputPath = assemblyPath + ".tmp"
            })
            {
                Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0");
                mm.Read();
                mm.ReadMod(Path.Combine(_assemblyDirectory, AssemblyPatchName));
                mm.MapDependencies();
                mm.AutoPatch();
                mm.Write();
            }

            // Copy the resultant assembly
            File.Delete(assemblyPath);
            File.Move(assemblyPath + ".tmp", assemblyPath);
        }
コード例 #6
0
        public static bool Mod(this InstallerWindow ins, string file)
        {
            string     inPath  = Path.Combine(ins.MainModDir, file);
            string     outPath = Path.Combine(ins.MainModDir, file + ".tmp.dll");
            MonoModder monomod = new MonoModder()
            {
                InputPath  = inPath,
                OutputPath = outPath
            };

            monomod.SetupETGModder();
            using (FileStream fileStream = File.Open(LogPath, FileMode.Append)) {
                using (StreamWriter streamWriter = new StreamWriter(fileStream)) {
                    monomod.Logger  = (string s) => ins.OnActivity();
                    monomod.Logger += (string s) => streamWriter.WriteLine(s);
                    // Unity wants .mdbs
                    // monomod.WriterParameters.SymbolWriterProvider = new Mono.Cecil.Mdb.MdbWriterProvider();
                    string db    = Path.ChangeExtension(inPath, "pdb");
                    string dbTmp = Path.ChangeExtension(outPath, "pdb");
                    if (!File.Exists(db))
                    {
                        db    = inPath + ".mdb";
                        dbTmp = outPath + ".mdb";
                    }
#if !DEBUG
RETRY:
                    try {
#endif
                    monomod.Read();                                        // Read main module first
                    monomod.ReadMod(Directory.GetParent(inPath).FullName); // ... then mods
                    monomod.MapDependencies();                             // ... then all dependencies
                    monomod.AutoPatch();                                   // Patch,
                    monomod.Write();                                       // and write.
                    monomod.Dispose();                                     // Finally, dispose, because file access happens now.

                    File.Delete(inPath);
                    File.Move(outPath, inPath);
                    if (File.Exists(db))
                    {
                        File.Delete(db);
                    }
                    if (File.Exists(dbTmp))
                    {
                        File.Move(dbTmp, db);
                    }
                    return(true);

#if !DEBUG
                } catch (ArgumentException e) {
                    monomod.Dispose();
                    if (File.Exists(db))
                    {
                        File.Delete(db);
                        if (File.Exists(dbTmp))
                        {
                            File.Delete(dbTmp);
                        }
                        goto RETRY;
                    }
                    ins.LogLine(e.ToString());
                    throw;
                    return(false);
                } catch (Exception e) {
                    monomod.Dispose();
                    ins.LogLine(e.ToString());
                    throw;
                    return(false);
                }
#endif
                }
            }
        }
コード例 #7
0
ファイル: Program.cs プロジェクト: zatherz/MonoMod
        public static void Main(string[] args)
        {
            Console.WriteLine("MonoMod " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);

            if (args.Length == 0)
            {
                Console.WriteLine("No valid arguments (assembly path) passed.");
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return;
            }

            string pathIn;
            string pathOut;

            if (args.Length > 1 &&
                args[0] == "--generate-debug-il" ||
                args[0] == "--gen-dbg-il")
            {
                Console.WriteLine("[DbgILGen] Generating debug hierarchy and debug data (pdb / mdb).");

                pathIn  = args[1];
                pathOut = args.Length != 2 ? args[args.Length - 1] : Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn));

                using (MonoModder mm = new MonoModder()
                {
                    InputPath = pathIn,
                    OutputPath = pathOut
                }) {
                    mm.Read(false);

                    mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);");
                    DebugILGenerator.Generate(mm);

                    mm.Write();

                    mm.Log("[DbgILGen] Done.");
                }

                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return;
            }

            int pathInI = 0;

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1");
                    pathInI = i + 1;
                }
                else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_VERBOSE", "1");
                    pathInI = i + 1;
                }
            }

            if (pathInI >= args.Length)
            {
                Console.WriteLine("No assembly path passed.");
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return;
            }

            pathIn  = args[pathInI];
            pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn));

            if (File.Exists(pathOut))
            {
                File.Delete(pathOut);
            }

            try {
                using (MonoModder mm = new MonoModder()
                {
                    InputPath = pathIn,
                    OutputPath = pathOut,
                    Verbose = Environment.GetEnvironmentVariable("MONOMOD_VERBOSE") == "1"
                }) {
                    mm.Read(false);

                    if (args.Length <= 2)
                    {
                        mm.Log("[Main] Scanning for mods in directory.");
                        mm.ReadMod(Directory.GetParent(pathIn).FullName);
                    }
                    else
                    {
                        mm.Log("[Main] Reading mods list from arguments.");
                        for (int i = pathInI + 1; i < args.Length - 2; i++)
                        {
                            mm.ReadMod(args[i]);
                        }
                    }

                    mm.Read(true);

                    mm.Log("[Main] mm.AutoPatch();");
                    mm.AutoPatch();

                    mm.Write();

                    mm.Log("[Main] Done.");
                }
            } catch (Exception e) {
                Console.WriteLine(e);
            }

            if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
            {
                Console.ReadKey();
            }
        }
コード例 #8
0
        public static int Main(string[] args)
        {
            Console.WriteLine("MonoMod " + typeof(Program).GetTypeInfo().Assembly.GetName().Version);

            if (args.Length == 0)
            {
                Console.WriteLine("No valid arguments (assembly path) passed.");
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return(0);
            }

            string pathIn;
            string pathOut;

            int pathInI = 0;

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1");
                    pathInI = i + 1;
                }
                else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cache=0" || args[i] == "--uncached")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_RELINKER_CACHED", "0");
                    pathInI = i + 1;
                }
            }

            if (pathInI >= args.Length)
            {
                Console.WriteLine("No assembly path passed.");
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return(0);
            }

            pathIn  = args[pathInI];
            pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null;
            pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn));

            if (File.Exists(pathOut))
            {
                File.Delete(pathOut);
            }

#if !DEBUG
            try {
#endif
            using (MonoModder mm = new MonoModder()
            {
                InputPath = pathIn,
                OutputPath = pathOut
            }) {
                mm.Read();

                if (args.Length <= 2)
                {
                    mm.Log("[Main] Scanning for mods in directory.");
                    mm.ReadMod(Directory.GetParent(pathIn).FullName);
                }
                else
                {
                    mm.Log("[Main] Reading mods list from arguments.");
                    for (int i = pathInI + 1; i < args.Length - 1; i++)
                    {
                        mm.ReadMod(args[i]);
                    }
                }

                mm.MapDependencies();

                mm.Log("[Main] mm.AutoPatch();");
                mm.AutoPatch();

                mm.Write();

                mm.Log("[Main] Done.");
            }
#if !DEBUG
        }

        catch (Exception e) {
            Console.WriteLine(e);
            if (System.Diagnostics.Debugger.IsAttached)     // Keep window open when running in IDE
            {
                Console.ReadKey();
            }
            return(-1);
        }
#endif

            if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
            {
                Console.ReadKey();
            }
            return(0);
        }
コード例 #9
0
            public void Install(Installer installer, bool leave_mmdlls = false)
            {
                var managed = installer.ManagedDir;

                if (HasPluginsDir)
                {
                    _InstallPlugins(installer.PluginsDir);
                }
                if (RequiresPatchedExe)
                {
                    installer.PatchExe();
                }

                using (StreamWriter patches_info_writer = new StreamWriter(File.OpenWrite(installer.PatchesInfoFile))) {
                    patches_info_writer.WriteLine($"{Name} {VersionName}");
                }

                _Install("assembly", Assemblies, managed);
                _Install("MonoMod patch DLL", PatchDLLs, managed);
                _Install("file", OtherFiles, managed, subdir: true);
                _Install("directory", Dirs, managed, subdir: true);

                foreach (var patch_target in Metadata?.OrderedTargets ?? installer.Downloader.GungeonMetadata.ViablePatchTargets)
                {
                    var patch_target_dll = Path.Combine(managed, $"{patch_target}.dll");
                    var patch_target_tmp = Path.Combine(managed, $"{patch_target}{TMP_PATCH_SUFFIX}");

                    var modder = new MonoModder {
                        InputPath  = patch_target_dll,
                        OutputPath = patch_target_tmp
                    };

                    if (Metadata != null && Metadata.RelinkMap != null)
                    {
                        Dictionary <string, string> rmap;
                        if (Metadata.RelinkMap.TryGetValue(patch_target, out rmap))
                        {
                            _Logger.Info($"Reading component relink map for target {patch_target}");
                            foreach (var pair in rmap)
                            {
                                ModuleDefinition module;
                                if (!modder.DependencyCache.TryGetValue(pair.Value, out module))
                                {
                                    var path = Path.Combine(managed, pair.Value);
                                    _Logger.Debug($"Dependency not in cache: {pair.Value} ({path})");
                                    module = modder.DependencyCache[pair.Value] = ModuleDefinition.ReadModule(path);
                                }

                                _Logger.Debug($"Mapping {pair.Key} => {pair.Value}");
                                modder.RelinkModuleMap[pair.Key] = module;
                            }
                        }
                    }

                    modder.Read();

                    var found_mods = false;

                    foreach (var dll in PatchDLLs)
                    {
                        if (File.Exists(Path.Combine(managed, dll)) && dll.StartsWith($"{patch_target}.", StringComparison.InvariantCulture))
                        {
                            found_mods = true;
                            _Logger.Debug($"Using patch DLL: {dll}");

                            modder.ReadMod(Path.Combine(managed, dll));
                        }
                    }

                    if (!found_mods)
                    {
                        _Logger.Info($"Not patching {patch_target} because this component has no patches for it");
                        continue;
                    }

                    _Logger.Info($"Patching target: {patch_target}");

                    modder.MapDependencies();
                    modder.AutoPatch();
                    modder.Write();
                    modder.Dispose();

                    _Logger.Debug($"Replacing original ({patch_target_tmp} => {patch_target_dll})");
                    if (File.Exists(patch_target_dll))
                    {
                        File.Delete(patch_target_dll);
                    }
                    File.Move(patch_target_tmp, patch_target_dll);
                }

                if (!leave_mmdlls)
                {
                    foreach (var dll in PatchDLLs)
                    {
                        if (!File.Exists(Path.Combine(managed, dll)))
                        {
                            continue;
                        }

                        _Logger.Debug($"Cleaning up patch DLL {dll}");
                        File.Delete(Path.Combine(managed, dll));
                    }
                }

                _Logger.Debug($"Cleaning up patched DLL MDB/PDBs");
                foreach (var ent in Directory.GetFileSystemEntries(managed))
                {
                    if (ent.EndsWith($"{TMP_PATCH_SUFFIX}.mdb", StringComparison.InvariantCulture))
                    {
                        File.Delete(ent);
                    }
                }
            }
コード例 #10
0
ファイル: Program.cs プロジェクト: thswogur00/ETGMod
        public static int Main(string[] args)
        {
            Console.WriteLine("MonoMod " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);

            if (args.Length == 0)
            {
                Console.WriteLine("No valid arguments (assembly path) passed.");
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return(0);
            }

            if (args[0] == "--test")
            {
                Console.WriteLine("[QuickDebugTest] Running...");
                int result = QuickDebugTest.Run(args);
                if (result == 0)
                {
                    Console.WriteLine("[QuickDebugTest] Passed!");
                }
                else
                {
                    Console.WriteLine($"[QuickDebugTest] Failed: {result}");
                }
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return(result);
            }

            string pathIn;
            string pathOut;

            int pathInI = 0;

            bool generateDebugIL = false;

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1");
                    pathInI = i + 1;
                }
                else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1");
                    pathInI = i + 1;
                }
                else if (args[i] == "--cache=0" || args[i] == "--uncached")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_RELINKER_CACHED", "0");
                    pathInI = i + 1;
                }
                else if (args[i] == "--generate-debug-il" || args[i] == "--gen-dbg-il")
                {
                    generateDebugIL = true;
                    pathInI         = i + 1;
                }
                else if (args[i] == "--debug-il-relative" || args[i] == "--dbg-il-relative")
                {
                    Environment.SetEnvironmentVariable("MONOMOD_DEBUGIL_RELATIVE", "1");
                    pathInI = i + 1;
                }
            }

            if (pathInI >= args.Length)
            {
                Console.WriteLine("No assembly path passed.");
                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return(0);
            }

            pathIn  = args[pathInI];
            pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null;

            if (generateDebugIL)
            {
                Console.WriteLine("[DbgILGen] Generating debug hierarchy and debug data (pdb / mdb).");

                pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn));

                using (MonoModder mm = new MonoModder()
                {
                    InputPath = pathIn,
                    OutputPath = pathOut
                }) {
                    mm.Read();

                    mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);");
                    DebugILGenerator.Generate(mm);

                    mm.Write();

                    mm.Log("[DbgILGen] Done.");
                }

                if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
                {
                    Console.ReadKey();
                }
                return(0);
            }

            pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn));

            if (File.Exists(pathOut))
            {
                File.Delete(pathOut);
            }

#if !DEBUG
            try {
#endif
            using (MonoModder mm = new MonoModder()
            {
                InputPath = pathIn,
                OutputPath = pathOut
            }) {
                mm.Read();

                if (args.Length <= 2)
                {
                    mm.Log("[Main] Scanning for mods in directory.");
                    mm.ReadMod(Directory.GetParent(pathIn).FullName);
                }
                else
                {
                    mm.Log("[Main] Reading mods list from arguments.");
                    for (int i = pathInI + 1; i < args.Length - 1; i++)
                    {
                        mm.ReadMod(args[i]);
                    }
                }

                mm.MapDependencies();

                mm.Log("[Main] mm.AutoPatch();");
                mm.AutoPatch();

                mm.Write();

                mm.Log("[Main] Done.");
            }
#if !DEBUG
        }

        catch (Exception e) {
            Console.WriteLine(e);
            if (System.Diagnostics.Debugger.IsAttached)     // Keep window open when running in IDE
            {
                Console.ReadKey();
            }
            return(-1);
        }
#endif

            if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE
            {
                Console.ReadKey();
            }
            return(0);
        }