using SwitchGiftDataManager.Core; using Enums; namespace SwitchGiftDataManager.CommandLine; public static class Program { public static void Main() { var msg = $"Switch Gift Data Manager v{BCATManager.Version}"; Log(msg); Task.Run(TryUpdate).Wait(); msg = $"{Environment.NewLine}Select your game:{Environment.NewLine}{Environment.NewLine}" + $"1 - LGPE{Environment.NewLine}" + $"2 - SWSH{Environment.NewLine}" + $"3 - BDSP{Environment.NewLine}" + $"4 - PLA{Environment.NewLine}" + $"5 - SCVI"; Log(msg); Games game = (Games)int.Parse(Console.ReadLine()!); if (game is Games.None || game > Games.SCVI) { Log("Invalid input. Aborted."); Console.ReadKey(); return; } var bcat = new BCATManager(game); msg = $"{Environment.NewLine}Enter a valid input path.{Environment.NewLine}{Environment.NewLine}The path can be either:{Environment.NewLine}" + $"- A direct (full) path to a wondercard file{Environment.NewLine}" + $"- A (full) path to a folder containing wondercard files"; Log(msg); var path = Console.ReadLine()!; if (File.Exists(path)) bcat.TryAddWondercards(File.ReadAllBytes(path)); else if (CheckValidPath(path)) foreach (var file in Directory.GetFiles(path)) if (!bcat.TryAddWondercards(File.ReadAllBytes(file))) Log($"{file} could not be loaded."); if (bcat.Count() <= 0) { Log("No valid files have been loaded. Aborted."); Console.ReadKey(); return; } bcat.Sort(); var methodSelectionInfo = $"{Environment.NewLine}The Pokémon Scarlet & Violet v2.0.1 Update, released on September 13 - 2023, introduced a new TID / SID handling method for Wondercards.{Environment.NewLine}" + $"This Pokémon Gift could be redeemed both before and after the v2.0.1 release, meaning it can be redeemed with either the old or new TID/SID handling method, depending on the redemption date.{Environment.NewLine}" + $"The redemption date can be changed with the homebrew 'switch-time'. If you're not going to use 'switch-time', please select 'After v2.0.1'."; foreach (var (i, title) in bcat.GetListNames().Select((title, i) => (i, title)).Where(x => bcat.GetRequiresMethodSelection(x.i))) { var method = 0; while (method is not (1 or 2)) { Log($"{Environment.NewLine}[{title}] This Pokémon Gift could be redeemed both before and after the v2.0.1 release. Please select the redemption method you want to use, depending on the Date/Time you'll redeem the gift." + $"{Environment.NewLine}1 - Before v2.0.1" + $"{Environment.NewLine}2 - After v2.0.1" + $"{Environment.NewLine}3 - Info"); method = int.Parse(Console.ReadLine()!); if (method is (1 or 2)) bcat.SetIsBefore201(i, method == 1); else Log(methodSelectionInfo); } } Log($"{Environment.NewLine}Enter the source (full) path to your dumped BCAT:"); var sourcepath = Console.ReadLine()!; if (!CheckValidBcatPath(sourcepath)) { Log("Not a valid BCAT folder path. Aborted."); Console.ReadKey(); return; } Log($"{Environment.NewLine}Enter a destination (full) path to save the forged BCAT:"); var destpath = Console.ReadLine()!; if (!CheckValidPath(destpath)) { Log("Not a valid path. Aborted."); Console.ReadKey(); return; } if (game is not (Games.LGPE or Games.BDSP)) { msg = $"{Environment.NewLine}Select a build option:{Environment.NewLine}{Environment.NewLine}" + $"1 - Merge as one file{Environment.NewLine}" + $"2 - Keep separate files"; Log(msg); } var opt = game switch { Games.LGPE => 2, Games.BDSP => 1, _ => int.Parse(Console.ReadLine()!), }; if(opt < 1 || opt > 2) { Log("Invalid input. Aborted."); Console.ReadKey(); return; } destpath = Path.Combine(destpath, $"Forged_BCAT_{game}"); CopyDirectory(sourcepath, destpath); if (opt == 1) { try { var wcdata = bcat.ConcatenateFiles(); var metadata = bcat.ForgeMetaInfo(wcdata.ToArray()); var metadatapath = Path.Combine(destpath, "directories"); metadatapath = Path.Combine(metadatapath, bcat.GetDefaultBcatFolderName()); var wcpath = Path.Combine(metadatapath, "files"); if (Directory.Exists(metadatapath)) DeleteFilesAndDirectory(metadatapath); Directory.CreateDirectory(wcpath); File.WriteAllBytes(Path.Combine(metadatapath, "files.meta"), metadata.ToArray()); File.WriteAllBytes(Path.Combine(wcpath, bcat.GetDefaultBcatFileName()), wcdata.ToArray()); Log($"Saved in {path}{Environment.NewLine}BCAT forge was successful.{Environment.NewLine}Press any key to exit..."); Console.ReadKey(); } catch (Exception) { Log("Internal Error. Press any key to exit..."); Console.ReadKey(); } } else { var metadata = bcat.ForgeMetaInfo(); var metadatapath = Path.Combine(destpath, "directories"); metadatapath = Path.Combine(metadatapath, bcat.GetDefaultBcatFolderName()); var wcspath = Path.Combine(metadatapath, "files"); if (Directory.Exists(metadatapath)) DeleteFilesAndDirectory(metadatapath); Directory.CreateDirectory(wcspath); File.WriteAllBytes(Path.Combine(metadatapath, "files.meta"), metadata.ToArray()); if (bcat.TrySaveAllWondercards(wcspath)) { Log($"Saved in {path}{Environment.NewLine}BCAT forge was successful.{Environment.NewLine}Press any key to exit..."); Console.ReadKey(); } else { Log("Internal error. Press any key to exit..."); Console.ReadKey(); } } return; } private static bool CheckValidPath(string path) { if (string.IsNullOrWhiteSpace(path)) return false; if (!Directory.Exists(path)) return false; return true; } private static bool CheckValidBcatPath(string path) { if (string.IsNullOrWhiteSpace(path)) return false; if (!Directory.Exists(Path.Combine(path, "directories"))) return false; if (!File.Exists(Path.Combine(path, "directories.meta"))) return false; if (!File.Exists(Path.Combine(path, "etag.bin"))) return false; if (!File.Exists(Path.Combine(path, "list.msgpack"))) return false; if (!File.Exists(Path.Combine(path, "na_required"))) return false; if (!File.Exists(Path.Combine(path, "passphrase.bin"))) return false; return true; } static void CopyDirectory(string source, string dest) { var dir = new DirectoryInfo(source); DirectoryInfo[] dirs = dir.GetDirectories(); Directory.CreateDirectory(dest); foreach (FileInfo file in dir.GetFiles()) { string targetFilePath = Path.Combine(dest, file.Name); if (!File.Exists(targetFilePath)) file.CopyTo(targetFilePath); } foreach (DirectoryInfo subDir in dirs) { string newDestinationDir = Path.Combine(dest, subDir.Name); CopyDirectory(subDir.FullName, newDestinationDir); } } private static void DeleteFilesAndDirectory(string targetDir) { string[] files = Directory.GetFiles(targetDir); string[] dirs = Directory.GetDirectories(targetDir); foreach (string file in files) { File.SetAttributes(file, FileAttributes.Normal); File.Delete(file); } foreach (string dir in dirs) DeleteFilesAndDirectory(dir); Directory.Delete(targetDir, false); } private static async Task TryUpdate() { if (await GitHubUtil.IsUpdateAvailable()) { Log("A program update is available. Do you want to download the latest release?\n[Y\\n]:"); var str = Console.ReadLine(); if (!string.IsNullOrWhiteSpace(str) && (str.ToLower().Equals("y") || str.ToLower().Equals("yes"))) System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = @"https://github.com/Manu098vm/Switch-Gift-Data-Manager/releases", UseShellExecute = true }); } } private static void Log(string msg) => Console.WriteLine(msg); }