using Mono.Options; using System.Text; using Repackinator.Core.Actions; using System.Diagnostics; using Repackinator.Core.Models; using Repackinator.Core.Logging; namespace Repackinator.Shell.Console { public static class ConsoleRepack { public const string Action = "Repack"; public static string Input { get; set; } = string.Empty; public static string Output { get; set; } = string.Empty; public static string Unpack { get; set; } = string.Empty; public static string Grouping { get; set; } = "NONE"; public static bool Uppercase { get; set; } = false; public static bool Recurse { get; set; } = false; public static bool NoSplit { get; set; } = false; public static string Log { get; set; } = string.Empty; public static bool Compress { get; set; } = false; public static bool Scrub { get; set; } = false; public static bool TrimScrub { get; set; } = false; public static bool ShowHelp { get; set; } = false; public static bool Wait { get; set; } = false; public static OptionSet GetOptions() { return new OptionSet { { "i|input=", "Input folder", i => Input = i }, { "o|output=", "Output folder", o => Output = o }, { "p|unpack=", "Unpack folder for temporary extraction (optional)", p => Unpack = p}, { "g|grouping=", "Grouping (None *default*, Region, Letter, RegionLetter, LetterRegion)", g => Grouping = g.ToUpper() }, { "u|uppercase", "Uppercase", u => Uppercase = u != null }, { "r|recurse", "Recurse (Traverse Subdirs)", r => Recurse = r != null }, { "c|compress", "Compress (CCI)", c => Compress = c != null }, { "s|scrub", "Scrub", s => Scrub = s != null }, { "t|trimscrub", "TrimScrub", t => TrimScrub = t != null }, { "n|nosplit", "No Split of output file", n => NoSplit = n != null }, { "l|log=", "log file", l => Log = l }, { "h|help", "show help", h => ShowHelp = h != null }, { "w|wait", "Wait on exit", w => Wait = w != null } }; } public static void ShowOptionDescription() { System.Console.WriteLine(); System.Console.WriteLine("Repack Action..."); System.Console.WriteLine(); System.Console.WriteLine("This action is used to repackinate your collection of xbox disk images."); System.Console.WriteLine(); GetOptions().WriteOptionDescriptions(System.Console.Out); } public static void Process(string version, string[] args) { try { var options = GetOptions(); options.Parse(args); if (ShowHelp) { ConsoleUtil.ShowHelpHeaderForAction(version, Action, options); ConsoleUtil.ProcessWait(Wait); return; } if (string.IsNullOrEmpty(Input)) { throw new OptionException("input not specified.", "input"); } string input; try { input = Path.GetFullPath(Input); } catch (ArgumentException) { throw new OptionException("input is not a valid directory.", "input"); } if (!Directory.Exists(input)) { throw new OptionException("input directory does not exist.", "input"); } if (string.IsNullOrEmpty(Output)) { throw new OptionException("output not specified.", "output"); } string output; try { output = Path.GetFullPath(Output); } catch (ArgumentException) { throw new OptionException("output is not a valid directory.", "output"); } var groupingValue = GroupingOptionType.None; if (string.Equals(Grouping, "NONE")) { groupingValue = GroupingOptionType.None; } else if (string.Equals(Grouping, "REGION")) { groupingValue = GroupingOptionType.Region; } else if (string.Equals(Grouping, "LETTER")) { groupingValue = GroupingOptionType.Letter; } else if (string.Equals(Grouping, "REGIONLETTER")) { groupingValue = GroupingOptionType.RegionLetter; } else if (string.Equals(Grouping, "LETTERREGION")) { groupingValue = GroupingOptionType.LetterRegion; } else { throw new OptionException("grouping is not valid.", "grouping"); } var compressValue = CompressOptionType.None; if (Compress) { compressValue = CompressOptionType.CCI; } var scrubValue = ScrubOptionType.None; if (TrimScrub) { scrubValue = ScrubOptionType.TrimScrub; } else if (Scrub) { scrubValue = ScrubOptionType.Scrub; } string unpack; if (!string.IsNullOrEmpty(Unpack)) { try { unpack = Path.GetFullPath(Unpack); if (!Directory.Exists(unpack)) { Directory.CreateDirectory(unpack); } } catch (ArgumentException) { throw new OptionException("unpack is not a valid directory.", "unpack"); } } if (!Directory.Exists(output)) { Directory.CreateDirectory(output); } string log; FileStream? logStream = null; if (!string.IsNullOrEmpty(Log)) { try { log = Path.GetFullPath(Log); string? dir = Path.GetDirectoryName(log); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } logStream = File.OpenWrite(log); } catch (ArgumentException) { throw new OptionException("log is not a valid filepath.", "log"); } } var logger = new Action((logMessage) => { var formattedTime = logMessage.Time.ToString("HH:mm:ss"); var message = $"{formattedTime} {logMessage.Level} - {logMessage.Message}"; System.Console.WriteLine(message); logStream?.Write(Encoding.UTF8.GetBytes(message)); }); var config = new Config { InputPath = Input, OutputPath = Output, UnpackPath = Unpack, GroupingOption = groupingValue, RecurseInput = Recurse, Uppercase = Uppercase, CompressOption = compressValue, NoSplit = NoSplit, ScrubOption = scrubValue, }; var gameData = GameDataHelper.LoadGameData(); var prevMessage = string.Empty; var previousProgress1 = -1.0f; var previousProgress2 = -1.0f; var progress = new Action((progressInfo) => { if (!string.IsNullOrEmpty(progressInfo.Progress1Text) && progressInfo.Progress1Text != prevMessage) { if (!string.IsNullOrEmpty(prevMessage)) { System.Console.WriteLine(); } System.Console.WriteLine(progressInfo.Progress1Text); prevMessage = progressInfo.Progress1Text; } var amount1 = (float)Math.Round(progressInfo.Progress1 * 100); if (amount1 != previousProgress1) { if (amount1 < 10) { System.Console.Write($"Progress {amount1}%"); } else if (amount1 < 100) { System.Console.Write($"Progress {amount1}%"); } else { System.Console.Write($"Progress {amount1}%"); } System.Console.CursorLeft = 0; previousProgress1 = amount1; } if (progressInfo.Progress1 >= 1.0f && !string.IsNullOrEmpty(progressInfo.Progress2Text)) { var amount2 = (float)Math.Round(progressInfo.Progress2 * 100); if (amount2 != previousProgress2) { System.Console.WriteLine(); System.Console.Write($"{progressInfo.Progress2Text} - "); if (amount2 < 10) { System.Console.Write($"Progress {amount2}%"); } else if (amount2 < 100) { System.Console.Write($"Progress {amount2}%"); } else { System.Console.Write($"Progress {amount2}%"); } System.Console.CursorLeft = 0; previousProgress2 = amount2; } } }); var repacker = new Repacker(); repacker.StartRepacking(gameData, config, progress, logger, new Stopwatch(), default); logStream?.Dispose(); System.Console.WriteLine(); System.Console.WriteLine("Repack completed."); } catch (OptionException e) { ConsoleUtil.ShowOptionException(e, Action, version); } ConsoleUtil.ProcessWait(Wait); } } }