/// <summary> /// Fired on startup /// </summary> /// <param name="e">startup event args</param> protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // Used for command line option parsing bool performUpdate = false; string filePath = string.Empty; // Parse command line arguments if (e.Args != null & e.Args.Length > 0) { for (var i = 0; i < e.Args.Length; i++) { if (e.Args[i].Equals("--patch", StringComparison.InvariantCultureIgnoreCase) && string.IsNullOrEmpty(filePath)) { if (i + 1 < e.Args.Length) { filePath = e.Args[i + 1]; continue; } } else if (e.Args[i].Equals("--update", StringComparison.InvariantCultureIgnoreCase) && !performUpdate) { performUpdate = true; continue; } } } // Only show the UI when not using the command-line version if (string.IsNullOrEmpty(filePath) && !performUpdate) { var window = new MainWindow(); window.ShowDialog(); } else { // Allocate a console AllocConsole(); // Update first if required try { if (performUpdate) { Console.WriteLine("Checking for updates..."); if (Patcher.AnyUpdateAvailable()) { Console.WriteLine("Downloading latest patch definitions..."); Patcher.DownloadLatestPatchDefinitions(); Console.WriteLine("Done."); } else { Console.WriteLine("No updates available."); } } } catch (Exception ex) { Console.Error.WriteLine($"An error occured while checking for updates: {ex}"); Application.Current.Shutdown(1); return; } // Stop here if no path was specified if (string.IsNullOrEmpty(filePath)) { Application.Current.Shutdown(0); return; } // Load the patch definitions file try { Console.WriteLine("Loading patch definitions file..."); Patcher.LoadPatchDefinitions(); Console.WriteLine("Done."); } catch (Exception ex) { Console.Error.WriteLine($"An error occured while loading the patch definitions file: {ex}"); Application.Current.Shutdown(1); return; } // Stop if there are no patches loaded if (!Patcher.AnyPatchesLoaded()) { Console.Out.WriteLine($"Unable to patch: 0 patches loaded"); Application.Current.Shutdown(1); return; } // Check game build GameBuild gameBuild = null; try { Console.WriteLine("Checking game build..."); gameBuild = Patcher.GetGameBuild(filePath); if (gameBuild == null) { Console.Out.WriteLine($"Unable to apply patches: unsupported game build detected"); Application.Current.Shutdown(1); return; } Console.WriteLine($"{gameBuild.Id} detected."); } catch (Exception ex) { Console.Error.WriteLine($"An error occured while checking the game build: {ex}"); Application.Current.Shutdown(1); return; } // Patch the specified file int successes = 0; try { Console.WriteLine("Applying patches..."); foreach (var patchResult in Patcher.ApplyPatches(filePath, gameBuild.Patches)) { if (patchResult.Success) { successes++; } Console.WriteLine($"{patchResult.Patch.Description} : {(patchResult.Success ? "Success" : "Failure")}"); } Console.WriteLine($"\n{successes} out of {gameBuild.Patches.Count} applied."); } catch (Exception ex) { Console.Error.WriteLine($"An error occured while patching the game executable: {ex}"); Application.Current.Shutdown(1); return; } Application.Current.Shutdown(successes == gameBuild.Patches.Count ? 0 : 1); } }
/// <summary> /// UI method for patching the specified file at the given file path /// </summary> /// <param name="filePath">file path</param> private void Patch(string filePath) { // First check if the selected executable is valid // and if the game build is supported Dispatcher.Invoke(() => PatcherStatus.Text = "Checking game version..."); GameBuild gameBuild = null; try { gameBuild = Patcher.GetGameBuild(filePath); } catch (Exception) { MessageBox.Show("An error occured while checking the game version.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); Dispatcher.Invoke(() => PatchButton.IsEnabled = true); Dispatcher.Invoke(() => CheckUpdatesButton.IsEnabled = true); Dispatcher.Invoke(() => PatcherStatus.Text = "Ready."); return; } // Unknown game build if (gameBuild == null) { MessageBox.Show("Make sure the selected file is correct and that " + "you are not selecting an already patched game executable, or check for updates.", "Unsupported game version detected", MessageBoxButton.OK, MessageBoxImage.Warning); Dispatcher.Invoke(() => PatchButton.IsEnabled = true); Dispatcher.Invoke(() => CheckUpdatesButton.IsEnabled = true); Dispatcher.Invoke(() => PatcherStatus.Text = "Ready."); return; } // Back up the executable? var makeBackup = MessageBox.Show("Do you want to make a backup of the current game executable?", "Backup", MessageBoxButton.YesNo, MessageBoxImage.Question); if (makeBackup == MessageBoxResult.Yes) { var saveFileDialog = new SaveFileDialog() { Filter = "All Files (.*)|*.*", FilterIndex = 1, FileName = "DOOMEternalx64vk.exe.bak", Title = "Save DOOM Eternal game executable file backup (.bak)" }; if (saveFileDialog.ShowDialog() == true) { try { if (File.Exists(saveFileDialog.FileName)) { File.Delete(saveFileDialog.FileName); } File.Copy(filePath, saveFileDialog.FileName); } catch (Exception) { var continueOrCancel = MessageBox.Show("An error occured while backing up the game executable. " + "Do you want to continue patching anyways?", "Error", MessageBoxButton.OKCancel, MessageBoxImage.Error); if (continueOrCancel == MessageBoxResult.Cancel) { Dispatcher.Invoke(() => PatchButton.IsEnabled = true); Dispatcher.Invoke(() => CheckUpdatesButton.IsEnabled = true); Dispatcher.Invoke(() => PatcherStatus.Text = "Ready."); return; } } } } // Patch the executable Dispatcher.Invoke(() => PatcherStatus.Text = "Patching..."); try { var patchingResult = Patcher.ApplyPatches(filePath, gameBuild.Patches); // Display patching results var succesfulPatches = new StringBuilder(); var failedPatches = new StringBuilder(); var resultsString = new StringBuilder(); int successes = 0; int fails = 0; foreach (var patchResult in patchingResult) { if (patchResult.Success) { succesfulPatches.Append(patchResult.Patch.Description).Append("\n"); successes++; continue; } failedPatches.Append(patchResult.Patch.Description).Append("\n"); fails++; } if (successes > 0) { resultsString.Append("The following patches were successfuly applied:\n\n"); resultsString.Append(succesfulPatches); } if (fails > 0) { if (successes > 0) { resultsString.Append("\n"); } resultsString.Append("The following patches could not be applied:\n\n"); resultsString.Append(failedPatches); } resultsString.Append($"\n{successes} patches out of {gameBuild.Patches.Count} applied."); MessageBox.Show(resultsString.ToString(), "Patching results", MessageBoxButton.OK, fails > 0 ? MessageBoxImage.Warning : MessageBoxImage.Information); } catch (Exception) { MessageBox.Show($"An error occured while patching the game executable.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } finally { Dispatcher.Invoke(() => PatchButton.IsEnabled = true); Dispatcher.Invoke(() => CheckUpdatesButton.IsEnabled = true); Dispatcher.Invoke(() => PatcherStatus.Text = "Ready."); } }