/// <summary> /// Shuts down the Reloaded Launcher and launches the currently selected game. /// The parameter of this method allows for the specification OPTIONAL ADDITIONAL arguments such as --log or --attach. /// </summary> /// <param name="localArguments">Additional command line arguments/options to pass to Reloaded-Loader.</param> public static void LaunchLoader(string[] localArguments) { // Build filepath and arguments string filePath = $"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\\Reloaded-Loader.exe"; // Build arguments. List <string> argumentsList = new List <string>() { $"\"{Strings.Common.LoaderSettingConfig}\"", $"\"{Global.CurrentGameConfig.ConfigLocation}\"" }; // We are done here. argumentsList.AddRange(localArguments); // Start process ReloadedProcess process = new ReloadedProcess(filePath, argumentsList.ToArray()); process.ResumeAllThreads(); if (Global.LoaderConfiguration.ExitAfterLaunch) { // Self-shutdown. Shutdown(); } }
/// <summary> /// The main entry point for the application. /// </summary> /// <param name="args"></param> public static void Main(string[] args) { #if DEBUG Debugger.Launch(); #endif // Find Assemblies Manually if necessary (Deprecate app.config) AppDomain.CurrentDomain.AssemblyResolve += AssemblyFinder.CurrentDomain_AssemblyResolve; /* - Initialization - */ IgnoreSquirrel(); ParseArguments(args); LoaderConsole.Initialize(); SetuplibReloadedBindings(); Banner.Execute(); Controllers.PrintControllerOrder(); DllUnlocker.UnblockDlls(); // Removes Zone Information which may prevent DLL injection if DLL was downloaded from e.g. Internet Explorer LoaderServer.SetupServer(); /* - Boot up Reloaded Assembler, Get the Game Process running/attached and with mods running. - */ Assembler.Assemble(new string[] { "use32", "nop eax" }); // Startup Assembler (So a running instance/open handle does not bother devs working on mods) GetGameProcess(args); InjectMods(args); // Resume game after injection if we are NOT in attach mode. if (_attachTargetName == null) { _gameProcess.ResumeAllThreads(); } // Stay alive in the background AppDomain.CurrentDomain.ProcessExit += Shutdown; Console.CancelKeyPress += Shutdown; // Wait infinitely. while (true) { Console.ReadLine(); } }
/// <summary> /// Reboots the Reloaded Loader in x64 mode by running the x64 wrapper. /// </summary> /// <param name="arguments">A copy of the arguments originally passed to the starting application.</param> private static void RebootX64(string[] arguments) { // Add quotes to each argument in quotes. for (int x = 0; x < arguments.Length; x++) { arguments[x] = $"\"{arguments[x]}\""; } ReloadedProcess reloadedProcess = new ReloadedProcess($"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\\Reloaded-Wrapper-x64.exe", arguments); reloadedProcess.ResumeAllThreads(); Shutdown(null, null); }
/// <summary> /// Shuts down the Reloaded Launcher and launches the currently selected game. /// The parameter of this method allows for the specification OPTIONAL ADDITIONAL arguments such as --log or --attach. /// </summary> /// <param name="extraArguments">Additional command line arguments/options to pass to Reloaded-Loader.</param> public static void LaunchLoader(string[] extraArguments) { // Gets a file path of the loader. string filePath = GetLoaderFilePath(); // Start process ReloadedProcess process = new ReloadedProcess(filePath, GetCommandlineParameters(extraArguments).ToArray()); process.ResumeAllThreads(); // Self-shutdown. if (Global.LoaderConfiguration.ExitAfterLaunch) { Shutdown(); } }
/// <summary> /// Launches Reloaded's Launcher with the Steam flag set for a specific game. /// </summary> /// <param name="gameConfigDirectory"></param> public static void LaunchGame(string gameConfigDirectory) { // Get launcher location and arguments. string reloadedLauncherLocation = GetLauncherLocation(); var arguments = new List <string>() { $"{Strings.Launcher.LaunchArgumentName}", $"{gameConfigDirectory}", $"{Strings.Common.LoaderSettingSteamShim}" }; // Start Reloaded-Launcher. DateTime currentTime = DateTime.Now; ReloadedProcess process = new ReloadedProcess(reloadedLauncherLocation, arguments.ToArray()); process.ResumeAllThreads(); // Synchronize exit of this application with Reloaded-Loader. bool is64Bit = IsGameConfig64Bit(gameConfigDirectory); FindLoaderAndSynchronizeExit(is64Bit, currentTime); }
/// <summary> /// Finds the mods that are currently enabled for the game and injects into the target process. /// </summary> /// <param name="gameConfiguration">The game configuration which contains the current directory and list of mods to load.</param> /// <param name="reloadedProcess">The reloaded process to inject the modifications into.</param> public static void LoadMods(GameConfigParser.GameConfig gameConfiguration, ReloadedProcess reloadedProcess) { // Get directory containing the global mod list. GameConfigParser.GameConfig globalModConfig = GameConfigParser.ParseConfig(LoaderPaths.GetGlobalGameConfigDirectory()); // Get directory containing the game's mod list string gameModDirectory = Path.Combine(LoaderPaths.GetModLoaderModDirectory(), gameConfiguration.ModDirectory); string globalModDirectory = LoaderPaths.GetGlobalModDirectory(); // Get directories containing enabled mods. List <string> modLibraries = new List <string>(gameConfiguration.EnabledMods.Count); // Get the game mod dll locations. foreach (string modDirectory in gameConfiguration.EnabledMods) { // Add native or not native. if (ReloadedArchitecture.IsGame32Bit) { modLibraries.Add(Path.Combine(gameModDirectory, modDirectory, Strings.Loader.Mod32BitDllFile)); } else { modLibraries.Add(Path.Combine(gameModDirectory, modDirectory, Strings.Loader.Mod64BitDllFile)); } } // Get the global mod dll locations. foreach (string modDirectory in globalModConfig.EnabledMods) { // Add native or not native. if (ReloadedArchitecture.IsGame32Bit) { modLibraries.Add(Path.Combine(globalModDirectory, modDirectory, Strings.Loader.Mod32BitDllFile)); } else { modLibraries.Add(Path.Combine(globalModDirectory, modDirectory, Strings.Loader.Mod64BitDllFile)); } } // Initialize DLL Injector DllInjector reloadedDllInjector = new DllInjector(reloadedProcess); // If the main.dll exists, load it. foreach (string modLibrary in modLibraries) { // If the DLL Exists, Try to Load It if (File.Exists(modLibrary)) { // Allocate Memory for Server Port In Game Memory IntPtr parameterAddress = reloadedProcess.AllocateMemory(IntPtr.Size); // Write Server Port to Game Memory reloadedProcess.WriteMemoryExternal(parameterAddress, BitConverter.GetBytes(LoaderServer.ServerPort)); // Inject the individual DLL. reloadedDllInjector.InjectDll(modLibrary, parameterAddress); } } // Resume game after injection. reloadedProcess.ResumeAllThreads(); }
/// <summary> /// Checks whether to reattach Reloaded Mod Loader if the game process /// unexpectedly kills itself and then restarts (a standard for some games' launch procedures). /// </summary> /// <param name="arguments">The commandline arguments originally passed to this process.</param> /// <returns>Returns true if another game instance is running, else false.</returns> private static void ProcessSelfReattach(string[] arguments) { // Decides whether bool buildArgumentsList = false; // Auto re-attach if there's another process instance that's up with matching name. // First set the attach name if not set and add to the arguments. if (_attachTargetName == null) { // Set attach name. _attachTargetName = Path.GetFileNameWithoutExtension(_gameConfig.ExecutableLocation); buildArgumentsList = true; } // Use stopwatch for soft timing. Stopwatch timeoutStopWatch = new Stopwatch(); timeoutStopWatch.Start(); // Spin trying to get game process until timeout. while (timeoutStopWatch.ElapsedMilliseconds < 1000) { // Grab current already running game. ReloadedProcess localGameProcess = ReloadedProcess.GetProcessByName(_attachTargetName); // Did we find the process? If not, try again. if (localGameProcess == null) { continue; } // Suspend the resurrected game. localGameProcess.SuspendAllThreads(); // Check if process is newer than our original game process, if it is, restart self. if (localGameProcess.GetProcessFromReloadedProcess().StartTime > _processStartTime) { // If the loader is lacking the "attach" flag. // The reason this is done here is because we want to freeze the // target process as soon as possible, such that we can hook onto it as early as possible. if (buildArgumentsList) { // List of arguments. List <string> argumentsList = arguments.ToList(); // Append attach argument. argumentsList.Add($"{Strings.Common.LoaderSettingAttach}"); // Append attach name. argumentsList.Add(_attachTargetName); // Replace array. arguments = argumentsList.ToArray(); } _gameProcess = localGameProcess; RestartSelf(arguments); break; } // Resume the resurrected game. localGameProcess.ResumeAllThreads(); } // Kill the process itself. Shutdown(null, null); }