diff --git a/SwitchGiftDataManager.CommandLine/Program.cs b/SwitchGiftDataManager.CommandLine/Program.cs index 1c7b70b..fb55e2d 100644 --- a/SwitchGiftDataManager.CommandLine/Program.cs +++ b/SwitchGiftDataManager.CommandLine/Program.cs @@ -1,236 +1,234 @@ using SwitchGiftDataManager.Core; using Enums; +namespace SwitchGiftDataManager.CommandLine; -namespace SwitchGiftDataManager.CommandLine +public static class Program { - public static class Program + public static void Main() { - 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) { - var msg = $"Switch Gift Data Manager v{BCATManager.Version}"; + 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(); + 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); + } - Task.Run(TryUpdate).Wait(); + var opt = game switch { + Games.LGPE => 2, + Games.BDSP => 1, + _ => int.Parse(Console.ReadLine()!), + }; - 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); + if(opt < 1 || opt > 2) + { + Log("Invalid input. Aborted."); + Console.ReadKey(); + return; + } - Games game = (Games)int.Parse(Console.ReadLine()!); - if (game is Games.None || game > Games.SCVI) + destpath = Path.Combine(destpath, $"Forged_BCAT_{game}"); + CopyDirectory(sourcepath, destpath); + + if (opt == 1) + { + try { - 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(); - 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 wcdata = bcat.ConcatenateFiles(); + var metadata = bcat.ForgeMetaInfo(wcdata.ToArray()); var metadatapath = Path.Combine(destpath, "directories"); metadatapath = Path.Combine(metadatapath, bcat.GetDefaultBcatFolderName()); - var wcspath = Path.Combine(metadatapath, "files"); + var wcpath = Path.Combine(metadatapath, "files"); if (Directory.Exists(metadatapath)) DeleteFilesAndDirectory(metadatapath); - Directory.CreateDirectory(wcspath); + Directory.CreateDirectory(wcpath); 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(); - } + 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(); } - - 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()) + catch (Exception) { - 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); + Log("Internal Error. Press any key to exit..."); + Console.ReadKey(); } } - - private static void DeleteFilesAndDirectory(string targetDir) + else { - string[] files = Directory.GetFiles(targetDir); - string[] dirs = Directory.GetDirectories(targetDir); + var metadata = bcat.ForgeMetaInfo(); + var metadatapath = Path.Combine(destpath, "directories"); + metadatapath = Path.Combine(metadatapath, bcat.GetDefaultBcatFolderName()); + var wcspath = Path.Combine(metadatapath, "files"); - foreach (string file in files) + if (Directory.Exists(metadatapath)) + DeleteFilesAndDirectory(metadatapath); + + Directory.CreateDirectory(wcspath); + File.WriteAllBytes(Path.Combine(metadatapath, "files.meta"), metadata.ToArray()); + if (bcat.TrySaveAllWondercards(wcspath)) { - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); + Log($"Saved in {path}{Environment.NewLine}BCAT forge was successful.{Environment.NewLine}Press any key to exit..."); + Console.ReadKey(); } - - foreach (string dir in dirs) - DeleteFilesAndDirectory(dir); - - Directory.Delete(targetDir, false); - } - - private static async Task TryUpdate() - { - if (await GitHubUtil.IsUpdateAvailable()) + else { - 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 }); + Log("Internal error. Press any key to exit..."); + Console.ReadKey(); } } - private static void Log(string msg) => Console.WriteLine(msg); + 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); } \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/BCATManager/BCATManager.cs b/SwitchGiftDataManager.Core/Classes/BCATManager/BCATManager.cs index bf4e7ef..0fcb81a 100644 --- a/SwitchGiftDataManager.Core/Classes/BCATManager/BCATManager.cs +++ b/SwitchGiftDataManager.Core/Classes/BCATManager/BCATManager.cs @@ -3,373 +3,371 @@ using System.Globalization; using System.Text; using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class BCATManager { - public class BCATManager + public const string Version = "1.4.0"; + + private const int FileNameOffset = 0x00; + private const int UnkOffset = 0x20; + private const int FileSizeOffset = 0x28; + private const int ChecksumOffset = 0x30; + private const int MaxFileNameLength = 0x1F; + private const int WCMetaInfoLength = 0x80; + private const int MetaHeaderLength = 0x04; + + private Games Game { get; set; } + private List? WCList { get; set; } + + public BCATManager(Games game) { - public const string Version = "1.4.0"; + Game = game; + WCList = new(); + } - private const int FileNameOffset = 0x00; - private const int UnkOffset = 0x20; - private const int FileSizeOffset = 0x28; - private const int ChecksumOffset = 0x30; - private const int MaxFileNameLength = 0x1F; - private const int WCMetaInfoLength = 0x80; - private const int MetaHeaderLength = 0x04; - - private Games Game { get; set; } - private List? WCList { get; set; } - - public BCATManager(Games game) + private Wondercard CreateWondercard(ReadOnlySpan data) + { + return Game switch { - Game = game; - WCList = new(); - } + Games.LGPE => new WB7(data), + Games.SWSH => new WC8(data), + Games.BDSP => new WB8(data), + Games.PLA => new WA8(data), + Games.SCVI => new WC9(data), + _ => throw new ArgumentOutOfRangeException(nameof(Game)), + }; + } - private Wondercard CreateWondercard(ReadOnlySpan data) - { - return Game switch + public bool TryAddWondercards(ReadOnlySpan data, bool sort = false) + { + var success = false; + if (Game is not Games.None && WCList is not null) + if (Game is not Games.LGPE || (Game is Games.LGPE && WCList.Count == 0)) { - Games.LGPE => new WB7(data), - Games.SWSH => new WC8(data), - Games.BDSP => new WB8(data), - Games.PLA => new WA8(data), - Games.SCVI => new WC9(data), - _ => throw new ArgumentOutOfRangeException(), - }; - } - - public bool TryAddWondercards(ReadOnlySpan data, bool sort = false) - { - var success = false; - if (Game is not Games.None && WCList is not null) - if (Game is not Games.LGPE || (Game is Games.LGPE && WCList.Count == 0)) + var game = GetCompatibleGamesFromWC(data); + if (game == Game) { - var game = GetCompatibleGamesFromWC(data); - if (game == Game) + var size = (int)Wondercard.GetSize(game); + var qty = data.Length / size; + for (int i = 0; i < qty; i++) { - var size = (int)Wondercard.GetSize(game); - var qty = data.Length / size; - for (int i = 0; i < qty; i++) + var wc = CreateWondercard(data[(i * size)..((i + 1) * size)]); + if (wc.IsValid()) { - var wc = CreateWondercard(data[(i * size)..((i + 1) * size)]); - if (wc.IsValid()) - { - WCList.Add(wc); - success = true; - } + WCList.Add(wc); + success = true; } } - if (sort) - Sort(); } - return success; - } - - public void Sort() => WCList!.Sort((x, y) => x.WCID.CompareTo(y.WCID)); - - public int Count() - { - if (WCList is not null) - return WCList.Count; - - return 0; - } - - public void RemoveWC(int index) - { - if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1) - WCList.RemoveAt(index); - } - - public void Reset() - { - if(WCList is not null) - WCList.Clear(); - else - WCList = new List(); - } - - public void SetWCID(int index, ushort wcid) - { - if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) - { - var wc = WCList.ElementAt(index); - wc.SetID(wcid); + if (sort) + Sort(); } - } + return success; + } - public ushort GetWCID(int index) + public void Sort() => WCList!.Sort((x, y) => x.WCID.CompareTo(y.WCID)); + + public int Count() + { + if (WCList is not null) + return WCList.Count; + + return 0; + } + + public void RemoveWC(int index) + { + if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1) + WCList.RemoveAt(index); + } + + public void Reset() + { + if(WCList is not null) + WCList.Clear(); + else + WCList = new List(); + } + + public void SetWCID(int index, ushort wcid) + { + if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) { - if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) - return WCList.ElementAt(index).WCID; - return 0; - } - - public void SetIsRepeatable(int index, bool repeatable) - { - if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) - { - var wc = WCList.ElementAt(index); - wc.SetRepeatable(repeatable); - } - } - - public bool GetIsRepeatable(int index) - { - if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) - return WCList.ElementAt(index).IsRepeatable; - return false; - } - - public int GetIndex(ushort wcid) - { - if (WCList is not null && WCList.Count > 0) - return WCList.FindIndex((x) => x.WCID == wcid); - else - throw new IndexOutOfRangeException(); - } - - public static Games GetCompatibleGamesFromWC(ReadOnlySpan data) - { - if (data.Length % (int)Wondercard.GetSize(Games.LGPE) == 0) - return Games.LGPE; - else if (data.Length % (int)Wondercard.GetSize(Games.SWSH) == 0) - return Games.SWSH; - else if (data.Length % (int)Wondercard.GetSize(Games.BDSP) == 0) - return Games.BDSP; - else if (data.Length % (int)Wondercard.GetSize(Games.SCVI) == 0) - return data[Wondercard.GenOffset] != 0 ? Games.PLA : Games.SCVI; - else - return Games.None; - } - - public List GetListNames() - { - List list = new(); - if (WCList is not null && WCList.Count > 0) - foreach (var wc in WCList) - { - var str = wc.Type!.ToString()!.Equals("Pokemon") ? ((PokemonGift)wc.Content!).GetSpeciesName().Replace("\r","") : wc.Type!.ToString()!; - list.Add($"{Game} #{wc.WCID}: {str}"); - } - return list; - } - - public List GetContentToString(int index) - { - var wcid = ""; - var el1 = ""; - var el2 = ""; - var el3 = ""; - var el4 = ""; - var el5 = ""; - var el6 = ""; - var el7 = ""; - - if (WCList is not null && WCList.Count > 0 && WCList.Count >= index) - { - var wc = WCList.ElementAt(index); - wcid = wc.WCID.ToString(); - var content = wc.Content; - if (content!.GetType() == typeof(PokemonGift)) - { - var c = (PokemonGift)content; - el1 = GetShinyString(c.ShinyType); - el2 = c.GetSpeciesName(); - el3 = GetPIDString(c.PIDType); - } - else if (content!.GetType() == typeof(List)) - { - foreach (var c in (List)content) - { - var item = c.GetItemName().Replace("\r",""); - var qty = c.Quantity; - var str = $"{item.Replace("BP", "Battle Points").Replace("LP", "League Points")}"; - if (qty != 0x0 && qty != 0xFFFF) - str = $"{str} x{qty}"; - if (el1.Equals("")) - el1 = str; - else if (el2.Equals("")) - el2 = str; - else if (el3.Equals("")) - el3 = str; - else if (el4.Equals("")) - el4 = str; - else if (el5.Equals("")) - el5 = str; - else if (el6.Equals("")) - el6 = str; - else if (el7.Equals("")) - el7 = str; - } - } - } - return new List { wcid, el1, el2, el3, el4, el5, el6, el7 }; - } - - public List? GetDuplicatedWCID() - { - if (WCList is not null && WCList.Count > 1) - { - var l = WCList.GroupBy(x => x.WCID) - .Where(g => g.Count() > 1) - .Select(y => y.Key) - .ToList(); - return l; - } - else - return new List(); - } - - public string GetDefaultBcatFolderName() => GetDefaultBcatFolderName(this.Game); - public string GetDefaultBcatFileName() => GetDefaultBcatFileName(this.Game); - - public static string GetDefaultBcatFolderName(Games game) - { - return game switch - { - Games.LGPE => "normal", - Games.SWSH => "normal", - Games.BDSP => "99", - Games.PLA => "normal", - Games.SCVI => "normal", - _ => throw new ArgumentOutOfRangeException(), - }; - } - - - public static string GetDefaultBcatFileName(Games game) - { - return game switch - { - Games.SWSH => "distribution_internet", - Games.BDSP => "99", - Games.PLA => "distribution_internet", - Games.SCVI => "distribution_internet", - _ => throw new ArgumentOutOfRangeException(), - }; - } - - public bool TrySaveAllWondercards(string path) - { - if (WCList is null || WCList.Count == 0) - return false; - - for (int i = 0; i < WCList.Count; i++) - if (!TrySaveWondercard(i, path)) - return false; - - return true; - } - - public bool TrySaveWondercard(int index, string path) - { - try - { - var wc = WCList!.ElementAt(index); - File.WriteAllBytes(Path.Combine(path, ForgeWcFileName(wc)), wc.Data!); - return true; - } - catch (Exception) - { - return false; - } - } - - public ReadOnlySpan ConcatenateFiles() - { - var size = (int)Wondercard.GetSize(Game); - var data = new byte[size * WCList!.Count]; - foreach (var el in WCList!.Select((wc, i) => new { i, wc })) - el.wc.Data!.CopyTo(data, el.i * size); - return data.AsSpan(); - } - - private string ForgeWcFileName(Wondercard wc) - { - var type = wc.Type!.ToString()!; - var content = type.Equals("Pokemon") ? $"{((PokemonGift)wc.Content!).GetSpeciesName().Replace("\r","")}" : type; - var str = $"{wc.WCID:0000}_{content}"; - var sb = new System.Text.StringBuilder(); - foreach (char c in str) - if (c != '\\' && c != '/' && c != ':' && c != '*' && c != '?' && c != '"' && c != '<' && c != '>' && c != '|') - sb.Append(c); - var _sb = new System.Text.StringBuilder(); - foreach (char c in sb.ToString().Normalize(NormalizationForm.FormD)) - if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) - _sb.Append(c); - return _sb.ToString().ToLower(); - } - - public ReadOnlySpan ForgeMetaInfo(object? data = null) - { - if (data is not null && data.GetType() == typeof(byte[])) - { - var fileName = System.Text.Encoding.UTF8.GetBytes(GetDefaultBcatFileName()); - var unknown = 0xFFFFFFFF; - var fileSize = (uint)((byte[])data).Length; - var checksum = ChecksumCalculator.CalcReverseMD5((byte[])data); - var metainfo = new byte[WCMetaInfoLength]; - fileName.CopyTo(metainfo, FileNameOffset); - BinaryPrimitives.WriteUInt32LittleEndian(metainfo.AsSpan(UnkOffset), unknown); - BinaryPrimitives.WriteUInt32LittleEndian(metainfo.AsSpan(FileSizeOffset), fileSize); - checksum.ToArray().CopyTo(metainfo, ChecksumOffset); - return ForgeMetaInfoHeader(metainfo); - } - else - { - var metainfo = new byte[WCMetaInfoLength * WCList!.Count]; - foreach (var el in WCList!.Select((wc, i) => new { i, wc })) - ForgeWcMetaInfo(el.wc).ToArray().CopyTo(metainfo, el.i * WCMetaInfoLength); - return ForgeMetaInfoHeader(metainfo); - } - } - - private ReadOnlySpan ForgeWcMetaInfo(Wondercard wc) - { - var fileName = System.Text.Encoding.UTF8.GetBytes(ForgeWcFileName(wc)); - var unknown = 0xFFFFFFFF; - var fileSize = (uint)Wondercard.GetSize(Game); - var checksum = wc.CalcMetaChecksum(); - var data = new byte[WCMetaInfoLength]; - fileName.CopyTo(data, FileNameOffset); - BinaryPrimitives.WriteUInt32LittleEndian(data.AsSpan(UnkOffset), unknown); - BinaryPrimitives.WriteUInt32LittleEndian(data.AsSpan(FileSizeOffset), fileSize); - checksum.ToArray().CopyTo(data, ChecksumOffset); - return data.AsSpan(); - } - - private ReadOnlySpan ForgeMetaInfoHeader(ReadOnlySpan data) - { - uint header = 0x1; - byte[] filesDotMeta = new byte[data.Length + MetaHeaderLength]; - BinaryPrimitives.WriteUInt32LittleEndian(filesDotMeta.AsSpan(), header); - data.ToArray().CopyTo(filesDotMeta, MetaHeaderLength); - return filesDotMeta.AsSpan(); - } - - private string GetShinyString(ShinyType type) - { - return type switch - { - ShinyType.ShinyLocked => "Shiny Locked", - ShinyType.ShinyPossible => "Shiny Standard Odds", - ShinyType.ShinyHighOdds => "Shiny High Odds", - ShinyType.ShinyForced => "Shiny Forced", - ShinyType.ShinyTIDAbuse => "Shiny Possible (TID Abuse)", - _ => throw new IndexOutOfRangeException() - }; - } - - private string GetPIDString(PIDType type) - { - return type switch - { - PIDType.FixedPID => "Fixed PID", - PIDType.RandomPID => "Random PID", - _ => throw new IndexOutOfRangeException() - }; + var wc = WCList.ElementAt(index); + wc.SetID(wcid); } } + + public ushort GetWCID(int index) + { + if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) + return WCList.ElementAt(index).WCID; + return 0; + } + + public void SetIsRepeatable(int index, bool repeatable) + { + if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) + { + var wc = WCList.ElementAt(index); + wc.SetRepeatable(repeatable); + } + } + + public bool GetIsRepeatable(int index) + { + if (WCList is not null && WCList.Count > 0 && WCList.Count >= index - 1 && index >= 0) + return WCList.ElementAt(index).IsRepeatable; + return false; + } + + public int GetIndex(ushort wcid) + { + if (WCList is not null && WCList.Count > 0) + return WCList.FindIndex((x) => x.WCID == wcid); + else + throw new IndexOutOfRangeException(); + } + + public List GetListNames() + { + List list = new(); + if (WCList is not null && WCList.Count > 0) + foreach (var wc in WCList) + { + var str = wc.Type!.ToString()!.Equals("Pokemon") ? ((PokemonGift)wc.Content!).GetSpeciesName().Replace("\r","") : wc.Type!.ToString()!; + list.Add($"{Game} #{wc.WCID}: {str}"); + } + return list; + } + + public List GetContentToString(int index) + { + var wcid = ""; + var el1 = ""; + var el2 = ""; + var el3 = ""; + var el4 = ""; + var el5 = ""; + var el6 = ""; + var el7 = ""; + + if (WCList is not null && WCList.Count > 0 && WCList.Count >= index) + { + var wc = WCList.ElementAt(index); + wcid = wc.WCID.ToString(); + var content = wc.Content; + if (content!.GetType() == typeof(PokemonGift)) + { + var c = (PokemonGift)content; + el1 = GetShinyString(c.ShinyType); + el2 = c.GetSpeciesName(); + el3 = GetPIDString(c.PIDType); + } + else if (content!.GetType() == typeof(List)) + { + foreach (var c in (List)content) + { + var item = c.GetItemName().Replace("\r",""); + var qty = c.Quantity; + var str = $"{item.Replace("BP", "Battle Points").Replace("LP", "League Points")}"; + if (qty != 0x0 && qty != ushort.MaxValue) + str = $"{str} x{qty}"; + if (el1.Equals("")) + el1 = str; + else if (el2.Equals("")) + el2 = str; + else if (el3.Equals("")) + el3 = str; + else if (el4.Equals("")) + el4 = str; + else if (el5.Equals("")) + el5 = str; + else if (el6.Equals("")) + el6 = str; + else if (el7.Equals("")) + el7 = str; + } + } + } + return new List { wcid, el1, el2, el3, el4, el5, el6, el7 }; + } + + public List? GetDuplicatedWCID() + { + if (WCList is not null && WCList.Count > 1) + { + var l = WCList.GroupBy(x => x.WCID) + .Where(g => g.Count() > 1) + .Select(y => y.Key) + .ToList(); + return l; + } + else + return new List(); + } + + public string GetDefaultBcatFolderName() => GetDefaultBcatFolderName(this.Game); + public string GetDefaultBcatFileName() => GetDefaultBcatFileName(this.Game); + + public bool TrySaveAllWondercards(string path) + { + if (WCList is null || WCList.Count == 0) + return false; + + for (int i = 0; i < WCList.Count; i++) + if (!TrySaveWondercard(i, path)) + return false; + + return true; + } + + public bool TrySaveWondercard(int index, string path) + { + try + { + var wc = WCList!.ElementAt(index); + File.WriteAllBytes(Path.Combine(path, ForgeWcFileName(wc)), wc.Data!); + return true; + } + catch (Exception) + { + return false; + } + } + + public ReadOnlySpan ConcatenateFiles() + { + var size = (int)Wondercard.GetSize(Game); + var data = new byte[size * WCList!.Count]; + foreach (var el in WCList!.Select((wc, i) => new { i, wc })) + el.wc.Data!.CopyTo(data, el.i * size); + return data.AsSpan(); + } + + public ReadOnlySpan ForgeMetaInfo(object? data = null) + { + if (data is not null && data.GetType() == typeof(byte[])) + { + var fileName = System.Text.Encoding.UTF8.GetBytes(GetDefaultBcatFileName()); + var fileSize = (uint)((byte[])data).Length; + var checksum = ChecksumCalculator.CalcReverseMD5((byte[])data); + var metainfo = new byte[WCMetaInfoLength]; + fileName.CopyTo(metainfo, FileNameOffset); + BinaryPrimitives.WriteUInt32LittleEndian(metainfo.AsSpan(UnkOffset), uint.MaxValue); + BinaryPrimitives.WriteUInt32LittleEndian(metainfo.AsSpan(FileSizeOffset), fileSize); + checksum.ToArray().CopyTo(metainfo, ChecksumOffset); + return ForgeMetaInfoHeader(metainfo); + } + else + { + var metainfo = new byte[WCMetaInfoLength * WCList!.Count]; + foreach (var el in WCList!.Select((wc, i) => new { i, wc })) + ForgeWcMetaInfo(el.wc).ToArray().CopyTo(metainfo, el.i * WCMetaInfoLength); + return ForgeMetaInfoHeader(metainfo); + } + } + + private static ReadOnlySpan ForgeWcMetaInfo(Wondercard wc) + { + var fileName = System.Text.Encoding.UTF8.GetBytes(ForgeWcFileName(wc)); + var fileSize = (uint)Wondercard.GetSize(wc.Game); + var checksum = wc.CalcMetaChecksum(); + var data = new byte[WCMetaInfoLength]; + fileName.CopyTo(data, FileNameOffset); + BinaryPrimitives.WriteUInt32LittleEndian(data.AsSpan(UnkOffset), uint.MaxValue); + BinaryPrimitives.WriteUInt32LittleEndian(data.AsSpan(FileSizeOffset), fileSize); + checksum.ToArray().CopyTo(data, ChecksumOffset); + return data.AsSpan(); + } + + private static string ForgeWcFileName(Wondercard wc) + { + var type = wc.Type!.ToString()!; + var content = type.Equals("Pokemon") ? $"{((PokemonGift)wc.Content!).GetSpeciesName().Replace("\r", "")}" : type; + var str = $"{wc.WCID:0000}_{content}"; + var sb = new System.Text.StringBuilder(); + foreach (char c in str) + if (c != '\\' && c != '/' && c != ':' && c != '*' && c != '?' && c != '"' && c != '<' && c != '>' && c != '|') + sb.Append(c); + var _sb = new System.Text.StringBuilder(); + foreach (char c in sb.ToString().Normalize(NormalizationForm.FormD)) + if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) + _sb.Append(c); + return _sb.ToString().ToLower(); + } + + private static ReadOnlySpan ForgeMetaInfoHeader(ReadOnlySpan data) + { + uint header = 0x1; + byte[] filesDotMeta = new byte[data.Length + MetaHeaderLength]; + BinaryPrimitives.WriteUInt32LittleEndian(filesDotMeta.AsSpan(), header); + data.ToArray().CopyTo(filesDotMeta, MetaHeaderLength); + return filesDotMeta.AsSpan(); + } + + public static Games GetCompatibleGamesFromWC(ReadOnlySpan data) + { + if (data.Length % (int)Wondercard.GetSize(Games.LGPE) == 0) + return Games.LGPE; + else if (data.Length % (int)Wondercard.GetSize(Games.SWSH) == 0) + return Games.SWSH; + else if (data.Length % (int)Wondercard.GetSize(Games.BDSP) == 0) + return Games.BDSP; + else if (data.Length % (int)Wondercard.GetSize(Games.PLA) == 0 && data[Wondercard.GenOffset] != 0) + return Games.PLA; + else if (data.Length % (int)Wondercard.GetSize(Games.SCVI) == 0 && data[Wondercard.GenOffset] == 0) + return Games.SCVI; + else + return Games.None; + } + + public static string GetDefaultBcatFolderName(Games game) + { + return game switch + { + Games.LGPE => "normal", + Games.SWSH => "normal", + Games.BDSP => "99", + Games.PLA => "normal", + Games.SCVI => "normal", + _ => throw new ArgumentOutOfRangeException(nameof(game)), + }; + } + + public static string GetDefaultBcatFileName(Games game) + { + return game switch + { + Games.SWSH => "distribution_internet", + Games.BDSP => "99", + Games.PLA => "distribution_internet", + Games.SCVI => "distribution_internet", + _ => throw new ArgumentOutOfRangeException(nameof(game)), + }; + } + + private static string GetShinyString(ShinyType type) + { + return type switch + { + ShinyType.ShinyLocked => "Shiny Locked", + ShinyType.ShinyPossible => "Shiny Standard Odds", + ShinyType.ShinyHighOdds => "Shiny High Odds", + ShinyType.ShinyForced => "Shiny Forced", + ShinyType.ShinyTIDAbuse => "Shiny Possible (TID Abuse)", + _ => throw new IndexOutOfRangeException() + }; + } + + private static string GetPIDString(PIDType type) + { + return type switch + { + PIDType.FixedPID => "Fixed PID", + PIDType.RandomPID => "Random PID", + _ => throw new IndexOutOfRangeException() + }; + } } \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/ChecksumCalculator.cs b/SwitchGiftDataManager.Core/Classes/WCManager/ChecksumCalculator.cs index 2b841e4..8994053 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/ChecksumCalculator.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/ChecksumCalculator.cs @@ -1,77 +1,76 @@ using System.Security.Cryptography; //Credits for the CalcCcittFalse implementation to PNZEmil: https://gist.github.com/tijnkooijmans/10981093?permalink_comment_id=3996072#gistcomment-3996072 -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public static class ChecksumCalculator { - public static class ChecksumCalculator + private const ushort InitialValue = 0xFFFF; + + private static readonly ushort[] ccittFalseCrc16Table = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 + }; + + public static ushort CalcCcittFalse(ReadOnlySpan bytes) { - private const ushort InitialValue = 0xFFFF; + var crc16 = InitialValue; - private static readonly ushort[] ccittFalseCrc16Table = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 - }; - - public static ushort CalcCcittFalse(ReadOnlySpan bytes) + var length = bytes.Length; + var byteIndex = 0; + while (length-- > 0) { - var crc16 = InitialValue; - - var length = bytes.Length; - var byteIndex = 0; - while (length-- > 0) - { - var tableIndex = crc16 >> 8 ^ bytes[byteIndex++]; - crc16 = (ushort)(crc16 << 8 ^ ccittFalseCrc16Table[tableIndex]); - } - - return crc16; + var tableIndex = crc16 >> 8 ^ bytes[byteIndex++]; + crc16 = (ushort)(crc16 << 8 ^ ccittFalseCrc16Table[tableIndex]); } - public static Span CalcReverseMD5(byte[] data) - { - var md5 = MD5.Create().ComputeHash(data); + return crc16; + } - var tmp1 = md5.AsSpan((md5.Length / 2)..); - tmp1.Reverse(); + public static Span CalcReverseMD5(byte[] data) + { + var md5 = MD5.Create().ComputeHash(data); - var tmp2 = md5.AsSpan(0..(md5.Length / 2)); - tmp2.Reverse(); - - var b = new byte[md5.Length]; - tmp2.ToArray().CopyTo(b, 0); - tmp1.ToArray().CopyTo(b, tmp1.Length); + var tmp1 = md5.AsSpan((md5.Length / 2)..); + tmp1.Reverse(); - return b.AsSpan(); - } + var tmp2 = md5.AsSpan(0..(md5.Length / 2)); + tmp2.Reverse(); + + var b = new byte[md5.Length]; + tmp2.ToArray().CopyTo(b, 0); + tmp1.ToArray().CopyTo(b, tmp1.Length); + + return b.AsSpan(); } } \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/OtherGift.cs b/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/OtherGift.cs index c7c72e1..79672c3 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/OtherGift.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/OtherGift.cs @@ -1,105 +1,104 @@ using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class OtherGift { - public class OtherGift + public object? Type { get; set; } + public ushort Item { get; set; } + public uint Quantity { get; set; } + public ushort Opt { get; set; } + + public string GetItemName() => GetItemName(Item, Type!, Opt); + + public static string GetItemName(ushort id, object type, ushort opt = 0) { - public object? Type { get; set; } - public ushort Item { get; set; } - public uint Quantity { get; set; } - public ushort Opt { get; set; } + var str = ""; - public string GetItemName() => GetItemName(Item, Type!, Opt); - - public static string GetItemName(ushort id, object type, ushort opt = 0) + if (type.GetType() == typeof(GiftType7)) { - var str = ""; - - if (type.GetType() == typeof(GiftType7)) - { - if ((GiftType7)type is GiftType7.Item) - str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else - str = ((GiftType7)type).ToString(); - } - else if (type.GetType() == typeof(GiftType8)) - { - if ((GiftType8)type is GiftType8.Item) - str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else if ((GiftType8)type is GiftType8.Clothing) - { - var category = (ClothingType8)id; - var description = category switch - { - ClothingType8.Glasses => Properties.Resources.SWSHClothingGlasses.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Hats => Properties.Resources.SWSHClothingHats.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Jackets => Properties.Resources.SWSHClothingJackets.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Tops => Properties.Resources.SWSHClothingTops.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Bags => Properties.Resources.SWSHClothingBags.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Gloves => Properties.Resources.SWSHClothingGloves.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Bottoms => Properties.Resources.SWSHClothingBottoms.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Legwear => Properties.Resources.SWSHClothingLegwear.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8.Footwear => Properties.Resources.SWSHClothingShoes.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - _ => throw new ArgumentOutOfRangeException(), - }; - str = $"[{category}] {description}"; - } - else - str = ((GiftType8)type).ToString(); - } - else if(type.GetType() == typeof(GiftType8B)) - { - if ((GiftType8B)type is GiftType8B.Item) - str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else if ((GiftType8B)type is GiftType8B.Clothing) - str = Properties.Resources.BDSPClothing.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else if ((GiftType8B)type is GiftType8B.Underground) - str = Properties.Resources.UndergroundItems.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else - str = ((GiftType8B)type).ToString(); - } - else if (type.GetType() == typeof(GiftType8A)) - { - if ((GiftType8A)type is GiftType8A.Item) - str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else if ((GiftType8A)type is GiftType8A.Clothing) + if ((GiftType7)type is GiftType7.Item) + str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else + str = ((GiftType7)type).ToString(); + } + else if (type.GetType() == typeof(GiftType8)) + { + if ((GiftType8)type is GiftType8.Item) + str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else if ((GiftType8)type is GiftType8.Clothing) { - var category = (ClothingType8A)id; + var category = (ClothingType8)id; var description = category switch { - ClothingType8A.Headwear => Properties.Resources.PLAClothingHeads.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8A.Tops => Properties.Resources.PLAClothingTops.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8A.Bottoms => Properties.Resources.PLAClothingBottoms.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], - ClothingType8A.Outfit => "", - ClothingType8A.Footwear => "", - ClothingType8A.Glasses => "", - ClothingType8A.Eyewear => "", + ClothingType8.Glasses => Properties.Resources.SWSHClothingGlasses.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Hats => Properties.Resources.SWSHClothingHats.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Jackets => Properties.Resources.SWSHClothingJackets.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Tops => Properties.Resources.SWSHClothingTops.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Bags => Properties.Resources.SWSHClothingBags.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Gloves => Properties.Resources.SWSHClothingGloves.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Bottoms => Properties.Resources.SWSHClothingBottoms.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Legwear => Properties.Resources.SWSHClothingLegwear.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8.Footwear => Properties.Resources.SWSHClothingShoes.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], _ => throw new ArgumentOutOfRangeException(), }; - if(string.IsNullOrWhiteSpace(description)) - description = $"{opt:X4}"; str = $"[{category}] {description}"; } - else - str = ((GiftType8A)type).ToString(); - } - else if (type.GetType() == typeof(GiftType9)) - { - if ((GiftType9)type is GiftType9.Item) - str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; - else if ((GiftType9)type is GiftType9.Clothing) - { - var category = (ClothingType9)id; - var description = Properties.Resources.SCVIClothings.Split(new String[] { "\n" }, StringSplitOptions.None)[opt]; - if (string.IsNullOrWhiteSpace(description)) - description = $"{opt:X4}"; - str = $"[{category.ToString().Replace("Uniform", "Clothing")}] {description}"; - } - else - str = ((GiftType9)type).ToString(); - } - - return str; + else + str = ((GiftType8)type).ToString(); } + else if(type.GetType() == typeof(GiftType8B)) + { + if ((GiftType8B)type is GiftType8B.Item) + str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else if ((GiftType8B)type is GiftType8B.Clothing) + str = Properties.Resources.BDSPClothing.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else if ((GiftType8B)type is GiftType8B.Underground) + str = Properties.Resources.UndergroundItems.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else + str = ((GiftType8B)type).ToString(); + } + else if (type.GetType() == typeof(GiftType8A)) + { + if ((GiftType8A)type is GiftType8A.Item) + str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else if ((GiftType8A)type is GiftType8A.Clothing) + { + var category = (ClothingType8A)id; + var description = category switch + { + ClothingType8A.Headwear => Properties.Resources.PLAClothingHeads.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8A.Tops => Properties.Resources.PLAClothingTops.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8A.Bottoms => Properties.Resources.PLAClothingBottoms.Split(new String[] { "\n" }, StringSplitOptions.None)[opt], + ClothingType8A.Outfit => "", + ClothingType8A.Footwear => "", + ClothingType8A.Glasses => "", + ClothingType8A.Eyewear => "", + _ => throw new ArgumentOutOfRangeException(), + }; + if(string.IsNullOrWhiteSpace(description)) + description = $"{opt:X4}"; + str = $"[{category}] {description}"; + } + else + str = ((GiftType8A)type).ToString(); + } + else if (type.GetType() == typeof(GiftType9)) + { + if ((GiftType9)type is GiftType9.Item) + str = Properties.Resources.Items.Split(new String[] { "\n" }, StringSplitOptions.None)[id]; + else if ((GiftType9)type is GiftType9.Clothing) + { + var category = (ClothingType9)id; + var description = Properties.Resources.SCVIClothings.Split(new String[] { "\n" }, StringSplitOptions.None)[opt]; + if (string.IsNullOrWhiteSpace(description)) + description = $"{opt:X4}"; + str = $"[{category.ToString().Replace("Uniform", "Clothing")}] {description}"; + } + else + str = ((GiftType9)type).ToString(); + } + + return str; } -} +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/PokemonGift.cs b/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/PokemonGift.cs index bb882c8..9debb07 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/PokemonGift.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/GiftData/PokemonGift.cs @@ -1,39 +1,38 @@ using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class PokemonGift { - public class PokemonGift + public ushort Species { get; set; } + public uint PID { get; set; } + public uint TID { get; set; } + public uint SID { get; set; } + public ShinyType ShinyType { get; set; } + public PIDType PIDType { get; set; } + + public string GetSpeciesName() => GetSpeciesName(Species); + + public bool IsShiny() { - public ushort Species { get; set; } - public uint PID { get; set; } - public uint TID { get; set; } - public uint SID { get; set; } - public ShinyType ShinyType { get; set; } - public PIDType PIDType { get; set; } + if (ShinyType is ShinyType.ShinyForced) + return true; + else if (ShinyType is ShinyType.ShinyPossible && PID != 0 && TID != 0 && SID != 0) + return IsShiny(PID, TID, SID); - public string GetSpeciesName() => GetSpeciesName(Species); - - public bool IsShiny() - { - if (ShinyType is ShinyType.ShinyForced) - return true; - else if (ShinyType is ShinyType.ShinyPossible && PID != 0 && TID != 0 && SID != 0) - return IsShiny(PID, TID, SID); - - return false; - } - - public static string GetSpeciesName(uint species) => Properties.Resources.Species.Split(new string[] { "\n" }, StringSplitOptions.None)[species].Replace(",", ""); - - public static bool IsShiny(uint pid, uint tid, uint sid) => sid != 0 || tid != 0 ? (sid ^ tid ^ (pid >> 16) ^ (pid & 0xFFFF)) < 16 : false; - - public static bool IsTIDAbusePossible(uint tid, uint sid, PIDType type) - { - if (type is PIDType.FixedPID) - if (tid == 0) - if (sid == 0) - return true; - return false; - } + return false; } -} + + public static string GetSpeciesName(uint species) => Properties.Resources.Species.Split(new string[] { "\n" }, StringSplitOptions.None)[species].Replace(",", ""); + + public static bool IsShiny(uint pid, uint tid, uint sid) => sid != 0 || tid != 0 ? (sid ^ tid ^ (pid >> 16) ^ (pid & 0xFFFF)) < 16 : false; + + public static bool IsTIDAbusePossible(uint tid, uint sid, PIDType type) + { + if (type is PIDType.FixedPID) + if (tid == 0) + if (sid == 0) + return true; + return false; + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/WA8.cs b/SwitchGiftDataManager.Core/Classes/WCManager/WA8.cs index f43a1ed..14e0d33 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/WA8.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/WA8.cs @@ -1,140 +1,139 @@ using System.Buffers.Binary; using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class WA8 : Wondercard { - public class WA8 : Wondercard + private const int WondercardIDOffset = 0x08; + private const int FlagOffset = 0x0E; + private const int GiftTypeOffset = 0x0F; + private const int ItemOffset = 0x18; + private const int QuantityOffset = 0x1A; + private const int ClothingOffset = 0x1C; + private const int TIDOffset = 0x18; + private const int SIDOffset = 0x1A; + private const int PIDOffset = 0x24; + private const int SpeciesOffset = 0x238; + private const int ShinyTypeOffset = 0x240; + private const int ChecksumOffset = 0x2C4; + + public WA8(ReadOnlySpan data) : base(data) { - private const int WondercardIDOffset = 0x08; - private const int FlagOffset = 0x0E; - private const int GiftTypeOffset = 0x0F; - private const int ItemOffset = 0x18; - private const int QuantityOffset = 0x1A; - private const int ClothingOffset = 0x1C; - private const int TIDOffset = 0x18; - private const int SIDOffset = 0x1A; - private const int PIDOffset = 0x24; - private const int SpeciesOffset = 0x238; - private const int ShinyTypeOffset = 0x240; - private const int ChecksumOffset = 0x2C4; - - public WA8(ReadOnlySpan data) : base(data) + WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); + IsRepeatable = (Data![FlagOffset] & 1) == 0; + Type = (GiftType8A)Data![GiftTypeOffset]; + Content = Type switch { - WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); - IsRepeatable = (Data![FlagOffset] & 1) == 0; - Type = (GiftType8A)Data![GiftTypeOffset]; - Content = Type switch - { - GiftType8A.Pokemon => GetPokemon(), - _ => GetItems(), - }; - } - - private PokemonGift GetPokemon() - { - var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); - var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); - var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); - var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); - var test = (ShinyType8)Data![ShinyTypeOffset]; - var pidtype = (ShinyType8)Data![ShinyTypeOffset] switch - { - ShinyType8.ShinyLocked => PIDType.RandomPID, - ShinyType8.ShinyRandom => PIDType.RandomPID, - ShinyType8.ShinyStar => PIDType.FixedPID, - ShinyType8.ShinySquare => PIDType.FixedPID, - ShinyType8.Fixed => PIDType.FixedPID, - _ => throw new ArgumentOutOfRangeException(), - }; - var shinytype = (ShinyType8)Data![ShinyTypeOffset] switch - { - ShinyType8.ShinyLocked => ShinyType.ShinyLocked, - ShinyType8.ShinyRandom => ShinyType.ShinyPossible, - ShinyType8.ShinyStar or ShinyType8.ShinySquare => ShinyType.ShinyForced, - ShinyType8.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : - PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, - _ => throw new ArgumentOutOfRangeException(), - }; - - return new PokemonGift - { - Species = species, - PID = pid, - TID = tid, - SID = sid, - ShinyType = shinytype, - PIDType = pidtype, - }; - } - - private List GetItems() - { - List items = new(); - for (int i = 0; i < MaxItemCount; i++) - { - ushort item = 0; - ushort quantity = 0; - ushort opt = 0; - var type = (GiftType8A)Type!; - - if (type is GiftType8A.Clothing) - { - item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x08 * i))); - opt = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ClothingOffset + (0x08 * i))); - } - else - { - item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); - quantity = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); - } - - var gift = new OtherGift - { - Type = type, - Item = item, - Quantity = quantity, - Opt = opt, - }; - - if ((type is not GiftType8A.Clothing && gift.Item != 0x00) || (type is GiftType8A.Clothing && opt != 0xFFFF)) - items.Add(gift); - } - return items; - } - - public override bool IsChecksumValid() - { - if (Data is not null) - { - var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); - var span = Data.ToArray().AsSpan(); - BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); - var newchecksum = ChecksumCalculator.CalcCcittFalse(span); - if (oldChecksum == newchecksum) - return true; - } - return false; - } - - public override void UpdateChecksum() - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); - var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); - } - - public override void SetID(ushort wcid) - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); - WCID = wcid; - UpdateChecksum(); - } - - public override void SetRepeatable(bool repeatable) - { - Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); - IsRepeatable = repeatable; - UpdateChecksum(); - } + GiftType8A.Pokemon => GetPokemon(), + _ => GetItems(), + }; } -} + + private PokemonGift GetPokemon() + { + var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); + var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); + var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); + var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); + var test = (ShinyType8)Data![ShinyTypeOffset]; + var pidtype = (ShinyType8)Data![ShinyTypeOffset] switch + { + ShinyType8.ShinyLocked => PIDType.RandomPID, + ShinyType8.ShinyRandom => PIDType.RandomPID, + ShinyType8.ShinyStar => PIDType.FixedPID, + ShinyType8.ShinySquare => PIDType.FixedPID, + ShinyType8.Fixed => PIDType.FixedPID, + _ => throw new ArgumentOutOfRangeException(), + }; + var shinytype = (ShinyType8)Data![ShinyTypeOffset] switch + { + ShinyType8.ShinyLocked => ShinyType.ShinyLocked, + ShinyType8.ShinyRandom => ShinyType.ShinyPossible, + ShinyType8.ShinyStar or ShinyType8.ShinySquare => ShinyType.ShinyForced, + ShinyType8.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : + PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, + _ => throw new ArgumentOutOfRangeException(), + }; + + return new PokemonGift + { + Species = species, + PID = pid, + TID = tid, + SID = sid, + ShinyType = shinytype, + PIDType = pidtype, + }; + } + + private List GetItems() + { + List items = new(); + for (int i = 0; i < MaxItemCount; i++) + { + ushort item = 0; + ushort quantity = 0; + ushort opt = 0; + var type = (GiftType8A)Type!; + + if (type is GiftType8A.Clothing) + { + item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x08 * i))); + opt = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ClothingOffset + (0x08 * i))); + } + else + { + item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); + quantity = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); + } + + var gift = new OtherGift + { + Type = type, + Item = item, + Quantity = quantity, + Opt = opt, + }; + + if ((type is not GiftType8A.Clothing && gift.Item != ushort.MinValue) || (type is GiftType8A.Clothing && opt != ushort.MaxValue)) + items.Add(gift); + } + return items; + } + + public override bool IsChecksumValid() + { + if (Data is not null) + { + var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); + var span = Data.ToArray().AsSpan(); + BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); + var newchecksum = ChecksumCalculator.CalcCcittFalse(span); + if (oldChecksum == newchecksum) + return true; + } + return false; + } + + public override void UpdateChecksum() + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); + var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); + } + + public override void SetID(ushort wcid) + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); + WCID = wcid; + UpdateChecksum(); + } + + public override void SetRepeatable(bool repeatable) + { + Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); + IsRepeatable = repeatable; + UpdateChecksum(); + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/WB7.cs b/SwitchGiftDataManager.Core/Classes/WCManager/WB7.cs index 651b8bb..c54980a 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/WB7.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/WB7.cs @@ -1,124 +1,123 @@ using System.Buffers.Binary; using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class WB7 : Wondercard { - public class WB7 : Wondercard + private const int WondercardIDOffset = 0x208; + private const int GiftTypeOffset = 0x259; + private const int FlagOffset = 0x25A; + private const int ItemOffset = 0x270; + private const int QuantityOffset = 0x272; + private const int TIDOffset = 0x270; + private const int SIDOffset = 0x272; + private const int SpeciesOffset = 0x28A; + private const int ShinyTypeOffset = 0x2AB; + private const int PIDOffset = 0xD4; + private const int ChecksumOffset = 0x202; + + public WB7(ReadOnlySpan data) : base(data) { - private const int WondercardIDOffset = 0x208; - private const int GiftTypeOffset = 0x259; - private const int FlagOffset = 0x25A; - private const int ItemOffset = 0x270; - private const int QuantityOffset = 0x272; - private const int TIDOffset = 0x270; - private const int SIDOffset = 0x272; - private const int SpeciesOffset = 0x28A; - private const int ShinyTypeOffset = 0x2AB; - private const int PIDOffset = 0xD4; - private const int ChecksumOffset = 0x202; - - public WB7(ReadOnlySpan data) : base(data) + WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); + IsRepeatable = (Data![FlagOffset] & 1) == 0; + Type = (GiftType7)Data![GiftTypeOffset]; + Content = Type switch { - WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); - IsRepeatable = (Data![FlagOffset] & 1) == 0; - Type = (GiftType7)Data![GiftTypeOffset]; - Content = Type switch - { - GiftType7.Pokemon => GetPokemon(), - _ => GetItems(), - }; - } - - private PokemonGift GetPokemon() - { - var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); - var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); - var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); - var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); - var pidtype = (ShinyType7)Data![ShinyTypeOffset] switch - { - ShinyType7.Fixed => PIDType.FixedPID, - ShinyType7.ShinyRandom => PIDType.RandomPID, - ShinyType7.Shiny => PIDType.RandomPID, - ShinyType7.ShinyLocked => PIDType.RandomPID, - _ => throw new ArgumentOutOfRangeException(), - }; - var shinytype = (ShinyType7)Data![ShinyTypeOffset] switch - { - ShinyType7.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : - PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, - ShinyType7.ShinyRandom => ShinyType.ShinyPossible, - ShinyType7.Shiny => ShinyType.ShinyForced, - ShinyType7.ShinyLocked => ShinyType.ShinyLocked, - _ => throw new ArgumentOutOfRangeException(), - }; - - return new PokemonGift - { - Species = species, - PID = pid, - TID = tid, - SID = sid, - ShinyType = shinytype, - PIDType = pidtype, - }; - } - - private List GetItems() - { - List items = new(); - for (int i = 0; i < MaxItemCount; i++) - { - var type = (GiftType7)Type!; - var item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); - var quantity = type is GiftType7.BP ? item : BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); - - var gift = new OtherGift - { - Type = type, - Item = item, - Quantity = quantity, - }; - - if (gift.Item != 0) - items.Add(gift); - } - return items; - } - - public override bool IsChecksumValid() - { - if (Data is not null) - { - var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); - var span = Data.ToArray().AsSpan(); - BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); - var newchecksum = ChecksumCalculator.CalcCcittFalse(span); - if (oldChecksum == newchecksum) - return true; - } - return false; - } - - public override void UpdateChecksum() - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); - var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); - } - - public override void SetID(ushort wcid) - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); - WCID = wcid; - UpdateChecksum(); - } - - public override void SetRepeatable(bool repeatable) - { - Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); - IsRepeatable = repeatable; - UpdateChecksum(); - } + GiftType7.Pokemon => GetPokemon(), + _ => GetItems(), + }; } -} + + private PokemonGift GetPokemon() + { + var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); + var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); + var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); + var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); + var pidtype = (ShinyType7)Data![ShinyTypeOffset] switch + { + ShinyType7.Fixed => PIDType.FixedPID, + ShinyType7.ShinyRandom => PIDType.RandomPID, + ShinyType7.Shiny => PIDType.RandomPID, + ShinyType7.ShinyLocked => PIDType.RandomPID, + _ => throw new ArgumentOutOfRangeException(), + }; + var shinytype = (ShinyType7)Data![ShinyTypeOffset] switch + { + ShinyType7.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : + PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, + ShinyType7.ShinyRandom => ShinyType.ShinyPossible, + ShinyType7.Shiny => ShinyType.ShinyForced, + ShinyType7.ShinyLocked => ShinyType.ShinyLocked, + _ => throw new ArgumentOutOfRangeException(), + }; + + return new PokemonGift + { + Species = species, + PID = pid, + TID = tid, + SID = sid, + ShinyType = shinytype, + PIDType = pidtype, + }; + } + + private List GetItems() + { + List items = new(); + for (int i = 0; i < MaxItemCount; i++) + { + var type = (GiftType7)Type!; + var item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); + var quantity = type is GiftType7.BP ? item : BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); + + var gift = new OtherGift + { + Type = type, + Item = item, + Quantity = quantity, + }; + + if (gift.Item != ushort.MinValue) + items.Add(gift); + } + return items; + } + + public override bool IsChecksumValid() + { + if (Data is not null) + { + var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); + var span = Data.ToArray().AsSpan(); + BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); + var newchecksum = ChecksumCalculator.CalcCcittFalse(span); + if (oldChecksum == newchecksum) + return true; + } + return false; + } + + public override void UpdateChecksum() + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); + var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); + } + + public override void SetID(ushort wcid) + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); + WCID = wcid; + UpdateChecksum(); + } + + public override void SetRepeatable(bool repeatable) + { + Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); + IsRepeatable = repeatable; + UpdateChecksum(); + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/WB8.cs b/SwitchGiftDataManager.Core/Classes/WCManager/WB8.cs index a2d6718..73e919f 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/WB8.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/WB8.cs @@ -1,126 +1,125 @@ using System.Buffers.Binary; using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class WB8 : Wondercard { - public class WB8 : Wondercard + private const int WondercardIDOffset = 0x08; + private const int FlagOffset = 0x10; + private const int GiftTypeOffset = 0x11; + private const int ItemOffset = 0x20; + private const int QuantityOffset = 0x22; + private const int TIDOffset = 0x20; + private const int SIDOffset = 0x22; + private const int PIDOffset = 0x2C; + private const int SpeciesOffset = 0x288; + private const int ShinyTypeOffset = 0x290; + private const int ChecksumOffset = 0x2D0; + + public WB8(ReadOnlySpan data) : base(data) { - private const int WondercardIDOffset = 0x08; - private const int FlagOffset = 0x10; - private const int GiftTypeOffset = 0x11; - private const int ItemOffset = 0x20; - private const int QuantityOffset = 0x22; - private const int TIDOffset = 0x20; - private const int SIDOffset = 0x22; - private const int PIDOffset = 0x2C; - private const int SpeciesOffset = 0x288; - private const int ShinyTypeOffset = 0x290; - private const int ChecksumOffset = 0x2D0; - - public WB8(ReadOnlySpan data) : base(data) + WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); + IsRepeatable = (Data![FlagOffset] & 1) == 0; + Type = (GiftType8B)Data![GiftTypeOffset]; + Content = Type switch { - WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); - IsRepeatable = (Data![FlagOffset] & 1) == 0; - Type = (GiftType8B)Data![GiftTypeOffset]; - Content = Type switch - { - GiftType8B.Pokemon => GetPokemon(), - _ => GetItems(), - }; - } - - private PokemonGift GetPokemon() - { - var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); - var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); - var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); - var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); - var test = (ShinyType8)Data![ShinyTypeOffset]; - var pidtype = (ShinyType8)Data![ShinyTypeOffset] switch - { - ShinyType8.ShinyLocked => PIDType.RandomPID, - ShinyType8.ShinyRandom => PIDType.RandomPID, - ShinyType8.ShinyStar => PIDType.FixedPID, - ShinyType8.ShinySquare => PIDType.FixedPID, - ShinyType8.Fixed => PIDType.FixedPID, - _ => throw new ArgumentOutOfRangeException(), - }; - var shinytype = (ShinyType8)Data![ShinyTypeOffset] switch - { - ShinyType8.ShinyLocked => ShinyType.ShinyLocked, - ShinyType8.ShinyRandom => ShinyType.ShinyPossible, - ShinyType8.ShinyStar or ShinyType8.ShinySquare => ShinyType.ShinyForced, - ShinyType8.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : - PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, - _ => throw new ArgumentOutOfRangeException(), - }; - - return new PokemonGift - { - Species = species, - PID = pid, - TID = tid, - SID = sid, - ShinyType = shinytype, - PIDType = pidtype, - }; - } - - private List GetItems() - { - List items = new(); - for (int i = 0; i < MaxItemCount; i++) - { - var type = (GiftType8B)Type!; - var item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x10 * i))); - var quantity = type is GiftType8B.BP or GiftType8B.Money ? item : BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x10 * i))); - - var gift = new OtherGift - { - Type = Type, - Item = item, - Quantity = quantity, - }; - - if (gift.Item != 0) - items.Add(gift); - } - return items; - } - - public override bool IsChecksumValid() - { - if (Data is not null) - { - var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); - var span = Data.ToArray().AsSpan(); - BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); - var newchecksum = ChecksumCalculator.CalcCcittFalse(span); - if (oldChecksum == newchecksum) - return true; - } - return false; - } - - public override void UpdateChecksum() - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); - var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); - } - - public override void SetID(ushort wcid) - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); - WCID = wcid; - UpdateChecksum(); - } - - public override void SetRepeatable(bool repeatable) - { - Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); - IsRepeatable = repeatable; - UpdateChecksum(); - } + GiftType8B.Pokemon => GetPokemon(), + _ => GetItems(), + }; } -} + + private PokemonGift GetPokemon() + { + var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); + var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); + var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); + var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); + var test = (ShinyType8)Data![ShinyTypeOffset]; + var pidtype = (ShinyType8)Data![ShinyTypeOffset] switch + { + ShinyType8.ShinyLocked => PIDType.RandomPID, + ShinyType8.ShinyRandom => PIDType.RandomPID, + ShinyType8.ShinyStar => PIDType.FixedPID, + ShinyType8.ShinySquare => PIDType.FixedPID, + ShinyType8.Fixed => PIDType.FixedPID, + _ => throw new ArgumentOutOfRangeException(), + }; + var shinytype = (ShinyType8)Data![ShinyTypeOffset] switch + { + ShinyType8.ShinyLocked => ShinyType.ShinyLocked, + ShinyType8.ShinyRandom => ShinyType.ShinyPossible, + ShinyType8.ShinyStar or ShinyType8.ShinySquare => ShinyType.ShinyForced, + ShinyType8.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : + PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, + _ => throw new ArgumentOutOfRangeException(), + }; + + return new PokemonGift + { + Species = species, + PID = pid, + TID = tid, + SID = sid, + ShinyType = shinytype, + PIDType = pidtype, + }; + } + + private List GetItems() + { + List items = new(); + for (int i = 0; i < MaxItemCount; i++) + { + var type = (GiftType8B)Type!; + var item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x10 * i))); + var quantity = type is GiftType8B.BP or GiftType8B.Money ? item : BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x10 * i))); + + var gift = new OtherGift + { + Type = Type, + Item = item, + Quantity = quantity, + }; + + if (gift.Item != ushort.MinValue) + items.Add(gift); + } + return items; + } + + public override bool IsChecksumValid() + { + if (Data is not null) + { + var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); + var span = Data.ToArray().AsSpan(); + BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); + var newchecksum = ChecksumCalculator.CalcCcittFalse(span); + if (oldChecksum == newchecksum) + return true; + } + return false; + } + + public override void UpdateChecksum() + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); + var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); + } + + public override void SetID(ushort wcid) + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); + WCID = wcid; + UpdateChecksum(); + } + + public override void SetRepeatable(bool repeatable) + { + Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); + IsRepeatable = repeatable; + UpdateChecksum(); + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/WC8.cs b/SwitchGiftDataManager.Core/Classes/WCManager/WC8.cs index d9aa02e..c431e1b 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/WC8.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/WC8.cs @@ -1,140 +1,139 @@ using System.Buffers.Binary; using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class WC8 : Wondercard { - public class WC8 : Wondercard + private const int WondercardIDOffset = 0x08; + private const int FlagOffset = 0x10; + private const int GiftTypeOffset = 0x11; + private const int ItemOffset = 0x20; + private const int QuantityOffset = 0x22; + private const int ClothingOffset = 0x24; + private const int TIDOffset = 0x20; + private const int SIDOffset = 0x22; + private const int PIDOffset = 0x2C; + private const int SpeciesOffset = 0x240; + private const int ShinyTypeOffset = 0x248; + private const int ChecksumOffset = 0x2CC; + + public WC8(ReadOnlySpan data) : base(data) { - private const int WondercardIDOffset = 0x08; - private const int FlagOffset = 0x10; - private const int GiftTypeOffset = 0x11; - private const int ItemOffset = 0x20; - private const int QuantityOffset = 0x22; - private const int ClothingOffset = 0x24; - private const int TIDOffset = 0x20; - private const int SIDOffset = 0x22; - private const int PIDOffset = 0x2C; - private const int SpeciesOffset = 0x240; - private const int ShinyTypeOffset = 0x248; - private const int ChecksumOffset = 0x2CC; - - public WC8(ReadOnlySpan data) : base(data) + WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); + IsRepeatable = (Data![FlagOffset] & 1) == 0; + Type = (GiftType8)Data![GiftTypeOffset]; + Content = Type switch { - WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); - IsRepeatable = (Data![FlagOffset] & 1) == 0; - Type = (GiftType8)Data![GiftTypeOffset]; - Content = Type switch - { - GiftType8.Pokemon => GetPokemon(), - _ => GetItems(), - }; - } - - private PokemonGift GetPokemon() - { - var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); - var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); - var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); - var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); - var test = (ShinyType8)Data![ShinyTypeOffset]; - var pidtype = (ShinyType8)Data![ShinyTypeOffset] switch - { - ShinyType8.ShinyLocked => PIDType.RandomPID, - ShinyType8.ShinyRandom => PIDType.RandomPID, - ShinyType8.ShinyStar => PIDType.FixedPID, - ShinyType8.ShinySquare => PIDType.FixedPID, - ShinyType8.Fixed => PIDType.FixedPID, - _ => throw new ArgumentOutOfRangeException(), - }; - var shinytype = (ShinyType8)Data![ShinyTypeOffset] switch - { - ShinyType8.ShinyLocked => ShinyType.ShinyLocked, - ShinyType8.ShinyRandom => ShinyType.ShinyPossible, - ShinyType8.ShinyStar or ShinyType8.ShinySquare => ShinyType.ShinyForced, - ShinyType8.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : - PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, - _ => throw new ArgumentOutOfRangeException(), - }; - - return new PokemonGift - { - Species = species, - PID = pid, - TID = tid, - SID = sid, - ShinyType = shinytype, - PIDType = pidtype, - }; - } - - private List GetItems() - { - List items = new(); - for (int i = 0; i < MaxItemCount; i++) - { - ushort item = 0; - ushort quantity = 0; - ushort opt = 0; - var type = (GiftType8)Type!; - - if (type is GiftType8.Clothing) - { - item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x08 * i))); - opt = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ClothingOffset + (0x08 * i))); - } - else - { - item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); - quantity = type is GiftType8.BP or GiftType8.Money ? item : BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); - } - - var gift = new OtherGift - { - Type = type, - Item = item, - Quantity = quantity, - Opt = opt, - }; - - if (gift.Item != 0x00 && opt != 0xFFFF) - items.Add(gift); - } - return items; - } - - public override bool IsChecksumValid() - { - if (Data is not null) - { - var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); - var span = Data.ToArray().AsSpan(); - BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); - var newchecksum = ChecksumCalculator.CalcCcittFalse(span); - if (oldChecksum == newchecksum) - return true; - } - return false; - } - - public override void UpdateChecksum() - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); - var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); - } - - public override void SetID(ushort wcid) - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); - WCID = wcid; - UpdateChecksum(); - } - - public override void SetRepeatable(bool repeatable) - { - Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); - IsRepeatable = repeatable; - UpdateChecksum(); - } + GiftType8.Pokemon => GetPokemon(), + _ => GetItems(), + }; } -} + + private PokemonGift GetPokemon() + { + var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); + var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); + var tid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(TIDOffset)); + var sid = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SIDOffset)); + var test = (ShinyType8)Data![ShinyTypeOffset]; + var pidtype = (ShinyType8)Data![ShinyTypeOffset] switch + { + ShinyType8.ShinyLocked => PIDType.RandomPID, + ShinyType8.ShinyRandom => PIDType.RandomPID, + ShinyType8.ShinyStar => PIDType.FixedPID, + ShinyType8.ShinySquare => PIDType.FixedPID, + ShinyType8.Fixed => PIDType.FixedPID, + _ => throw new ArgumentOutOfRangeException(), + }; + var shinytype = (ShinyType8)Data![ShinyTypeOffset] switch + { + ShinyType8.ShinyLocked => ShinyType.ShinyLocked, + ShinyType8.ShinyRandom => ShinyType.ShinyPossible, + ShinyType8.ShinyStar or ShinyType8.ShinySquare => ShinyType.ShinyForced, + ShinyType8.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : + PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, + _ => throw new ArgumentOutOfRangeException(), + }; + + return new PokemonGift + { + Species = species, + PID = pid, + TID = tid, + SID = sid, + ShinyType = shinytype, + PIDType = pidtype, + }; + } + + private List GetItems() + { + List items = new(); + for (int i = 0; i < MaxItemCount; i++) + { + ushort item = 0; + ushort quantity = 0; + ushort opt = 0; + var type = (GiftType8)Type!; + + if (type is GiftType8.Clothing) + { + item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x08 * i))); + opt = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ClothingOffset + (0x08 * i))); + } + else + { + item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); + quantity = type is GiftType8.BP or GiftType8.Money ? item : BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); + } + + var gift = new OtherGift + { + Type = type, + Item = item, + Quantity = quantity, + Opt = opt, + }; + + if (gift.Item != ushort.MinValue && opt != ushort.MaxValue) + items.Add(gift); + } + return items; + } + + public override bool IsChecksumValid() + { + if (Data is not null) + { + var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); + var span = Data.ToArray().AsSpan(); + BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); + var newchecksum = ChecksumCalculator.CalcCcittFalse(span); + if (oldChecksum == newchecksum) + return true; + } + return false; + } + + public override void UpdateChecksum() + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); + var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); + } + + public override void SetID(ushort wcid) + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); + WCID = wcid; + UpdateChecksum(); + } + + public override void SetRepeatable(bool repeatable) + { + Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); + IsRepeatable = repeatable; + UpdateChecksum(); + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/WC9.cs b/SwitchGiftDataManager.Core/Classes/WCManager/WC9.cs index 519d3c4..4e5f43b 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/WC9.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/WC9.cs @@ -1,161 +1,159 @@ using System.Buffers.Binary; -using System.Reflection.PortableExecutable; using Enums; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public class WC9 : Wondercard { - public class WC9 : Wondercard + private const int WondercardIDOffset = 0x08; + private const int FlagOffset = 0x10; + private const int GiftTypeOffset = 0x11; + private const int ItemOffset = 0x18; + private const int QuantityOffset = 0x1A; + private const int ClothingOffset = 0x1C; + private const int TIDOffset = 0x18; + private const int PIDOffset = 0x24; + private const int SpeciesOffset = 0x238; + private const int ShinyTypeOffset = 0x240; + private const int ChecksumOffset = 0x2C4; + + public WC9(ReadOnlySpan data) : base(data) { - private const int WondercardIDOffset = 0x08; - private const int FlagOffset = 0x10; - private const int GiftTypeOffset = 0x11; - private const int ItemOffset = 0x18; - private const int QuantityOffset = 0x1A; - private const int ClothingOffset = 0x1C; - private const int TIDOffset = 0x18; - private const int PIDOffset = 0x24; - private const int SpeciesOffset = 0x238; - private const int ShinyTypeOffset = 0x240; - private const int ChecksumOffset = 0x2C4; - - public WC9(ReadOnlySpan data) : base(data) + WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); + IsRepeatable = (Data![FlagOffset] & 1) == 0; + Type = (GiftType9)Data![GiftTypeOffset]; + Content = Type switch { - WCID = BinaryPrimitives.ReadUInt16LittleEndian(data[WondercardIDOffset..]); - IsRepeatable = (Data![FlagOffset] & 1) == 0; - Type = (GiftType9)Data![GiftTypeOffset]; - Content = Type switch - { - GiftType9.Pokemon => GetPokemon(), - _ => GetItems(), - }; - } - - private PokemonGift GetPokemon() - { - var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); - var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); - var tid = (ushort)((BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(TIDOffset)) - (1000000u * WCID)) & 0xFFFF); - var sid = (ushort)((BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(TIDOffset)) - (1000000u * WCID)) >> 16 & 0xFFFF); - var test = (ShinyType9)Data![ShinyTypeOffset]; - var pidtype = (ShinyType9)Data![ShinyTypeOffset] switch - { - ShinyType9.ShinyLocked => PIDType.RandomPID, - ShinyType9.ShinyRandom => PIDType.RandomPID, - ShinyType9.ShinyStar => PIDType.FixedPID, - ShinyType9.ShinySquare => PIDType.FixedPID, - ShinyType9.Fixed => PIDType.FixedPID, - _ => throw new ArgumentOutOfRangeException(), - }; - var shinytype = (ShinyType9)Data![ShinyTypeOffset] switch - { - ShinyType9.ShinyLocked => ShinyType.ShinyLocked, - ShinyType9.ShinyRandom => ShinyType.ShinyPossible, - ShinyType9.ShinyStar or ShinyType9.ShinySquare => ShinyType.ShinyForced, - ShinyType9.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : - PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, - _ => throw new ArgumentOutOfRangeException(), - }; - - return new PokemonGift - { - Species = species, - PID = pid, - TID = tid, - SID = sid, - ShinyType = shinytype, - PIDType = pidtype, - }; - } - - private List GetItems() - { - List items = new(); - for (int i = 0; i < MaxItemCount; i++) - { - ushort item = 0; - uint quantity = 0; - ushort opt = 0; - var type = (GiftType9)Type!; - - if (type is GiftType9.Clothing) - { - item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x08 * i))); - opt = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ClothingOffset + (0x08 * i))); - } - else - { - item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); - quantity = type is GiftType9.LP ? BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))) : - BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); - } - - var gift = new OtherGift - { - Type = type, - Item = item, - Quantity = quantity, - Opt = opt, - }; - - if ((type is not GiftType9.Clothing && gift.Item != 0x00) || (type is GiftType9.Clothing && opt != 0xFFFF)) - items.Add(gift); - } - return items; - } - - public override bool IsChecksumValid() - { - if (Data is not null) - { - var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); - var span = Data.ToArray().AsSpan(); - BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); - var newchecksum = ChecksumCalculator.CalcCcittFalse(span); - if (oldChecksum == newchecksum) - return true; - } - return false; - } - - public override void UpdateChecksum() - { - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); - var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); - } - - public override void SetID(ushort wcid) - { - var pkEdited = false; - //Wondercard ID in Gen 9 also influence the TID and SID of Pokémon Entities - if (Type is GiftType9 t9 && t9 is GiftType9.Pokemon) - { - //Old FullTID - var ftid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(TIDOffset)) - (1000000u * (uint)WCID); - - //Recalculate the TID and SID (FullTID) to account for the new Wondercard ID - BinaryPrimitives.WriteUInt32LittleEndian(Data.AsSpan(TIDOffset), ftid + (1000000u * (uint)wcid)); - - pkEdited = true; - } - - //Write the new Wondercard ID - BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); - WCID = wcid; - - //Reload Pokémon content - if (pkEdited) - Content = GetPokemon(); - - //Refresh card checksum - UpdateChecksum(); - } - - public override void SetRepeatable(bool repeatable) - { - Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); - IsRepeatable = repeatable; - UpdateChecksum(); - } + GiftType9.Pokemon => GetPokemon(), + _ => GetItems(), + }; } -} + + private PokemonGift GetPokemon() + { + var species = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(SpeciesOffset)); + var pid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(PIDOffset)); + var tid = (ushort)((BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(TIDOffset)) - (1000000u * WCID)) & 0xFFFF); + var sid = (ushort)((BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(TIDOffset)) - (1000000u * WCID)) >> 16 & 0xFFFF); + var test = (ShinyType9)Data![ShinyTypeOffset]; + var pidtype = (ShinyType9)Data![ShinyTypeOffset] switch + { + ShinyType9.ShinyLocked => PIDType.RandomPID, + ShinyType9.ShinyRandom => PIDType.RandomPID, + ShinyType9.ShinyStar => PIDType.FixedPID, + ShinyType9.ShinySquare => PIDType.FixedPID, + ShinyType9.Fixed => PIDType.FixedPID, + _ => throw new ArgumentOutOfRangeException(), + }; + var shinytype = (ShinyType9)Data![ShinyTypeOffset] switch + { + ShinyType9.ShinyLocked => ShinyType.ShinyLocked, + ShinyType9.ShinyRandom => ShinyType.ShinyPossible, + ShinyType9.ShinyStar or ShinyType9.ShinySquare => ShinyType.ShinyForced, + ShinyType9.Fixed => PokemonGift.IsShiny(pid, tid, sid) ? ShinyType.ShinyForced : + PokemonGift.IsTIDAbusePossible(tid, sid, pidtype) ? ShinyType.ShinyTIDAbuse : ShinyType.ShinyLocked, + _ => throw new ArgumentOutOfRangeException(), + }; + + return new PokemonGift + { + Species = species, + PID = pid, + TID = tid, + SID = sid, + ShinyType = shinytype, + PIDType = pidtype, + }; + } + + private List GetItems() + { + List items = new(); + for (int i = 0; i < MaxItemCount; i++) + { + ushort item = 0; + uint quantity = 0; + ushort opt = 0; + var type = (GiftType9)Type!; + + if (type is GiftType9.Clothing) + { + item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x08 * i))); + opt = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ClothingOffset + (0x08 * i))); + } + else + { + item = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))); + quantity = type is GiftType9.LP ? BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(ItemOffset + (0x04 * i))) : + BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(QuantityOffset + (0x04 * i))); + } + + var gift = new OtherGift + { + Type = type, + Item = item, + Quantity = quantity, + Opt = opt, + }; + + if ((type is not GiftType9.Clothing && gift.Item != ushort.MinValue) || (type is GiftType9.Clothing && opt != ushort.MaxValue)) + items.Add(gift); + } + return items; + } + + public override bool IsChecksumValid() + { + if (Data is not null) + { + var oldChecksum = BinaryPrimitives.ReadUInt16LittleEndian(Data.AsSpan(ChecksumOffset)); + var span = Data.ToArray().AsSpan(); + BinaryPrimitives.WriteUInt16LittleEndian(span[ChecksumOffset..], 0x0); + var newchecksum = ChecksumCalculator.CalcCcittFalse(span); + if (oldChecksum == newchecksum) + return true; + } + return false; + } + + public override void UpdateChecksum() + { + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), 0x0); + var checksum = ChecksumCalculator.CalcCcittFalse(Data.AsSpan()); + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(ChecksumOffset), checksum); + } + + public override void SetID(ushort wcid) + { + var pkEdited = false; + //Wondercard ID in Gen 9 also influence the TID and SID of Pokémon Entities + if (Type is GiftType9 t9 && t9 is GiftType9.Pokemon) + { + //Old FullTID + var ftid = BinaryPrimitives.ReadUInt32LittleEndian(Data.AsSpan(TIDOffset)) - (1000000u * (uint)WCID); + + //Recalculate the TID and SID (FullTID) to account for the new Wondercard ID + BinaryPrimitives.WriteUInt32LittleEndian(Data.AsSpan(TIDOffset), ftid + (1000000u * (uint)wcid)); + + pkEdited = true; + } + + //Write the new Wondercard ID + BinaryPrimitives.WriteUInt16LittleEndian(Data.AsSpan(WondercardIDOffset), wcid); + WCID = wcid; + + //Reload Pokémon content + if (pkEdited) + Content = GetPokemon(); + + //Refresh card checksum + UpdateChecksum(); + } + + public override void SetRepeatable(bool repeatable) + { + Data![FlagOffset] = (byte)((Data![FlagOffset] & ~1) | (repeatable ? 0 : 1)); + IsRepeatable = repeatable; + UpdateChecksum(); + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Classes/WCManager/Wondercard.cs b/SwitchGiftDataManager.Core/Classes/WCManager/Wondercard.cs index 0230839..3ee434d 100644 --- a/SwitchGiftDataManager.Core/Classes/WCManager/Wondercard.cs +++ b/SwitchGiftDataManager.Core/Classes/WCManager/Wondercard.cs @@ -1,73 +1,73 @@ using Enums; using System.Buffers.Binary; -namespace SwitchGiftDataManager.Core +namespace SwitchGiftDataManager.Core; + +public abstract class Wondercard { - public abstract class Wondercard + public static int GenOffset = 0x0F; + protected const int MaxItemCount = 6; + + public Games Game { get; } + public ushort WCID { get; protected set; } + public bool IsRepeatable { get; protected set; } + public object? Type { get; protected set; } + public object? Content { get; protected set; } + public byte[]? Data { get; protected set; } + + public Wondercard(ReadOnlySpan data) { - public static int GenOffset = 0x0F; - protected const int MaxItemCount = 6; - - public Games Game { get; } - public ushort WCID { get; protected set; } - public bool IsRepeatable { get; protected set; } - public object? Type { get; protected set; } - public object? Content { get; protected set; } - public byte[]? Data { get; protected set; } - - public Wondercard(ReadOnlySpan data) + Game = (WondercardSize)data.Length switch { - Game = (WondercardSize)data.Length switch - { - WondercardSize.WB7 => Games.LGPE, - WondercardSize.WC8 => Games.SWSH, - WondercardSize.WB8 => Games.BDSP, - WondercardSize.WC9 => data[GenOffset] != 0 ? Games.PLA : Games.SCVI, - _ => Games.None, - }; - Data = data.ToArray(); - } + WondercardSize.WB7 => Games.LGPE, + WondercardSize.WC8 => Games.SWSH, + WondercardSize.WB8 => Games.BDSP, + WondercardSize.WA8 when data[GenOffset] != 0 => Games.PLA, + WondercardSize.WC9 when data[GenOffset] == 0 => Games.SCVI, + _ => Games.None, + }; + Data = data.ToArray(); + } - public bool IsValid() - { - if (WCID <= 0) - return false; + public bool IsValid() + { + if (WCID <= 0) + return false; - if (Content is null) - return false; + if (Content is null) + return false; #if DEBUG - if (!IsChecksumValid()) - UpdateChecksum(); + if (!IsChecksumValid()) + UpdateChecksum(); #endif - if (!IsChecksumValid()) - return false; + if (!IsChecksumValid()) + return false; - return true; - } - - public ReadOnlySpan CalcMetaChecksum() => ChecksumCalculator.CalcReverseMD5(Data!); - - public abstract bool IsChecksumValid(); - - public abstract void UpdateChecksum(); - - public abstract void SetID(ushort wcid); - - public abstract void SetRepeatable(bool repeatable); - - public static WondercardSize GetSize(Games game) - { - return game switch - { - Games.LGPE => WondercardSize.WB7, - Games.SWSH => WondercardSize.WC8, - Games.BDSP => WondercardSize.WB8, - Games.PLA => WondercardSize.WA8, - Games.SCVI => WondercardSize.WC9, - _ => throw new ArgumentOutOfRangeException(), - }; - } + return true; } -} + + public ReadOnlySpan CalcMetaChecksum() => ChecksumCalculator.CalcReverseMD5(Data!); + + public abstract bool IsChecksumValid(); + + public abstract void UpdateChecksum(); + + public abstract void SetID(ushort wcid); + + public abstract void SetRepeatable(bool repeatable); + + public static WondercardSize GetSize(Games game) + { + return game switch + { + Games.LGPE => WondercardSize.WB7, + Games.SWSH => WondercardSize.WC8, + Games.BDSP => WondercardSize.WB8, + Games.PLA => WondercardSize.WA8, + Games.SCVI => WondercardSize.WC9, + _ => throw new ArgumentOutOfRangeException(nameof(game)), + }; + } +} \ No newline at end of file diff --git a/SwitchGiftDataManager.Core/Enums/Enums.cs b/SwitchGiftDataManager.Core/Enums/Enums.cs index eb209f7..8d9b402 100644 --- a/SwitchGiftDataManager.Core/Enums/Enums.cs +++ b/SwitchGiftDataManager.Core/Enums/Enums.cs @@ -1,152 +1,152 @@ -namespace Enums { - public enum Games : int - { - None = 0, - LGPE = 1, - SWSH = 2, - BDSP = 3, - PLA = 4, - SCVI = 5, - } +namespace Enums; - public enum WCType - { - Pokemon, - Item, - } +public enum Games : int +{ + None = 0, + LGPE = 1, + SWSH = 2, + BDSP = 3, + PLA = 4, + SCVI = 5, +} - public enum WondercardSize : ushort - { - WB7 = 0x310, - WC8 = 0x2D0, - WB8 = 0x2DC, - WA8 = 0x2C8, - WC9 = 0x2C8, - } +public enum WCType +{ + Pokemon, + Item, +} - public enum GiftType7 : byte - { - Pokemon = 0, - Item = 1, - Bean = 2, - BP = 3, - } +public enum WondercardSize : ushort +{ + WB7 = 0x310, + WC8 = 0x2D0, + WB8 = 0x2DC, + WA8 = 0x2C8, + WC9 = 0x2C8, +} - public enum GiftType8 : byte - { - None = 0, - Pokemon = 1, - Item = 2, - BP = 3, - Clothing = 4, - Money = 5, - } +public enum GiftType7 : byte +{ + Pokemon = 0, + Item = 1, + Bean = 2, + BP = 3, +} - public enum GiftType8B : byte - { - None = 0, - Pokemon = 1, - Item = 2, - BP = 3, - Clothing = 4, - Money = 5, - Underground = 6, - } +public enum GiftType8 : byte +{ + None = 0, + Pokemon = 1, + Item = 2, + BP = 3, + Clothing = 4, + Money = 5, +} - public enum GiftType8A : byte - { - None = 0, - Pokemon = 1, - Item = 2, - Clothing = 3, - } +public enum GiftType8B : byte +{ + None = 0, + Pokemon = 1, + Item = 2, + BP = 3, + Clothing = 4, + Money = 5, + Underground = 6, +} - public enum GiftType9 : byte - { - None = 0, - Pokemon = 1, - Item = 2, - LP = 3, - Clothing = 4, - } +public enum GiftType8A : byte +{ + None = 0, + Pokemon = 1, + Item = 2, + Clothing = 3, +} - public enum PIDType - { - RandomPID, - FixedPID, - } +public enum GiftType9 : byte +{ + None = 0, + Pokemon = 1, + Item = 2, + LP = 3, + Clothing = 4, +} - public enum ShinyType - { - ShinyLocked, - ShinyPossible, - ShinyForced, - ShinyTIDAbuse, - ShinyHighOdds, - } +public enum PIDType +{ + RandomPID, + FixedPID, +} - public enum ShinyType7 : byte - { - Fixed = 0, - ShinyRandom = 1, - Shiny = 2, - ShinyLocked = 3, - } +public enum ShinyType +{ + ShinyLocked, + ShinyPossible, + ShinyForced, + ShinyTIDAbuse, + ShinyHighOdds, +} - public enum ShinyType8 : byte - { - ShinyLocked = 0, - ShinyRandom = 1, - ShinyStar = 2, - ShinySquare = 3, - Fixed = 4, - } +public enum ShinyType7 : byte +{ + Fixed = 0, + ShinyRandom = 1, + Shiny = 2, + ShinyLocked = 3, +} - public enum ShinyType9 : byte - { - ShinyLocked = 0, - ShinyRandom = 1, - ShinyStar = 2, - ShinySquare = 3, - Fixed = 4, - } +public enum ShinyType8 : byte +{ + ShinyLocked = 0, + ShinyRandom = 1, + ShinyStar = 2, + ShinySquare = 3, + Fixed = 4, +} - public enum ClothingType8: byte - { - Glasses = 0x06, - Hats = 0x07, - Jackets = 0x08, - Tops = 0x09, - Bags = 0x0A, - Gloves = 0x0B, - Bottoms = 0x0C, - Legwear = 0x0D, - Footwear = 0x0E, - None = 0xFF, - } +public enum ShinyType9 : byte +{ + ShinyLocked = 0, + ShinyRandom = 1, + ShinyStar = 2, + ShinySquare = 3, + Fixed = 4, +} - public enum ClothingType8A: byte - { - Headwear = 0x00, - Tops = 0x01, - Bottoms = 0x02, - Outfit = 0x03, - Footwear = 0x5, - Glasses = 0x06, - Eyewear = 0x08, - None = 0xFF, - } +public enum ClothingType8: byte +{ + Glasses = 0x06, + Hats = 0x07, + Jackets = 0x08, + Tops = 0x09, + Bags = 0x0A, + Gloves = 0x0B, + Bottoms = 0x0C, + Legwear = 0x0D, + Footwear = 0x0E, + None = 0xFF, +} - public enum ClothingType9 : byte - { - Uniform = 0x00, - Legwear = 0x01, - Footwear = 0x02, - Gloves = 0x03, - Bags = 0x04, - Headwear = 0x5, - Eyewear = 0x06, - PhoneCase = 0x08, - None = 0xFF, - } +public enum ClothingType8A: byte +{ + Headwear = 0x00, + Tops = 0x01, + Bottoms = 0x02, + Outfit = 0x03, + Footwear = 0x5, + Glasses = 0x06, + Eyewear = 0x08, + None = 0xFF, +} + +public enum ClothingType9 : byte +{ + Uniform = 0x00, + Legwear = 0x01, + Footwear = 0x02, + Gloves = 0x03, + Bags = 0x04, + Headwear = 0x5, + Eyewear = 0x06, + PhoneCase = 0x08, + None = 0xFF, } \ No newline at end of file diff --git a/SwitchGiftDataManager.WinForm/MainWindow.Designer.cs b/SwitchGiftDataManager.WinForm/MainWindow.Designer.cs index 119f8e7..dbe5de8 100644 --- a/SwitchGiftDataManager.WinForm/MainWindow.Designer.cs +++ b/SwitchGiftDataManager.WinForm/MainWindow.Designer.cs @@ -1,424 +1,423 @@ -namespace SwitchGiftDataManager.WinForm +namespace SwitchGiftDataManager.WinForm; + +partial class MainWindow { - partial class MainWindow + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) + if (disposing && (components != null)) { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); + components.Dispose(); } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); - BtnLGPE = new Button(); - BtnSWSH = new Button(); - BtnBDSP = new Button(); - BtnSCVI = new Button(); - BtnPLA = new Button(); - ListBoxWC = new ListBox(); - BtnOpen = new Button(); - BtnSave = new Button(); - GrpBCAT = new GroupBox(); - ChkRepeatable = new CheckBox(); - BtnApply = new Button(); - GrpContent = new GroupBox(); - LblInfo7 = new Label(); - LblInfo6 = new Label(); - LblInfo5 = new Label(); - LblInfo4 = new Label(); - LblInfo3 = new Label(); - LblInfo2 = new Label(); - LblInfo1 = new Label(); - TxtWCID = new TextBox(); - LblWCID = new Label(); - ContextMenuStripWC = new ContextMenuStrip(components); - BtnRemove = new ToolStripMenuItem(); - BtnRemoveAll = new ToolStripMenuItem(); - OpenFileDialogWC = new OpenFileDialog(); - ToolTipWcid = new ToolTip(components); - GrpBCAT.SuspendLayout(); - GrpContent.SuspendLayout(); - ContextMenuStripWC.SuspendLayout(); - SuspendLayout(); - // - // BtnLGPE - // - BtnLGPE.AccessibleDescription = ""; - BtnLGPE.AccessibleName = ""; - BtnLGPE.Cursor = Cursors.Hand; - BtnLGPE.FlatStyle = FlatStyle.Flat; - BtnLGPE.Location = new Point(5, 12); - BtnLGPE.Name = "BtnLGPE"; - BtnLGPE.Size = new Size(136, 60); - BtnLGPE.TabIndex = 0; - BtnLGPE.TabStop = false; - BtnLGPE.Text = "LGPE"; - BtnLGPE.UseVisualStyleBackColor = true; - BtnLGPE.Click += BtnLGPE_Click; - // - // BtnSWSH - // - BtnSWSH.AccessibleDescription = ""; - BtnSWSH.AccessibleName = ""; - BtnSWSH.Cursor = Cursors.Hand; - BtnSWSH.FlatStyle = FlatStyle.Flat; - BtnSWSH.Location = new Point(147, 12); - BtnSWSH.Name = "BtnSWSH"; - BtnSWSH.Size = new Size(136, 60); - BtnSWSH.TabIndex = 1; - BtnSWSH.TabStop = false; - BtnSWSH.Text = "SWSH"; - BtnSWSH.UseVisualStyleBackColor = true; - BtnSWSH.Click += BtnSWSH_Click; - // - // BtnBDSP - // - BtnBDSP.AccessibleDescription = ""; - BtnBDSP.AccessibleName = ""; - BtnBDSP.Cursor = Cursors.Hand; - BtnBDSP.FlatStyle = FlatStyle.Flat; - BtnBDSP.Location = new Point(289, 12); - BtnBDSP.Name = "BtnBDSP"; - BtnBDSP.Size = new Size(136, 60); - BtnBDSP.TabIndex = 2; - BtnBDSP.TabStop = false; - BtnBDSP.Text = "BDSP"; - BtnBDSP.UseVisualStyleBackColor = true; - BtnBDSP.Click += BtnBDSP_Click; - // - // BtnSCVI - // - BtnSCVI.AccessibleDescription = ""; - BtnSCVI.AccessibleName = ""; - BtnSCVI.Cursor = Cursors.Hand; - BtnSCVI.FlatStyle = FlatStyle.Flat; - BtnSCVI.Location = new Point(573, 12); - BtnSCVI.Name = "BtnSCVI"; - BtnSCVI.Size = new Size(136, 60); - BtnSCVI.TabIndex = 3; - BtnSCVI.TabStop = false; - BtnSCVI.Text = "SCVI"; - BtnSCVI.UseVisualStyleBackColor = true; - BtnSCVI.Click += BtnSCVI_Click; - // - // BtnPLA - // - BtnPLA.AccessibleDescription = ""; - BtnPLA.AccessibleName = ""; - BtnPLA.Cursor = Cursors.Hand; - BtnPLA.FlatStyle = FlatStyle.Flat; - BtnPLA.Location = new Point(431, 12); - BtnPLA.Name = "BtnPLA"; - BtnPLA.Size = new Size(136, 60); - BtnPLA.TabIndex = 4; - BtnPLA.TabStop = false; - BtnPLA.Text = "PLA"; - BtnPLA.UseVisualStyleBackColor = true; - BtnPLA.Click += BtnPLA_Click; - // - // ListBoxWC - // - ListBoxWC.AllowDrop = true; - ListBoxWC.DrawMode = DrawMode.OwnerDrawFixed; - ListBoxWC.FormattingEnabled = true; - ListBoxWC.ItemHeight = 20; - ListBoxWC.Location = new Point(7, 96); - ListBoxWC.Name = "ListBoxWC"; - ListBoxWC.Size = new Size(214, 304); - ListBoxWC.TabIndex = 5; - ToolTipWcid.SetToolTip(ListBoxWC, " Wondercards with duplicated WC ID will not be seen by the game. "); - ListBoxWC.DrawItem += ListBoxWC_DrawItem; - ListBoxWC.SelectedIndexChanged += ListBoxWC_SelectedIndexChanged; - ListBoxWC.DragDrop += FileDragDrop; - ListBoxWC.DragEnter += FileDragEnter; - ListBoxWC.MouseUp += ListBoxWC_MouseUp; - // - // BtnOpen - // - BtnOpen.Location = new Point(7, 26); - BtnOpen.Name = "BtnOpen"; - BtnOpen.Size = new Size(214, 29); - BtnOpen.TabIndex = 6; - BtnOpen.Text = "Open Wondercard Files..."; - BtnOpen.UseVisualStyleBackColor = true; - BtnOpen.Click += BtnOpen_Click; - // - // BtnSave - // - BtnSave.Enabled = false; - BtnSave.Location = new Point(6, 61); - BtnSave.Name = "BtnSave"; - BtnSave.Size = new Size(214, 29); - BtnSave.TabIndex = 7; - BtnSave.Text = "Save as BCAT Package..."; - BtnSave.UseVisualStyleBackColor = true; - BtnSave.Click += BtnSave_Click; - // - // GrpBCAT - // - GrpBCAT.Controls.Add(ChkRepeatable); - GrpBCAT.Controls.Add(BtnApply); - GrpBCAT.Controls.Add(GrpContent); - GrpBCAT.Controls.Add(TxtWCID); - GrpBCAT.Controls.Add(LblWCID); - GrpBCAT.Controls.Add(ListBoxWC); - GrpBCAT.Controls.Add(BtnSave); - GrpBCAT.Controls.Add(BtnOpen); - GrpBCAT.Enabled = false; - GrpBCAT.Location = new Point(5, 78); - GrpBCAT.Name = "GrpBCAT"; - GrpBCAT.Size = new Size(704, 409); - GrpBCAT.TabIndex = 8; - GrpBCAT.TabStop = false; - GrpBCAT.Text = "BCAT Manager"; - // - // ChkRepeatable - // - ChkRepeatable.AutoSize = true; - ChkRepeatable.Location = new Point(510, 69); - ChkRepeatable.Name = "ChkRepeatable"; - ChkRepeatable.Size = new Size(121, 24); - ChkRepeatable.TabIndex = 12; - ChkRepeatable.Text = "Is Repeatable"; - ChkRepeatable.UseVisualStyleBackColor = true; - ChkRepeatable.CheckedChanged += ChkRepeatable_CheckedChanged; - // - // BtnApply - // - BtnApply.Enabled = false; - BtnApply.Location = new Point(426, 368); - BtnApply.Name = "BtnApply"; - BtnApply.Size = new Size(97, 32); - BtnApply.TabIndex = 11; - BtnApply.Text = "Apply"; - BtnApply.UseVisualStyleBackColor = true; - BtnApply.Click += BtnApply_Click; - // - // GrpContent - // - GrpContent.Controls.Add(LblInfo7); - GrpContent.Controls.Add(LblInfo6); - GrpContent.Controls.Add(LblInfo5); - GrpContent.Controls.Add(LblInfo4); - GrpContent.Controls.Add(LblInfo3); - GrpContent.Controls.Add(LblInfo2); - GrpContent.Controls.Add(LblInfo1); - GrpContent.Enabled = false; - GrpContent.Location = new Point(294, 99); - GrpContent.Name = "GrpContent"; - GrpContent.Size = new Size(358, 263); - GrpContent.TabIndex = 10; - GrpContent.TabStop = false; - GrpContent.Text = "Gift Content"; - // - // LblInfo7 - // - LblInfo7.AutoSize = true; - LblInfo7.Location = new Point(158, 230); - LblInfo7.Name = "LblInfo7"; - LblInfo7.Size = new Size(49, 20); - LblInfo7.TabIndex = 6; - LblInfo7.Text = "Info_7"; - LblInfo7.Visible = false; - LblInfo7.SizeChanged += LblInfo_SizeChanged; - // - // LblInfo6 - // - LblInfo6.AutoSize = true; - LblInfo6.Location = new Point(158, 198); - LblInfo6.Name = "LblInfo6"; - LblInfo6.Size = new Size(49, 20); - LblInfo6.TabIndex = 5; - LblInfo6.Text = "Info_6"; - LblInfo6.Visible = false; - LblInfo6.SizeChanged += LblInfo_SizeChanged; - // - // LblInfo5 - // - LblInfo5.AutoSize = true; - LblInfo5.Location = new Point(158, 165); - LblInfo5.Name = "LblInfo5"; - LblInfo5.Size = new Size(49, 20); - LblInfo5.TabIndex = 4; - LblInfo5.Text = "Info_5"; - LblInfo5.Visible = false; - LblInfo5.SizeChanged += LblInfo_SizeChanged; - // - // LblInfo4 - // - LblInfo4.AutoSize = true; - LblInfo4.Location = new Point(158, 132); - LblInfo4.Name = "LblInfo4"; - LblInfo4.Size = new Size(49, 20); - LblInfo4.TabIndex = 3; - LblInfo4.Text = "Info_4"; - LblInfo4.Visible = false; - LblInfo4.SizeChanged += LblInfo_SizeChanged; - // - // LblInfo3 - // - LblInfo3.AutoSize = true; - LblInfo3.Location = new Point(158, 99); - LblInfo3.Name = "LblInfo3"; - LblInfo3.Size = new Size(49, 20); - LblInfo3.TabIndex = 2; - LblInfo3.Text = "Info_3"; - LblInfo3.Visible = false; - LblInfo3.SizeChanged += LblInfo_SizeChanged; - // - // LblInfo2 - // - LblInfo2.AutoSize = true; - LblInfo2.Location = new Point(158, 66); - LblInfo2.Name = "LblInfo2"; - LblInfo2.Size = new Size(49, 20); - LblInfo2.TabIndex = 1; - LblInfo2.Text = "Info_2"; - LblInfo2.Visible = false; - LblInfo2.SizeChanged += LblInfo_SizeChanged; - // - // LblInfo1 - // - LblInfo1.AutoSize = true; - LblInfo1.Location = new Point(158, 33); - LblInfo1.Name = "LblInfo1"; - LblInfo1.Size = new Size(49, 20); - LblInfo1.TabIndex = 0; - LblInfo1.Text = "Info_1"; - LblInfo1.Visible = false; - LblInfo1.SizeChanged += LblInfo_SizeChanged; - // - // TxtWCID - // - TxtWCID.Enabled = false; - TxtWCID.Location = new Point(379, 66); - TxtWCID.MaxLength = 4; - TxtWCID.Name = "TxtWCID"; - TxtWCID.Size = new Size(115, 27); - TxtWCID.TabIndex = 9; - TxtWCID.TextChanged += TxtWCID_TextChanged; - TxtWCID.KeyPress += TxtWCID_KeyPress; - // - // LblWCID - // - LblWCID.AutoSize = true; - LblWCID.Enabled = false; - LblWCID.Location = new Point(319, 69); - LblWCID.Name = "LblWCID"; - LblWCID.Size = new Size(54, 20); - LblWCID.TabIndex = 8; - LblWCID.Text = "WC ID:"; - // - // ContextMenuStripWC - // - ContextMenuStripWC.ImageScalingSize = new Size(20, 20); - ContextMenuStripWC.Items.AddRange(new ToolStripItem[] { BtnRemove, BtnRemoveAll }); - ContextMenuStripWC.Name = "ConextMenuStripWC"; - ContextMenuStripWC.Size = new Size(155, 52); - ContextMenuStripWC.Text = "Remove"; - // - // BtnRemove - // - BtnRemove.Name = "BtnRemove"; - BtnRemove.Size = new Size(154, 24); - BtnRemove.Text = "Remove"; - BtnRemove.Click += BtnRemove_Click; - // - // BtnRemoveAll - // - BtnRemoveAll.Name = "BtnRemoveAll"; - BtnRemoveAll.Size = new Size(154, 24); - BtnRemoveAll.Text = "Remove All"; - BtnRemoveAll.Click += BtnRemoveAll_Click; - // - // OpenFileDialogWC - // - OpenFileDialogWC.Multiselect = true; - // - // ToolTipWcid - // - ToolTipWcid.AutoPopDelay = 100000; - ToolTipWcid.InitialDelay = 500; - ToolTipWcid.OwnerDraw = true; - ToolTipWcid.ReshowDelay = 100; - ToolTipWcid.UseAnimation = false; - ToolTipWcid.UseFading = false; - ToolTipWcid.Draw += ToolTipWcid_Draw; - // - // MainWindow - // - AllowDrop = true; - AutoScaleDimensions = new SizeF(8F, 20F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(715, 495); - Controls.Add(GrpBCAT); - Controls.Add(BtnPLA); - Controls.Add(BtnSCVI); - Controls.Add(BtnBDSP); - Controls.Add(BtnSWSH); - Controls.Add(BtnLGPE); - Icon = (Icon)resources.GetObject("$this.Icon"); - MaximizeBox = false; - MinimizeBox = false; - Name = "MainWindow"; - Text = "Switch Gift Data Manager v"; - DragDrop += FileDragDrop; - DragEnter += FileDragEnter; - GrpBCAT.ResumeLayout(false); - GrpBCAT.PerformLayout(); - GrpContent.ResumeLayout(false); - GrpContent.PerformLayout(); - ContextMenuStripWC.ResumeLayout(false); - ResumeLayout(false); - } - - #endregion - - private Button BtnLGPE; - private Button BtnSWSH; - private Button BtnBDSP; - private Button BtnSCVI; - private Button BtnPLA; - private ListBox ListBoxWC; - private Button BtnOpen; - private Button BtnSave; - private GroupBox GrpBCAT; - private Button BtnApply; - private GroupBox GrpContent; - private TextBox TxtWCID; - private Label LblWCID; - private ContextMenuStrip ContextMenuStripWC; - private ToolStripMenuItem BtnRemove; - private Label LblInfo5; - private Label LblInfo4; - private Label LblInfo3; - private Label LblInfo2; - private Label LblInfo1; - private OpenFileDialog OpenFileDialogWC; - private ToolStripMenuItem BtnRemoveAll; - private ToolTip ToolTipWcid; - private Label LblInfo7; - private Label LblInfo6; - private CheckBox ChkRepeatable; + base.Dispose(disposing); } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); + BtnLGPE = new Button(); + BtnSWSH = new Button(); + BtnBDSP = new Button(); + BtnSCVI = new Button(); + BtnPLA = new Button(); + ListBoxWC = new ListBox(); + BtnOpen = new Button(); + BtnSave = new Button(); + GrpBCAT = new GroupBox(); + ChkRepeatable = new CheckBox(); + BtnApply = new Button(); + GrpContent = new GroupBox(); + LblInfo7 = new Label(); + LblInfo6 = new Label(); + LblInfo5 = new Label(); + LblInfo4 = new Label(); + LblInfo3 = new Label(); + LblInfo2 = new Label(); + LblInfo1 = new Label(); + TxtWCID = new TextBox(); + LblWCID = new Label(); + ContextMenuStripWC = new ContextMenuStrip(components); + BtnRemove = new ToolStripMenuItem(); + BtnRemoveAll = new ToolStripMenuItem(); + OpenFileDialogWC = new OpenFileDialog(); + ToolTipWcid = new ToolTip(components); + GrpBCAT.SuspendLayout(); + GrpContent.SuspendLayout(); + ContextMenuStripWC.SuspendLayout(); + SuspendLayout(); + // + // BtnLGPE + // + BtnLGPE.AccessibleDescription = ""; + BtnLGPE.AccessibleName = ""; + BtnLGPE.Cursor = Cursors.Hand; + BtnLGPE.FlatStyle = FlatStyle.Flat; + BtnLGPE.Location = new Point(5, 12); + BtnLGPE.Name = "BtnLGPE"; + BtnLGPE.Size = new Size(136, 60); + BtnLGPE.TabIndex = 0; + BtnLGPE.TabStop = false; + BtnLGPE.Text = "LGPE"; + BtnLGPE.UseVisualStyleBackColor = true; + BtnLGPE.Click += BtnLGPE_Click; + // + // BtnSWSH + // + BtnSWSH.AccessibleDescription = ""; + BtnSWSH.AccessibleName = ""; + BtnSWSH.Cursor = Cursors.Hand; + BtnSWSH.FlatStyle = FlatStyle.Flat; + BtnSWSH.Location = new Point(147, 12); + BtnSWSH.Name = "BtnSWSH"; + BtnSWSH.Size = new Size(136, 60); + BtnSWSH.TabIndex = 1; + BtnSWSH.TabStop = false; + BtnSWSH.Text = "SWSH"; + BtnSWSH.UseVisualStyleBackColor = true; + BtnSWSH.Click += BtnSWSH_Click; + // + // BtnBDSP + // + BtnBDSP.AccessibleDescription = ""; + BtnBDSP.AccessibleName = ""; + BtnBDSP.Cursor = Cursors.Hand; + BtnBDSP.FlatStyle = FlatStyle.Flat; + BtnBDSP.Location = new Point(289, 12); + BtnBDSP.Name = "BtnBDSP"; + BtnBDSP.Size = new Size(136, 60); + BtnBDSP.TabIndex = 2; + BtnBDSP.TabStop = false; + BtnBDSP.Text = "BDSP"; + BtnBDSP.UseVisualStyleBackColor = true; + BtnBDSP.Click += BtnBDSP_Click; + // + // BtnSCVI + // + BtnSCVI.AccessibleDescription = ""; + BtnSCVI.AccessibleName = ""; + BtnSCVI.Cursor = Cursors.Hand; + BtnSCVI.FlatStyle = FlatStyle.Flat; + BtnSCVI.Location = new Point(573, 12); + BtnSCVI.Name = "BtnSCVI"; + BtnSCVI.Size = new Size(136, 60); + BtnSCVI.TabIndex = 3; + BtnSCVI.TabStop = false; + BtnSCVI.Text = "SCVI"; + BtnSCVI.UseVisualStyleBackColor = true; + BtnSCVI.Click += BtnSCVI_Click; + // + // BtnPLA + // + BtnPLA.AccessibleDescription = ""; + BtnPLA.AccessibleName = ""; + BtnPLA.Cursor = Cursors.Hand; + BtnPLA.FlatStyle = FlatStyle.Flat; + BtnPLA.Location = new Point(431, 12); + BtnPLA.Name = "BtnPLA"; + BtnPLA.Size = new Size(136, 60); + BtnPLA.TabIndex = 4; + BtnPLA.TabStop = false; + BtnPLA.Text = "PLA"; + BtnPLA.UseVisualStyleBackColor = true; + BtnPLA.Click += BtnPLA_Click; + // + // ListBoxWC + // + ListBoxWC.AllowDrop = true; + ListBoxWC.DrawMode = DrawMode.OwnerDrawFixed; + ListBoxWC.FormattingEnabled = true; + ListBoxWC.ItemHeight = 20; + ListBoxWC.Location = new Point(7, 96); + ListBoxWC.Name = "ListBoxWC"; + ListBoxWC.Size = new Size(214, 304); + ListBoxWC.TabIndex = 5; + ToolTipWcid.SetToolTip(ListBoxWC, " Wondercards with duplicated WC ID will not be seen by the game. "); + ListBoxWC.DrawItem += ListBoxWC_DrawItem; + ListBoxWC.SelectedIndexChanged += ListBoxWC_SelectedIndexChanged; + ListBoxWC.DragDrop += FileDragDrop; + ListBoxWC.DragEnter += FileDragEnter; + ListBoxWC.MouseUp += ListBoxWC_MouseUp; + // + // BtnOpen + // + BtnOpen.Location = new Point(7, 26); + BtnOpen.Name = "BtnOpen"; + BtnOpen.Size = new Size(214, 29); + BtnOpen.TabIndex = 6; + BtnOpen.Text = "Open Wondercard Files..."; + BtnOpen.UseVisualStyleBackColor = true; + BtnOpen.Click += BtnOpen_Click; + // + // BtnSave + // + BtnSave.Enabled = false; + BtnSave.Location = new Point(6, 61); + BtnSave.Name = "BtnSave"; + BtnSave.Size = new Size(214, 29); + BtnSave.TabIndex = 7; + BtnSave.Text = "Save as BCAT Package..."; + BtnSave.UseVisualStyleBackColor = true; + BtnSave.Click += BtnSave_Click; + // + // GrpBCAT + // + GrpBCAT.Controls.Add(ChkRepeatable); + GrpBCAT.Controls.Add(BtnApply); + GrpBCAT.Controls.Add(GrpContent); + GrpBCAT.Controls.Add(TxtWCID); + GrpBCAT.Controls.Add(LblWCID); + GrpBCAT.Controls.Add(ListBoxWC); + GrpBCAT.Controls.Add(BtnSave); + GrpBCAT.Controls.Add(BtnOpen); + GrpBCAT.Enabled = false; + GrpBCAT.Location = new Point(5, 78); + GrpBCAT.Name = "GrpBCAT"; + GrpBCAT.Size = new Size(704, 409); + GrpBCAT.TabIndex = 8; + GrpBCAT.TabStop = false; + GrpBCAT.Text = "BCAT Manager"; + // + // ChkRepeatable + // + ChkRepeatable.AutoSize = true; + ChkRepeatable.Location = new Point(510, 69); + ChkRepeatable.Name = "ChkRepeatable"; + ChkRepeatable.Size = new Size(121, 24); + ChkRepeatable.TabIndex = 12; + ChkRepeatable.Text = "Is Repeatable"; + ChkRepeatable.UseVisualStyleBackColor = true; + ChkRepeatable.CheckedChanged += ChkRepeatable_CheckedChanged; + // + // BtnApply + // + BtnApply.Enabled = false; + BtnApply.Location = new Point(426, 368); + BtnApply.Name = "BtnApply"; + BtnApply.Size = new Size(97, 32); + BtnApply.TabIndex = 11; + BtnApply.Text = "Apply"; + BtnApply.UseVisualStyleBackColor = true; + BtnApply.Click += BtnApply_Click; + // + // GrpContent + // + GrpContent.Controls.Add(LblInfo7); + GrpContent.Controls.Add(LblInfo6); + GrpContent.Controls.Add(LblInfo5); + GrpContent.Controls.Add(LblInfo4); + GrpContent.Controls.Add(LblInfo3); + GrpContent.Controls.Add(LblInfo2); + GrpContent.Controls.Add(LblInfo1); + GrpContent.Enabled = false; + GrpContent.Location = new Point(294, 99); + GrpContent.Name = "GrpContent"; + GrpContent.Size = new Size(358, 263); + GrpContent.TabIndex = 10; + GrpContent.TabStop = false; + GrpContent.Text = "Gift Content"; + // + // LblInfo7 + // + LblInfo7.AutoSize = true; + LblInfo7.Location = new Point(158, 230); + LblInfo7.Name = "LblInfo7"; + LblInfo7.Size = new Size(49, 20); + LblInfo7.TabIndex = 6; + LblInfo7.Text = "Info_7"; + LblInfo7.Visible = false; + LblInfo7.SizeChanged += LblInfo_SizeChanged; + // + // LblInfo6 + // + LblInfo6.AutoSize = true; + LblInfo6.Location = new Point(158, 198); + LblInfo6.Name = "LblInfo6"; + LblInfo6.Size = new Size(49, 20); + LblInfo6.TabIndex = 5; + LblInfo6.Text = "Info_6"; + LblInfo6.Visible = false; + LblInfo6.SizeChanged += LblInfo_SizeChanged; + // + // LblInfo5 + // + LblInfo5.AutoSize = true; + LblInfo5.Location = new Point(158, 165); + LblInfo5.Name = "LblInfo5"; + LblInfo5.Size = new Size(49, 20); + LblInfo5.TabIndex = 4; + LblInfo5.Text = "Info_5"; + LblInfo5.Visible = false; + LblInfo5.SizeChanged += LblInfo_SizeChanged; + // + // LblInfo4 + // + LblInfo4.AutoSize = true; + LblInfo4.Location = new Point(158, 132); + LblInfo4.Name = "LblInfo4"; + LblInfo4.Size = new Size(49, 20); + LblInfo4.TabIndex = 3; + LblInfo4.Text = "Info_4"; + LblInfo4.Visible = false; + LblInfo4.SizeChanged += LblInfo_SizeChanged; + // + // LblInfo3 + // + LblInfo3.AutoSize = true; + LblInfo3.Location = new Point(158, 99); + LblInfo3.Name = "LblInfo3"; + LblInfo3.Size = new Size(49, 20); + LblInfo3.TabIndex = 2; + LblInfo3.Text = "Info_3"; + LblInfo3.Visible = false; + LblInfo3.SizeChanged += LblInfo_SizeChanged; + // + // LblInfo2 + // + LblInfo2.AutoSize = true; + LblInfo2.Location = new Point(158, 66); + LblInfo2.Name = "LblInfo2"; + LblInfo2.Size = new Size(49, 20); + LblInfo2.TabIndex = 1; + LblInfo2.Text = "Info_2"; + LblInfo2.Visible = false; + LblInfo2.SizeChanged += LblInfo_SizeChanged; + // + // LblInfo1 + // + LblInfo1.AutoSize = true; + LblInfo1.Location = new Point(158, 33); + LblInfo1.Name = "LblInfo1"; + LblInfo1.Size = new Size(49, 20); + LblInfo1.TabIndex = 0; + LblInfo1.Text = "Info_1"; + LblInfo1.Visible = false; + LblInfo1.SizeChanged += LblInfo_SizeChanged; + // + // TxtWCID + // + TxtWCID.Enabled = false; + TxtWCID.Location = new Point(379, 66); + TxtWCID.MaxLength = 4; + TxtWCID.Name = "TxtWCID"; + TxtWCID.Size = new Size(115, 27); + TxtWCID.TabIndex = 9; + TxtWCID.TextChanged += TxtWCID_TextChanged; + TxtWCID.KeyPress += TxtWCID_KeyPress; + // + // LblWCID + // + LblWCID.AutoSize = true; + LblWCID.Enabled = false; + LblWCID.Location = new Point(319, 69); + LblWCID.Name = "LblWCID"; + LblWCID.Size = new Size(54, 20); + LblWCID.TabIndex = 8; + LblWCID.Text = "WC ID:"; + // + // ContextMenuStripWC + // + ContextMenuStripWC.ImageScalingSize = new Size(20, 20); + ContextMenuStripWC.Items.AddRange(new ToolStripItem[] { BtnRemove, BtnRemoveAll }); + ContextMenuStripWC.Name = "ConextMenuStripWC"; + ContextMenuStripWC.Size = new Size(155, 52); + ContextMenuStripWC.Text = "Remove"; + // + // BtnRemove + // + BtnRemove.Name = "BtnRemove"; + BtnRemove.Size = new Size(154, 24); + BtnRemove.Text = "Remove"; + BtnRemove.Click += BtnRemove_Click; + // + // BtnRemoveAll + // + BtnRemoveAll.Name = "BtnRemoveAll"; + BtnRemoveAll.Size = new Size(154, 24); + BtnRemoveAll.Text = "Remove All"; + BtnRemoveAll.Click += BtnRemoveAll_Click; + // + // OpenFileDialogWC + // + OpenFileDialogWC.Multiselect = true; + // + // ToolTipWcid + // + ToolTipWcid.AutoPopDelay = 100000; + ToolTipWcid.InitialDelay = 500; + ToolTipWcid.OwnerDraw = true; + ToolTipWcid.ReshowDelay = 100; + ToolTipWcid.UseAnimation = false; + ToolTipWcid.UseFading = false; + ToolTipWcid.Draw += ToolTipWcid_Draw; + // + // MainWindow + // + AllowDrop = true; + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(715, 495); + Controls.Add(GrpBCAT); + Controls.Add(BtnPLA); + Controls.Add(BtnSCVI); + Controls.Add(BtnBDSP); + Controls.Add(BtnSWSH); + Controls.Add(BtnLGPE); + Icon = (Icon)resources.GetObject("$this.Icon"); + MaximizeBox = false; + MinimizeBox = false; + Name = "MainWindow"; + Text = "Switch Gift Data Manager v"; + DragDrop += FileDragDrop; + DragEnter += FileDragEnter; + GrpBCAT.ResumeLayout(false); + GrpBCAT.PerformLayout(); + GrpContent.ResumeLayout(false); + GrpContent.PerformLayout(); + ContextMenuStripWC.ResumeLayout(false); + ResumeLayout(false); + } + + #endregion + + private Button BtnLGPE; + private Button BtnSWSH; + private Button BtnBDSP; + private Button BtnSCVI; + private Button BtnPLA; + private ListBox ListBoxWC; + private Button BtnOpen; + private Button BtnSave; + private GroupBox GrpBCAT; + private Button BtnApply; + private GroupBox GrpContent; + private TextBox TxtWCID; + private Label LblWCID; + private ContextMenuStrip ContextMenuStripWC; + private ToolStripMenuItem BtnRemove; + private Label LblInfo5; + private Label LblInfo4; + private Label LblInfo3; + private Label LblInfo2; + private Label LblInfo1; + private OpenFileDialog OpenFileDialogWC; + private ToolStripMenuItem BtnRemoveAll; + private ToolTip ToolTipWcid; + private Label LblInfo7; + private Label LblInfo6; + private CheckBox ChkRepeatable; } \ No newline at end of file diff --git a/SwitchGiftDataManager.WinForm/MainWindow.cs b/SwitchGiftDataManager.WinForm/MainWindow.cs index 5af240f..2e847c9 100644 --- a/SwitchGiftDataManager.WinForm/MainWindow.cs +++ b/SwitchGiftDataManager.WinForm/MainWindow.cs @@ -3,450 +3,449 @@ using SwitchGiftDataManager.Core; using Enums; using System.Diagnostics; -namespace SwitchGiftDataManager.WinForm +namespace SwitchGiftDataManager.WinForm; + +public partial class MainWindow : Form { - public partial class MainWindow : Form + private Games CurrentGame = Games.None; + private BCATManager PackageLGPE = new(Games.LGPE); + private BCATManager PackageSWSH = new(Games.SWSH); + private BCATManager PackageBDSP = new(Games.BDSP); + private BCATManager PackagePLA = new(Games.PLA); + private BCATManager PackageSCVI = new(Games.SCVI); + private List Duplicated = new List(); + + public MainWindow() { - private Games CurrentGame = Games.None; - private BCATManager PackageLGPE = new(Games.LGPE); - private BCATManager PackageSWSH = new(Games.SWSH); - private BCATManager PackageBDSP = new(Games.BDSP); - private BCATManager PackagePLA = new(Games.PLA); - private BCATManager PackageSCVI = new(Games.SCVI); - private List Duplicated = new List(); + Task.Run(TryUpdate).Wait(); + InitializeComponent(); + Text += BCATManager.Version; + } - public MainWindow() + private static async Task TryUpdate() + { + if (await GitHubUtil.IsUpdateAvailable()) { - Task.Run(TryUpdate).Wait(); - InitializeComponent(); - Text += BCATManager.Version; + var result = MessageBox.Show("A program update is available. Do you want to download the latest release?", "Update available", MessageBoxButtons.YesNo); + if (result == DialogResult.Yes) + Process.Start(new ProcessStartInfo { FileName = @"https://github.com/Manu098vm/Switch-Gift-Data-Manager/releases", UseShellExecute = true }); } + } - private static async Task TryUpdate() + private void ChangeGame(Games game) + { + GrpBCAT.Enabled = true; + CurrentGame = game; + RestoreMenu(); + EditFileFilter(); + EditGameButton(); + UpdateWCList(); + ListBoxWC.SelectedIndex = -1; + DisableContent(); + } + + private void RestoreMenu() + { + BtnLGPE.Enabled = true; + BtnSWSH.Enabled = true; + BtnBDSP.Enabled = true; + BtnPLA.Enabled = true; + BtnSCVI.Enabled = true; + + BtnLGPE.Font = new Font(BtnLGPE.Font.Name, BtnLGPE.Font.Size, FontStyle.Regular); + BtnSWSH.Font = new Font(BtnSWSH.Font.Name, BtnSWSH.Font.Size, FontStyle.Regular); + BtnBDSP.Font = new Font(BtnBDSP.Font.Name, BtnBDSP.Font.Size, FontStyle.Regular); + BtnPLA.Font = new Font(BtnPLA.Font.Name, BtnPLA.Font.Size, FontStyle.Regular); + BtnSCVI.Font = new Font(BtnSCVI.Font.Name, BtnSCVI.Font.Size, FontStyle.Regular); + } + + private void EditFileFilter() + { + OpenFileDialogWC.Filter = CurrentGame switch { - if (await GitHubUtil.IsUpdateAvailable()) + Games.LGPE => "wb7full files (*.wb7full)|*.wb7full|All files (*.*)|*.*", + Games.SWSH => "wc8 files (*.wc8)|*.wc8|All files (*.*)|*.*", + Games.BDSP => "wb8 files (*.wb8)|*.wb8|All files (*.*)|*.*", + Games.PLA => "wa8 files (*.wa8)|*.wa8|All files (*.*)|*.*", + Games.SCVI => "wc9 files (*.wc9)|*.wc9|All files (*.*)|*.*", + _ => "All files (*.*)|*.*", + }; + } + + private void EditGameButton() + { + Button btn = CurrentGame switch + { + Games.LGPE => BtnLGPE, + Games.SWSH => BtnSWSH, + Games.BDSP => BtnBDSP, + Games.PLA => BtnPLA, + Games.SCVI => BtnSCVI, + _ => throw new ArgumentOutOfRangeException(), + }; + EditSelectedButton(btn); + } + + private void EditSelectedButton(Button btn) + { + btn.Font = new Font(btn.Font.Name, btn.Font.Size, FontStyle.Bold); + btn.Enabled = false; + } + + private void UpdateWCList() + { + if (ListBoxWC.Items.Count > 0) + ListBoxWC.Items.Clear(); + + var list = CurrentGame switch + { + Games.LGPE => PackageLGPE.GetListNames(), + Games.SWSH => PackageSWSH.GetListNames(), + Games.BDSP => PackageBDSP.GetListNames(), + Games.PLA => PackagePLA.GetListNames(), + Games.SCVI => PackageSCVI.GetListNames(), + _ => throw new ArgumentOutOfRangeException(), + }; + + UpdateDuplicatedList(); + + foreach (var el in list) + ListBoxWC.Items.Add(el); + + if (ListBoxWC.Items.Count > 0) + BtnSave.Enabled = true; + else + BtnSave.Enabled = false; + } + + private void UpdateDuplicatedList() + { + var list = GetCurrentList().GetDuplicatedWCID(); + if (list != null) + Duplicated = list; + else + Duplicated = new List { 0 }; + } + + private BCATManager GetCurrentList() + { + return CurrentGame switch + { + Games.LGPE => PackageLGPE, + Games.SWSH => PackageSWSH, + Games.BDSP => PackageBDSP, + Games.PLA => PackagePLA, + Games.SCVI => PackageSCVI, + _ => throw new ArgumentOutOfRangeException(), + }; + } + + private void LoadLocalFiles(string[] files) + { + DisableContent(); + var list = GetCurrentList(); + var errList = new List(); + foreach (var path in files) + { + var data = File.ReadAllBytes(path); + var success = list.TryAddWondercards(data.AsSpan()); + if (!success) { - var result = MessageBox.Show("A program update is available. Do you want to download the latest release?", "Update available", MessageBoxButtons.YesNo); - if (result == DialogResult.Yes) - Process.Start(new ProcessStartInfo { FileName = @"https://github.com/Manu098vm/Switch-Gift-Data-Manager/releases", UseShellExecute = true }); + if (errList.Count == 0) + if (CurrentGame is Games.LGPE && list.Count() >= 1) + errList.Add("LGPE only supports one (1) wondercard at a time. Aborted file(s):\n"); + else + errList.Add($"Attempted to load invalid files. Aborted file(s):\n"); + errList.Add($"- {Path.GetFileName(path)}"); } } - private void ChangeGame(Games game) + if (errList.Count > 0) { - GrpBCAT.Enabled = true; - CurrentGame = game; - RestoreMenu(); - EditFileFilter(); - EditGameButton(); - UpdateWCList(); - ListBoxWC.SelectedIndex = -1; - DisableContent(); + var msg = ""; + foreach (var err in errList) + msg = $"{msg}\n{err}"; + MessageBox.Show(msg); } - private void RestoreMenu() - { - BtnLGPE.Enabled = true; - BtnSWSH.Enabled = true; - BtnBDSP.Enabled = true; - BtnPLA.Enabled = true; - BtnSCVI.Enabled = true; + list.Sort(); + UpdateWCList(); + } - BtnLGPE.Font = new Font(BtnLGPE.Font.Name, BtnLGPE.Font.Size, FontStyle.Regular); - BtnSWSH.Font = new Font(BtnSWSH.Font.Name, BtnSWSH.Font.Size, FontStyle.Regular); - BtnBDSP.Font = new Font(BtnBDSP.Font.Name, BtnBDSP.Font.Size, FontStyle.Regular); - BtnPLA.Font = new Font(BtnPLA.Font.Name, BtnPLA.Font.Size, FontStyle.Regular); - BtnSCVI.Font = new Font(BtnSCVI.Font.Name, BtnSCVI.Font.Size, FontStyle.Regular); - } + private void BtnLGPE_Click(object sender, EventArgs e) => ChangeGame(Games.LGPE); - private void EditFileFilter() + private void BtnSWSH_Click(object sender, EventArgs e) => ChangeGame(Games.SWSH); + + private void BtnBDSP_Click(object sender, EventArgs e) => ChangeGame(Games.BDSP); + + private void BtnPLA_Click(object sender, EventArgs e) => ChangeGame(Games.PLA); + + private void BtnSCVI_Click(object sender, EventArgs e) => ChangeGame(Games.SCVI); + + private void BtnSave_Click(object sender, EventArgs e) + { + this.Enabled = false; + var saveForm = new SaveWindow(GetCurrentList(), CurrentGame); + saveForm.FormClosed += (s, e) => this.Enabled = true; + saveForm.Location = this.Location; + saveForm.Show(); + } + + private void BtnApply_Click(object sender, EventArgs e) + { + var list = GetCurrentList(); + var wcid = UInt16.Parse(TxtWCID.Text); + var repeatable = ChkRepeatable.Checked; + + if (wcid != list.GetWCID(ListBoxWC.SelectedIndex)) { - OpenFileDialogWC.Filter = CurrentGame switch + var index = list.GetIndex(wcid); + if (index == -1) { - Games.LGPE => "wb7full files (*.wb7full)|*.wb7full|All files (*.*)|*.*", - Games.SWSH => "wc8 files (*.wc8)|*.wc8|All files (*.*)|*.*", - Games.BDSP => "wb8 files (*.wb8)|*.wb8|All files (*.*)|*.*", - Games.PLA => "wa8 files (*.wa8)|*.wa8|All files (*.*)|*.*", - Games.SCVI => "wc9 files (*.wc9)|*.wc9|All files (*.*)|*.*", - _ => "All files (*.*)|*.*", - }; - } - - private void EditGameButton() - { - Button btn = CurrentGame switch - { - Games.LGPE => BtnLGPE, - Games.SWSH => BtnSWSH, - Games.BDSP => BtnBDSP, - Games.PLA => BtnPLA, - Games.SCVI => BtnSCVI, - _ => throw new ArgumentOutOfRangeException(), - }; - EditSelectedButton(btn); - } - - private void EditSelectedButton(Button btn) - { - btn.Font = new Font(btn.Font.Name, btn.Font.Size, FontStyle.Bold); - btn.Enabled = false; - } - - private void UpdateWCList() - { - if (ListBoxWC.Items.Count > 0) - ListBoxWC.Items.Clear(); - - var list = CurrentGame switch - { - Games.LGPE => PackageLGPE.GetListNames(), - Games.SWSH => PackageSWSH.GetListNames(), - Games.BDSP => PackageBDSP.GetListNames(), - Games.PLA => PackagePLA.GetListNames(), - Games.SCVI => PackageSCVI.GetListNames(), - _ => throw new ArgumentOutOfRangeException(), - }; - - UpdateDuplicatedList(); - - foreach (var el in list) - ListBoxWC.Items.Add(el); - - if (ListBoxWC.Items.Count > 0) - BtnSave.Enabled = true; - else - BtnSave.Enabled = false; - } - - private void UpdateDuplicatedList() - { - var list = GetCurrentList().GetDuplicatedWCID(); - if (list != null) - Duplicated = list; - else - Duplicated = new List { 0 }; - } - - private BCATManager GetCurrentList() - { - return CurrentGame switch - { - Games.LGPE => PackageLGPE, - Games.SWSH => PackageSWSH, - Games.BDSP => PackageBDSP, - Games.PLA => PackagePLA, - Games.SCVI => PackageSCVI, - _ => throw new ArgumentOutOfRangeException(), - }; - } - - private void LoadLocalFiles(string[] files) - { - DisableContent(); - var list = GetCurrentList(); - var errList = new List(); - foreach (var path in files) - { - var data = File.ReadAllBytes(path); - var success = list.TryAddWondercards(data.AsSpan()); - if (!success) - { - if (errList.Count == 0) - if (CurrentGame is Games.LGPE && list.Count() >= 1) - errList.Add("LGPE only supports one (1) wondercard at a time. Aborted file(s):\n"); - else - errList.Add($"Attempted to load invalid files. Aborted file(s):\n"); - errList.Add($"- {Path.GetFileName(path)}"); - } - } - - if (errList.Count > 0) - { - var msg = ""; - foreach (var err in errList) - msg = $"{msg}\n{err}"; - MessageBox.Show(msg); - } - - list.Sort(); - UpdateWCList(); - } - - private void BtnLGPE_Click(object sender, EventArgs e) => ChangeGame(Games.LGPE); - - private void BtnSWSH_Click(object sender, EventArgs e) => ChangeGame(Games.SWSH); - - private void BtnBDSP_Click(object sender, EventArgs e) => ChangeGame(Games.BDSP); - - private void BtnPLA_Click(object sender, EventArgs e) => ChangeGame(Games.PLA); - - private void BtnSCVI_Click(object sender, EventArgs e) => ChangeGame(Games.SCVI); - - private void BtnSave_Click(object sender, EventArgs e) - { - this.Enabled = false; - var saveForm = new SaveWindow(GetCurrentList(), CurrentGame); - saveForm.FormClosed += (s, e) => this.Enabled = true; - saveForm.Location = this.Location; - saveForm.Show(); - } - - private void BtnApply_Click(object sender, EventArgs e) - { - var list = GetCurrentList(); - var wcid = UInt16.Parse(TxtWCID.Text); - var repeatable = ChkRepeatable.Checked; - - if (wcid != list.GetWCID(ListBoxWC.SelectedIndex)) - { - var index = list.GetIndex(wcid); - if (index == -1) - { - list.SetWCID(ListBoxWC.SelectedIndex, wcid); - list.Sort(); - UpdateWCList(); - ListBoxWC.SelectedIndex = list.GetIndex(wcid); - BtnApply.Enabled = false; - } - else - { - MessageBox.Show($"WCID {wcid} already exists."); - return; - } - } - - if (repeatable != list.GetIsRepeatable(ListBoxWC.SelectedIndex)) - { - list.SetIsRepeatable(ListBoxWC.SelectedIndex, repeatable); + list.SetWCID(ListBoxWC.SelectedIndex, wcid); + list.Sort(); + UpdateWCList(); + ListBoxWC.SelectedIndex = list.GetIndex(wcid); BtnApply.Enabled = false; } - } - - private void BtnRemove_Click(object sender, EventArgs e) - { - var list = GetCurrentList(); - list.RemoveWC(ListBoxWC.SelectedIndex); - ListBoxWC.SelectedIndex = -1; - DisableContent(); - UpdateWCList(); - } - - private void BtnRemoveAll_Click(object sender, EventArgs e) - { - var list = GetCurrentList(); - list.Reset(); - ListBoxWC.SelectedIndex = -1; - DisableContent(); - UpdateWCList(); - } - - private void BtnOpen_Click(object sender, EventArgs e) - { - if (OpenFileDialogWC.ShowDialog() == DialogResult.OK) - LoadLocalFiles(OpenFileDialogWC.FileNames); - } - - void FileDragEnter(object sender, DragEventArgs e) - { - if (e.Data is not null && CurrentGame is not Games.None) - if (e.Data.GetDataPresent(DataFormats.FileDrop)) - e.Effect = DragDropEffects.Copy; - } - - void FileDragDrop(object sender, DragEventArgs e) - { - if (e.Data is not null && CurrentGame is not Games.None) + else { - string[] files = (string[])e.Data.GetData(DataFormats.FileDrop)!; - LoadLocalFiles(files); + MessageBox.Show($"WCID {wcid} already exists."); + return; } } - private void TxtWCID_KeyPress(object sender, KeyPressEventArgs e) + if (repeatable != list.GetIsRepeatable(ListBoxWC.SelectedIndex)) { - if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) - e.Handled = true; + list.SetIsRepeatable(ListBoxWC.SelectedIndex, repeatable); + BtnApply.Enabled = false; } + } - private void TxtWCID_TextChanged(object sender, EventArgs e) + private void BtnRemove_Click(object sender, EventArgs e) + { + var list = GetCurrentList(); + list.RemoveWC(ListBoxWC.SelectedIndex); + ListBoxWC.SelectedIndex = -1; + DisableContent(); + UpdateWCList(); + } + + private void BtnRemoveAll_Click(object sender, EventArgs e) + { + var list = GetCurrentList(); + list.Reset(); + ListBoxWC.SelectedIndex = -1; + DisableContent(); + UpdateWCList(); + } + + private void BtnOpen_Click(object sender, EventArgs e) + { + if (OpenFileDialogWC.ShowDialog() == DialogResult.OK) + LoadLocalFiles(OpenFileDialogWC.FileNames); + } + + void FileDragEnter(object sender, DragEventArgs e) + { + if (e.Data is not null && CurrentGame is not Games.None) + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + } + + void FileDragDrop(object sender, DragEventArgs e) + { + if (e.Data is not null && CurrentGame is not Games.None) { - if (!TxtWCID.Text.Equals("")) - { - var list = GetCurrentList(); - var newWcid = UInt16.Parse(TxtWCID.Text); - var oldWcid = list.GetWCID(ListBoxWC.SelectedIndex); - - if (oldWcid > 0 && newWcid > 0 && newWcid != oldWcid) - BtnApply.Enabled = true; - else - BtnApply.Enabled = false; - } + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop)!; + LoadLocalFiles(files); } + } - private void ChkRepeatable_CheckedChanged(object sender, EventArgs e) + private void TxtWCID_KeyPress(object sender, KeyPressEventArgs e) + { + if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) + e.Handled = true; + } + + private void TxtWCID_TextChanged(object sender, EventArgs e) + { + if (!TxtWCID.Text.Equals("")) { var list = GetCurrentList(); - var newBool = ChkRepeatable.Checked; - var oldBool = list.GetIsRepeatable(ListBoxWC.SelectedIndex); + var newWcid = UInt16.Parse(TxtWCID.Text); + var oldWcid = list.GetWCID(ListBoxWC.SelectedIndex); - if (newBool != oldBool) + if (oldWcid > 0 && newWcid > 0 && newWcid != oldWcid) BtnApply.Enabled = true; else BtnApply.Enabled = false; } + } - private void ToolTipWcid_Draw(object sender, DrawToolTipEventArgs e) + private void ChkRepeatable_CheckedChanged(object sender, EventArgs e) + { + var list = GetCurrentList(); + var newBool = ChkRepeatable.Checked; + var oldBool = list.GetIsRepeatable(ListBoxWC.SelectedIndex); + + if (newBool != oldBool) + BtnApply.Enabled = true; + else + BtnApply.Enabled = false; + } + + private void ToolTipWcid_Draw(object sender, DrawToolTipEventArgs e) + { + Point screenPosition = ListBox.MousePosition; + Point listBoxClientAreaPosition = ListBoxWC.PointToClient(screenPosition); + int hoveredIndex = ListBoxWC.IndexFromPoint(listBoxClientAreaPosition); + if (hoveredIndex > -1) { - Point screenPosition = ListBox.MousePosition; - Point listBoxClientAreaPosition = ListBoxWC.PointToClient(screenPosition); - int hoveredIndex = ListBoxWC.IndexFromPoint(listBoxClientAreaPosition); - if (hoveredIndex > -1) - { - var str = ListBoxWC.Items[hoveredIndex].ToString()!; - if (str.Contains('\u26A0')) - { - var msg = "Wondercards with duplicated identifiers may cause issues and will not be seen by the game."; - e.DrawBackground(); - Graphics g = e.Graphics; - g.DrawString(msg, e.Font!, new SolidBrush(Color.Black), new PointF(e.Bounds.X, e.Bounds.Y)); - } - else if (str.Contains('\u2757')) - { - var msg = "Wondercard count is above the maximum allowed, or the WCID is over the maximum allowed."; - e.DrawBackground(); - Graphics g = e.Graphics; - g.DrawString(msg, e.Font!, new SolidBrush(Color.Black), new PointF(e.Bounds.X, e.Bounds.Y)); - } - else - { - ToolTipWcid.Hide(ListBoxWC); - } - } - else - ToolTipWcid.Hide(ListBoxWC); - } - - private void ListBoxWC_MouseUp(object sender, MouseEventArgs e) - { - if (e.Button == MouseButtons.Right) - { - var index = ListBoxWC.IndexFromPoint(e.X, e.Y); - if (index >= 0) - { - ListBoxWC.SelectedIndex = index; - ContextMenuStripWC.Show(Cursor.Position); - } - } - } - - private void ListBoxWC_SelectedIndexChanged(object sender, EventArgs e) - { - if (ListBoxWC.SelectedIndex > -1) - { - var list = GetCurrentList(); - var index = ListBoxWC.SelectedIndex; - var content = list.GetContentToString(index); - var nItem = content.Count(); - if (nItem >= 1) - LblInfo1.Text = content.ElementAt(1); - if (nItem >= 2) - LblInfo2.Text = content.ElementAt(2); - if (nItem >= 3) - LblInfo3.Text = content.ElementAt(3); - if (nItem >= 4) - LblInfo4.Text = content.ElementAt(4); - if (nItem >= 5) - LblInfo5.Text = content.ElementAt(5); - if (nItem >= 6) - LblInfo6.Text = content.ElementAt(6); - if (nItem >= 7) - LblInfo7.Text = content.ElementAt(7); - - TxtWCID.Text = content.ElementAt(0); - ChkRepeatable.Checked = list.GetIsRepeatable(index); - EnableContent(); - } - else - DisableContent(); - } - - private void ListBoxWC_DrawItem(object sender, DrawItemEventArgs e) - { - if (e.Index > -1) + var str = ListBoxWC.Items[hoveredIndex].ToString()!; + if (str.Contains('\u26A0')) { + var msg = "Wondercards with duplicated identifiers may cause issues and will not be seen by the game."; e.DrawBackground(); Graphics g = e.Graphics; - var curr = ((ListBox)sender).Items[e.Index].ToString()!; - var wcid = UInt16.Parse(Regex.Match(curr, @"(?<=\#)(.*?)(?=\:)").Groups[1].Value); - var handled = false; - if ((CurrentGame is Games.BDSP && wcid >= 2048) || (CurrentGame is Games.SWSH && e.Index >= 129)) + g.DrawString(msg, e.Font!, new SolidBrush(Color.Black), new PointF(e.Bounds.X, e.Bounds.Y)); + } + else if (str.Contains('\u2757')) + { + var msg = "Wondercard count is above the maximum allowed, or the WCID is over the maximum allowed."; + e.DrawBackground(); + Graphics g = e.Graphics; + g.DrawString(msg, e.Font!, new SolidBrush(Color.Black), new PointF(e.Bounds.X, e.Bounds.Y)); + } + else + { + ToolTipWcid.Hide(ListBoxWC); + } + } + else + ToolTipWcid.Hide(ListBoxWC); + } + + private void ListBoxWC_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + var index = ListBoxWC.IndexFromPoint(e.X, e.Y); + if (index >= 0) + { + ListBoxWC.SelectedIndex = index; + ContextMenuStripWC.Show(Cursor.Position); + } + } + } + + private void ListBoxWC_SelectedIndexChanged(object sender, EventArgs e) + { + if (ListBoxWC.SelectedIndex > -1) + { + var list = GetCurrentList(); + var index = ListBoxWC.SelectedIndex; + var content = list.GetContentToString(index); + var nItem = content.Count(); + if (nItem >= 1) + LblInfo1.Text = content.ElementAt(1); + if (nItem >= 2) + LblInfo2.Text = content.ElementAt(2); + if (nItem >= 3) + LblInfo3.Text = content.ElementAt(3); + if (nItem >= 4) + LblInfo4.Text = content.ElementAt(4); + if (nItem >= 5) + LblInfo5.Text = content.ElementAt(5); + if (nItem >= 6) + LblInfo6.Text = content.ElementAt(6); + if (nItem >= 7) + LblInfo7.Text = content.ElementAt(7); + + TxtWCID.Text = content.ElementAt(0); + ChkRepeatable.Checked = list.GetIsRepeatable(index); + EnableContent(); + } + else + DisableContent(); + } + + private void ListBoxWC_DrawItem(object sender, DrawItemEventArgs e) + { + if (e.Index > -1) + { + e.DrawBackground(); + Graphics g = e.Graphics; + var curr = ((ListBox)sender).Items[e.Index].ToString()!; + var wcid = UInt16.Parse(Regex.Match(curr, @"(?<=\#)(.*?)(?=\:)").Groups[1].Value); + var handled = false; + if ((CurrentGame is Games.BDSP && wcid >= 2048) || (CurrentGame is Games.SWSH && e.Index >= 129)) + { + if (!curr.Contains('\u2757')) + ((ListBox)sender).Items[e.Index] = $"{curr} \u2757"; + g.FillRectangle(new SolidBrush(Color.IndianRed), e.Bounds); + g.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font!, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y)); + handled = true; + } + foreach (var d in Duplicated) + { + if (d == wcid) { - if (!curr.Contains('\u2757')) - ((ListBox)sender).Items[e.Index] = $"{curr} \u2757"; - g.FillRectangle(new SolidBrush(Color.IndianRed), e.Bounds); + if (!curr.Contains('\u26A0')) + ((ListBox)sender).Items[e.Index] = $"{curr} \u26A0"; + g.FillRectangle(new SolidBrush(Color.Orange), e.Bounds); g.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font!, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y)); handled = true; } - foreach (var d in Duplicated) - { - if (d == wcid) - { - if (!curr.Contains('\u26A0')) - ((ListBox)sender).Items[e.Index] = $"{curr} \u26A0"; - g.FillRectangle(new SolidBrush(Color.Orange), e.Bounds); - g.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font!, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y)); - handled = true; - } - } - if (!handled) - g.DrawString(curr, e.Font!, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y)); } - } - - private void LblInfo_SizeChanged(object sender, EventArgs e) - { - var lbl = (Label)sender; - lbl.Left = (GrpContent.Width - lbl.Width) / 2; - } - - private void EnableContent() - { - TxtWCID.Enabled = true; - LblWCID.Enabled = true; - LblInfo1.Visible = true; - LblInfo2.Visible = true; - LblInfo3.Visible = true; - LblInfo4.Visible = true; - LblInfo5.Visible = true; - LblInfo6.Visible = true; - LblInfo7.Visible = true; - GrpContent.Enabled = true; - ChkRepeatable.Enabled = true; - } - - private void DisableContent() - { - TxtWCID.Text = ""; - TxtWCID.Enabled = false; - LblWCID.Enabled = false; - LblInfo1.Text = ""; - LblInfo1.Visible = false; - LblInfo2.Text = ""; - LblInfo2.Visible = false; - LblInfo3.Text = ""; - LblInfo3.Visible = false; - LblInfo4.Text = ""; - LblInfo4.Visible = false; - LblInfo5.Text = ""; - LblInfo5.Visible = false; - LblInfo6.Text = ""; - LblInfo6.Visible = false; - LblInfo7.Text = ""; - LblInfo7.Visible = false; - BtnApply.Enabled = false; - GrpContent.Enabled = false; - ChkRepeatable.Checked = false; - ChkRepeatable.Enabled = false; + if (!handled) + g.DrawString(curr, e.Font!, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y)); } } + + private void LblInfo_SizeChanged(object sender, EventArgs e) + { + var lbl = (Label)sender; + lbl.Left = (GrpContent.Width - lbl.Width) / 2; + } + + private void EnableContent() + { + TxtWCID.Enabled = true; + LblWCID.Enabled = true; + LblInfo1.Visible = true; + LblInfo2.Visible = true; + LblInfo3.Visible = true; + LblInfo4.Visible = true; + LblInfo5.Visible = true; + LblInfo6.Visible = true; + LblInfo7.Visible = true; + GrpContent.Enabled = true; + ChkRepeatable.Enabled = true; + } + + private void DisableContent() + { + TxtWCID.Text = ""; + TxtWCID.Enabled = false; + LblWCID.Enabled = false; + LblInfo1.Text = ""; + LblInfo1.Visible = false; + LblInfo2.Text = ""; + LblInfo2.Visible = false; + LblInfo3.Text = ""; + LblInfo3.Visible = false; + LblInfo4.Text = ""; + LblInfo4.Visible = false; + LblInfo5.Text = ""; + LblInfo5.Visible = false; + LblInfo6.Text = ""; + LblInfo6.Visible = false; + LblInfo7.Text = ""; + LblInfo7.Visible = false; + BtnApply.Enabled = false; + GrpContent.Enabled = false; + ChkRepeatable.Checked = false; + ChkRepeatable.Enabled = false; + } } \ No newline at end of file diff --git a/SwitchGiftDataManager.WinForm/SaveWindow.Designer.cs b/SwitchGiftDataManager.WinForm/SaveWindow.Designer.cs index ba3bd0d..ed4c51b 100644 --- a/SwitchGiftDataManager.WinForm/SaveWindow.Designer.cs +++ b/SwitchGiftDataManager.WinForm/SaveWindow.Designer.cs @@ -1,201 +1,200 @@ -namespace SwitchGiftDataManager.WinForm +namespace SwitchGiftDataManager.WinForm; + +partial class SaveWindow { - partial class SaveWindow + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) + if (disposing && (components != null)) { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); + components.Dispose(); } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SaveWindow)); - this.GrpBuild = new System.Windows.Forms.GroupBox(); - this.RadioUnique = new System.Windows.Forms.RadioButton(); - this.RadioMultiple = new System.Windows.Forms.RadioButton(); - this.TxtDestPath = new System.Windows.Forms.TextBox(); - this.BtnPath = new System.Windows.Forms.Button(); - this.GrpDest = new System.Windows.Forms.GroupBox(); - this.BtnCancel = new System.Windows.Forms.Button(); - this.BtnSave = new System.Windows.Forms.Button(); - this.FolderBrowser = new System.Windows.Forms.FolderBrowserDialog(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.BtnSrcBrowse = new System.Windows.Forms.Button(); - this.TxtSourcePath = new System.Windows.Forms.TextBox(); - this.GrpBuild.SuspendLayout(); - this.GrpDest.SuspendLayout(); - this.groupBox2.SuspendLayout(); - this.SuspendLayout(); - // - // GrpBuild - // - this.GrpBuild.Controls.Add(this.RadioUnique); - this.GrpBuild.Controls.Add(this.RadioMultiple); - this.GrpBuild.Location = new System.Drawing.Point(12, 12); - this.GrpBuild.Name = "GrpBuild"; - this.GrpBuild.Size = new System.Drawing.Size(458, 58); - this.GrpBuild.TabIndex = 0; - this.GrpBuild.TabStop = false; - this.GrpBuild.Text = "Build Method"; - // - // RadioUnique - // - this.RadioUnique.AutoSize = true; - this.RadioUnique.Location = new System.Drawing.Point(238, 26); - this.RadioUnique.Name = "RadioUnique"; - this.RadioUnique.Size = new System.Drawing.Size(156, 24); - this.RadioUnique.TabIndex = 1; - this.RadioUnique.Text = "Keep separate files"; - this.RadioUnique.UseVisualStyleBackColor = true; - // - // RadioMultiple - // - this.RadioMultiple.AutoSize = true; - this.RadioMultiple.Checked = true; - this.RadioMultiple.Location = new System.Drawing.Point(76, 26); - this.RadioMultiple.Name = "RadioMultiple"; - this.RadioMultiple.Size = new System.Drawing.Size(145, 24); - this.RadioMultiple.TabIndex = 0; - this.RadioMultiple.TabStop = true; - this.RadioMultiple.Text = "Merge as one file"; - this.RadioMultiple.UseVisualStyleBackColor = true; - // - // TxtDestPath - // - this.TxtDestPath.Location = new System.Drawing.Point(6, 26); - this.TxtDestPath.Name = "TxtDestPath"; - this.TxtDestPath.Size = new System.Drawing.Size(358, 27); - this.TxtDestPath.TabIndex = 1; - // - // BtnPath - // - this.BtnPath.Location = new System.Drawing.Point(370, 26); - this.BtnPath.Name = "BtnPath"; - this.BtnPath.Size = new System.Drawing.Size(82, 29); - this.BtnPath.TabIndex = 2; - this.BtnPath.Text = "Browse"; - this.BtnPath.UseVisualStyleBackColor = true; - this.BtnPath.Click += new System.EventHandler(this.BtnPath_Click); - // - // GrpDest - // - this.GrpDest.Controls.Add(this.TxtDestPath); - this.GrpDest.Controls.Add(this.BtnPath); - this.GrpDest.Location = new System.Drawing.Point(12, 153); - this.GrpDest.Name = "GrpDest"; - this.GrpDest.Size = new System.Drawing.Size(458, 66); - this.GrpDest.TabIndex = 3; - this.GrpDest.TabStop = false; - this.GrpDest.Text = "Destination BCAT Path"; - // - // BtnCancel - // - this.BtnCancel.Location = new System.Drawing.Point(99, 225); - this.BtnCancel.Name = "BtnCancel"; - this.BtnCancel.Size = new System.Drawing.Size(125, 29); - this.BtnCancel.TabIndex = 4; - this.BtnCancel.Text = "Cancel"; - this.BtnCancel.UseVisualStyleBackColor = true; - this.BtnCancel.Click += new System.EventHandler(this.BtnCancel_Click); - // - // BtnSave - // - this.BtnSave.Location = new System.Drawing.Point(250, 225); - this.BtnSave.Name = "BtnSave"; - this.BtnSave.Size = new System.Drawing.Size(125, 29); - this.BtnSave.TabIndex = 5; - this.BtnSave.Text = "Save"; - this.BtnSave.UseVisualStyleBackColor = true; - this.BtnSave.Click += new System.EventHandler(this.BtnSave_Click); - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.BtnSrcBrowse); - this.groupBox2.Controls.Add(this.TxtSourcePath); - this.groupBox2.Location = new System.Drawing.Point(12, 76); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(458, 66); - this.groupBox2.TabIndex = 6; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "Source BCAT Path"; - // - // BtnSrcBrowse - // - this.BtnSrcBrowse.Location = new System.Drawing.Point(370, 26); - this.BtnSrcBrowse.Name = "BtnSrcBrowse"; - this.BtnSrcBrowse.Size = new System.Drawing.Size(82, 27); - this.BtnSrcBrowse.TabIndex = 1; - this.BtnSrcBrowse.Text = "Browse"; - this.BtnSrcBrowse.UseVisualStyleBackColor = true; - this.BtnSrcBrowse.Click += new System.EventHandler(this.BtnSrcBrowse_Click); - // - // TxtSourcePath - // - this.TxtSourcePath.Location = new System.Drawing.Point(6, 26); - this.TxtSourcePath.Name = "TxtSourcePath"; - this.TxtSourcePath.Size = new System.Drawing.Size(358, 27); - this.TxtSourcePath.TabIndex = 0; - // - // SaveWindow - // - this.AcceptButton = this.BtnSave; - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.BtnCancel; - this.ClientSize = new System.Drawing.Size(483, 261); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.BtnSave); - this.Controls.Add(this.BtnCancel); - this.Controls.Add(this.GrpDest); - this.Controls.Add(this.GrpBuild); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "SaveWindow"; - this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; - this.Text = "Save BCAT Package"; - this.GrpBuild.ResumeLayout(false); - this.GrpBuild.PerformLayout(); - this.GrpDest.ResumeLayout(false); - this.GrpDest.PerformLayout(); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.ResumeLayout(false); - - } - - #endregion - - private GroupBox GrpBuild; - private RadioButton RadioUnique; - private RadioButton RadioMultiple; - private TextBox TxtDestPath; - private Button BtnPath; - private GroupBox GrpDest; - private Button BtnCancel; - private Button BtnSave; - private FolderBrowserDialog FolderBrowser; - private GroupBox groupBox2; - private Button BtnSrcBrowse; - private TextBox TxtSourcePath; + base.Dispose(disposing); } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SaveWindow)); + this.GrpBuild = new System.Windows.Forms.GroupBox(); + this.RadioUnique = new System.Windows.Forms.RadioButton(); + this.RadioMultiple = new System.Windows.Forms.RadioButton(); + this.TxtDestPath = new System.Windows.Forms.TextBox(); + this.BtnPath = new System.Windows.Forms.Button(); + this.GrpDest = new System.Windows.Forms.GroupBox(); + this.BtnCancel = new System.Windows.Forms.Button(); + this.BtnSave = new System.Windows.Forms.Button(); + this.FolderBrowser = new System.Windows.Forms.FolderBrowserDialog(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.BtnSrcBrowse = new System.Windows.Forms.Button(); + this.TxtSourcePath = new System.Windows.Forms.TextBox(); + this.GrpBuild.SuspendLayout(); + this.GrpDest.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // GrpBuild + // + this.GrpBuild.Controls.Add(this.RadioUnique); + this.GrpBuild.Controls.Add(this.RadioMultiple); + this.GrpBuild.Location = new System.Drawing.Point(12, 12); + this.GrpBuild.Name = "GrpBuild"; + this.GrpBuild.Size = new System.Drawing.Size(458, 58); + this.GrpBuild.TabIndex = 0; + this.GrpBuild.TabStop = false; + this.GrpBuild.Text = "Build Method"; + // + // RadioUnique + // + this.RadioUnique.AutoSize = true; + this.RadioUnique.Location = new System.Drawing.Point(238, 26); + this.RadioUnique.Name = "RadioUnique"; + this.RadioUnique.Size = new System.Drawing.Size(156, 24); + this.RadioUnique.TabIndex = 1; + this.RadioUnique.Text = "Keep separate files"; + this.RadioUnique.UseVisualStyleBackColor = true; + // + // RadioMultiple + // + this.RadioMultiple.AutoSize = true; + this.RadioMultiple.Checked = true; + this.RadioMultiple.Location = new System.Drawing.Point(76, 26); + this.RadioMultiple.Name = "RadioMultiple"; + this.RadioMultiple.Size = new System.Drawing.Size(145, 24); + this.RadioMultiple.TabIndex = 0; + this.RadioMultiple.TabStop = true; + this.RadioMultiple.Text = "Merge as one file"; + this.RadioMultiple.UseVisualStyleBackColor = true; + // + // TxtDestPath + // + this.TxtDestPath.Location = new System.Drawing.Point(6, 26); + this.TxtDestPath.Name = "TxtDestPath"; + this.TxtDestPath.Size = new System.Drawing.Size(358, 27); + this.TxtDestPath.TabIndex = 1; + // + // BtnPath + // + this.BtnPath.Location = new System.Drawing.Point(370, 26); + this.BtnPath.Name = "BtnPath"; + this.BtnPath.Size = new System.Drawing.Size(82, 29); + this.BtnPath.TabIndex = 2; + this.BtnPath.Text = "Browse"; + this.BtnPath.UseVisualStyleBackColor = true; + this.BtnPath.Click += new System.EventHandler(this.BtnPath_Click); + // + // GrpDest + // + this.GrpDest.Controls.Add(this.TxtDestPath); + this.GrpDest.Controls.Add(this.BtnPath); + this.GrpDest.Location = new System.Drawing.Point(12, 153); + this.GrpDest.Name = "GrpDest"; + this.GrpDest.Size = new System.Drawing.Size(458, 66); + this.GrpDest.TabIndex = 3; + this.GrpDest.TabStop = false; + this.GrpDest.Text = "Destination BCAT Path"; + // + // BtnCancel + // + this.BtnCancel.Location = new System.Drawing.Point(99, 225); + this.BtnCancel.Name = "BtnCancel"; + this.BtnCancel.Size = new System.Drawing.Size(125, 29); + this.BtnCancel.TabIndex = 4; + this.BtnCancel.Text = "Cancel"; + this.BtnCancel.UseVisualStyleBackColor = true; + this.BtnCancel.Click += new System.EventHandler(this.BtnCancel_Click); + // + // BtnSave + // + this.BtnSave.Location = new System.Drawing.Point(250, 225); + this.BtnSave.Name = "BtnSave"; + this.BtnSave.Size = new System.Drawing.Size(125, 29); + this.BtnSave.TabIndex = 5; + this.BtnSave.Text = "Save"; + this.BtnSave.UseVisualStyleBackColor = true; + this.BtnSave.Click += new System.EventHandler(this.BtnSave_Click); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.BtnSrcBrowse); + this.groupBox2.Controls.Add(this.TxtSourcePath); + this.groupBox2.Location = new System.Drawing.Point(12, 76); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(458, 66); + this.groupBox2.TabIndex = 6; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Source BCAT Path"; + // + // BtnSrcBrowse + // + this.BtnSrcBrowse.Location = new System.Drawing.Point(370, 26); + this.BtnSrcBrowse.Name = "BtnSrcBrowse"; + this.BtnSrcBrowse.Size = new System.Drawing.Size(82, 27); + this.BtnSrcBrowse.TabIndex = 1; + this.BtnSrcBrowse.Text = "Browse"; + this.BtnSrcBrowse.UseVisualStyleBackColor = true; + this.BtnSrcBrowse.Click += new System.EventHandler(this.BtnSrcBrowse_Click); + // + // TxtSourcePath + // + this.TxtSourcePath.Location = new System.Drawing.Point(6, 26); + this.TxtSourcePath.Name = "TxtSourcePath"; + this.TxtSourcePath.Size = new System.Drawing.Size(358, 27); + this.TxtSourcePath.TabIndex = 0; + // + // SaveWindow + // + this.AcceptButton = this.BtnSave; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.BtnCancel; + this.ClientSize = new System.Drawing.Size(483, 261); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.BtnSave); + this.Controls.Add(this.BtnCancel); + this.Controls.Add(this.GrpDest); + this.Controls.Add(this.GrpBuild); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SaveWindow"; + this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; + this.Text = "Save BCAT Package"; + this.GrpBuild.ResumeLayout(false); + this.GrpBuild.PerformLayout(); + this.GrpDest.ResumeLayout(false); + this.GrpDest.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private GroupBox GrpBuild; + private RadioButton RadioUnique; + private RadioButton RadioMultiple; + private TextBox TxtDestPath; + private Button BtnPath; + private GroupBox GrpDest; + private Button BtnCancel; + private Button BtnSave; + private FolderBrowserDialog FolderBrowser; + private GroupBox groupBox2; + private Button BtnSrcBrowse; + private TextBox TxtSourcePath; } \ No newline at end of file diff --git a/SwitchGiftDataManager.WinForm/SaveWindow.cs b/SwitchGiftDataManager.WinForm/SaveWindow.cs index 66c6aa6..14131a1 100644 --- a/SwitchGiftDataManager.WinForm/SaveWindow.cs +++ b/SwitchGiftDataManager.WinForm/SaveWindow.cs @@ -2,189 +2,188 @@ using SwitchGiftDataManager.Core; using Enums; -namespace SwitchGiftDataManager.WinForm +namespace SwitchGiftDataManager.WinForm; + +public partial class SaveWindow : Form { - public partial class SaveWindow : Form + private BCATManager Package; + private Games Game; + + public SaveWindow(BCATManager bcat, Games game) + { + InitializeComponent(); + + Package = bcat; + Game = game; + + if (Game is Games.LGPE) + { + RadioUnique.Checked = true; + RadioMultiple.Enabled = false; + } + else if (Game is Games.BDSP) + RadioUnique.Enabled = false; + } + + private void BtnCancel_Click(object sender, EventArgs e) => this.Close(); + + private void BtnSrcBrowse_Click(object sender, EventArgs e) { - private BCATManager Package; - private Games Game; + if(FolderBrowser.ShowDialog() == DialogResult.OK) + { + TxtSourcePath.Text = FolderBrowser.SelectedPath; + TxtDestPath.Text = Path.GetDirectoryName(FolderBrowser.SelectedPath); + } + } - public SaveWindow(BCATManager bcat, Games game) - { - InitializeComponent(); + private void BtnPath_Click(object sender, EventArgs e) + { + if (FolderBrowser.ShowDialog() == DialogResult.OK) + TxtDestPath.Text = FolderBrowser.SelectedPath; + } - Package = bcat; - Game = game; - - if (Game is Games.LGPE) - { - RadioUnique.Checked = true; - RadioMultiple.Enabled = false; - } - else if (Game is Games.BDSP) - RadioUnique.Enabled = false; + private void BtnSave_Click(object sender, EventArgs e) + { + if(!RadioUnique.Checked && !RadioMultiple.Checked) + { + MessageBox.Show("Select a Build Method."); + return; + } + if (!CheckValidBcatPath(TxtSourcePath.Text)) + { + MessageBox.Show("Invalid BCAT source path"); + return; + } + if (!CheckValidPath(TxtDestPath.Text)) + { + MessageBox.Show("Invalid destination path."); + return; } - private void BtnCancel_Click(object sender, EventArgs e) => this.Close(); + var path = Path.Combine(TxtDestPath.Text, $"Forged_BCAT_{Game}"); + CopyDirectory(TxtSourcePath.Text, path); - private void BtnSrcBrowse_Click(object sender, EventArgs e) + if (RadioMultiple.Checked) { - if(FolderBrowser.ShowDialog() == DialogResult.OK) + try { - TxtSourcePath.Text = FolderBrowser.SelectedPath; - TxtDestPath.Text = Path.GetDirectoryName(FolderBrowser.SelectedPath); - } - } - - private void BtnPath_Click(object sender, EventArgs e) - { - if (FolderBrowser.ShowDialog() == DialogResult.OK) - TxtDestPath.Text = FolderBrowser.SelectedPath; - } - - private void BtnSave_Click(object sender, EventArgs e) - { - if(!RadioUnique.Checked && !RadioMultiple.Checked) - { - MessageBox.Show("Select a Build Method."); - return; - } - if (!CheckValidBcatPath(TxtSourcePath.Text)) - { - MessageBox.Show("Invalid BCAT source path"); - return; - } - if (!CheckValidPath(TxtDestPath.Text)) - { - MessageBox.Show("Invalid destination path."); - return; - } - - var path = Path.Combine(TxtDestPath.Text, $"Forged_BCAT_{Game}"); - CopyDirectory(TxtSourcePath.Text, path); - - if (RadioMultiple.Checked) - { - try - { - var wcdata = Package.ConcatenateFiles(); - var metadata = Package.ForgeMetaInfo(wcdata.ToArray()); - var metadatapath = Path.Combine(path, "directories"); - metadatapath = Path.Combine(metadatapath, Package.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, Package.GetDefaultBcatFileName()), wcdata.ToArray()); - MessageBox.Show($"Saved in {path}{Environment.NewLine}BCAT forge was successful."); - this.Close(); - } - catch (Exception) - { - MessageBox.Show("Internal Error"); - this.Close(); - } - } - else - { - var metadata = Package.ForgeMetaInfo(); + var wcdata = Package.ConcatenateFiles(); + var metadata = Package.ForgeMetaInfo(wcdata.ToArray()); var metadatapath = Path.Combine(path, "directories"); metadatapath = Path.Combine(metadatapath, Package.GetDefaultBcatFolderName()); - var wcspath = Path.Combine(metadatapath, "files"); + var wcpath = Path.Combine(metadatapath, "files"); if (Directory.Exists(metadatapath)) DeleteFilesAndDirectory(metadatapath); - Directory.CreateDirectory(wcspath); + Directory.CreateDirectory(wcpath); File.WriteAllBytes(Path.Combine(metadatapath, "files.meta"), metadata.ToArray()); - if (Package.TrySaveAllWondercards(wcspath)) - { - MessageBox.Show($"Saved in {path}{Environment.NewLine}BCAT forge was successful."); - this.Close(); - } - else - { - MessageBox.Show("Internal error."); - this.Close(); - } + File.WriteAllBytes(Path.Combine(wcpath, Package.GetDefaultBcatFileName()), wcdata.ToArray()); + MessageBox.Show($"Saved in {path}{Environment.NewLine}BCAT forge was successful."); + this.Close(); } - } - - 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; - } - - private static bool CheckValidPath(string path) - { - if(string.IsNullOrWhiteSpace(path)) - return false; - - if (!Directory.Exists(path)) - return false; - - return true; - } - - private 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()) + catch (Exception) { - 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); + MessageBox.Show("Internal Error"); + this.Close(); } } - - private void DeleteFilesAndDirectory(string targetDir) + else { - string[] files = Directory.GetFiles(targetDir); - string[] dirs = Directory.GetDirectories(targetDir); + var metadata = Package.ForgeMetaInfo(); + var metadatapath = Path.Combine(path, "directories"); + metadatapath = Path.Combine(metadatapath, Package.GetDefaultBcatFolderName()); + var wcspath = Path.Combine(metadatapath, "files"); - foreach (string file in files) + if (Directory.Exists(metadatapath)) + DeleteFilesAndDirectory(metadatapath); + + Directory.CreateDirectory(wcspath); + File.WriteAllBytes(Path.Combine(metadatapath, "files.meta"), metadata.ToArray()); + if (Package.TrySaveAllWondercards(wcspath)) { - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); + MessageBox.Show($"Saved in {path}{Environment.NewLine}BCAT forge was successful."); + this.Close(); + } + else + { + MessageBox.Show("Internal error."); + this.Close(); } - - foreach (string dir in dirs) - DeleteFilesAndDirectory(dir); - - Directory.Delete(targetDir, false); } } + + 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; + } + + private static bool CheckValidPath(string path) + { + if(string.IsNullOrWhiteSpace(path)) + return false; + + if (!Directory.Exists(path)) + return false; + + return true; + } + + private 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 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); + } } \ No newline at end of file