diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index bda6591cb..8a1255a2f 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -470,7 +470,7 @@ private void mainMenuBoxLoad(object sender, EventArgs e) private void mainMenuBoxDump(object sender, EventArgs e) { string path; - bool dumptoboxes = false; + bool separate = false; // Dump all of box content to files. DialogResult ld = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Save to PKHeX's database?"); if (ld == DialogResult.Yes) @@ -481,7 +481,7 @@ private void mainMenuBoxDump(object sender, EventArgs e) } else if (ld == DialogResult.No) { - dumptoboxes = DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Save each box separately?"); + separate = DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Save each box separately?"); // open folder dialog FolderBrowserDialog fbd = new FolderBrowserDialog(); @@ -492,7 +492,9 @@ private void mainMenuBoxDump(object sender, EventArgs e) } else return; - dumpBoxesToDB(path, dumptoboxes); + string result; + SAV.dumpBoxes(path, out result, separate); + WinFormsUtil.Alert(result); } private void manMenuBatchEditor(object sender, EventArgs e) { @@ -3019,39 +3021,6 @@ public bool verifiedPKM() SystemSounds.Exclamation.Play(); return false; } - public static string[] verifyPKMtoSAV(PKM pk) - { - // Check if PKM properties are outside of the valid range - List errata = new List(); - if (SAV.Generation > 1) - { - ushort held = (ushort)pk.HeldItem; - - if (held > GameInfo.Strings.itemlist.Length) - errata.Add($"Item Index beyond range: {held}"); - else if (held > SAV.MaxItemID) - errata.Add($"Game can't obtain item: {GameInfo.Strings.itemlist[held]}"); - else if (!pk.CanHoldItem(SAV.HeldItems)) - errata.Add($"Game can't hold item: {GameInfo.Strings.itemlist[held]}"); - } - - if (pk.Species > GameInfo.Strings.specieslist.Length) - errata.Add($"Species Index beyond range: {pk.HeldItem}"); - else if (SAV.MaxSpeciesID < pk.Species) - errata.Add($"Game can't obtain species: {GameInfo.Strings.specieslist[pk.Species]}"); - - if (pk.Moves.Any(m => m > GameInfo.Strings.movelist.Length)) - errata.Add($"Item Index beyond range: {string.Join(", ", pk.Moves.Where(m => m > GameInfo.Strings.movelist.Length).Select(m => m.ToString()))}"); - else if (pk.Moves.Any(m => m > SAV.MaxMoveID)) - errata.Add($"Game can't have move: {string.Join(", ", pk.Moves.Where(m => m > SAV.MaxMoveID).Select(m => GameInfo.Strings.movelist[m]))}"); - - if (pk.Ability > GameInfo.Strings.abilitylist.Length) - errata.Add($"Ability Index beyond range: {pk.Ability}"); - else if (pk.Ability > SAV.MaxAbilityID) - errata.Add($"Game can't have ability: {GameInfo.Strings.abilitylist[pk.Ability]}"); - - return errata.ToArray(); - } public PKM preparePKM(bool click = true) { if (click) @@ -3362,7 +3331,7 @@ private void clickSet(object sender, EventArgs e) } PKM pk = preparePKM(); - string[] errata = verifyPKMtoSAV(pk); + string[] errata = SAV.IsPKMCompatible(pk); if (errata.Length > 0 && DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, string.Join(Environment.NewLine, errata), "Continue?")) return; @@ -3860,26 +3829,6 @@ private void switchDaycare(object sender, EventArgs e) // Refresh Boxes setPKXBoxes(); } - private void dumpBoxesToDB(string path, bool individualBoxFolders) - { - PKM[] boxdata = SAV.BoxData; - if (boxdata == null) { WinFormsUtil.Error("Null argument when dumping boxes."); return; } - for (int i = 0; i < boxdata.Length; i++) - { - PKM pk = boxdata[i]; - if (pk.Species == 0 || !pk.Valid) - continue; - string fileName = Util.CleanFileName(pk.FileName); - string boxfolder = ""; - if (individualBoxFolders) - { - boxfolder = SAV.getBoxName(i/SAV.BoxSlotCount); - Directory.CreateDirectory(Path.Combine(path, boxfolder)); - } - if (!File.Exists(Path.Combine(Path.Combine(path, boxfolder), fileName))) - File.WriteAllBytes(Path.Combine(Path.Combine(path, boxfolder), fileName), pk.DecryptedBoxData); - } - } private void loadBoxesFromDB(string path) { if (string.IsNullOrWhiteSpace(path)) return; @@ -3888,48 +3837,13 @@ private void loadBoxesFromDB(string path) DialogResult dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, "Clear subsequent boxes when importing data?", "If you only want to overwrite for new data, press no."); if (dr == DialogResult.Cancel) return; - if (dr == DialogResult.Yes) - SAV.resetBoxes(CB_BoxSelect.SelectedIndex); + string result; + bool clearAll = dr == DialogResult.Yes; bool? noSetb = getPKMSetOverride(); - int ctr = CB_BoxSelect.SelectedIndex*SAV.BoxSlotCount; - int pastctr = 0; - string[] filepaths = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly); - - foreach (byte[] data in from file in filepaths where PKX.getIsPKM(new FileInfo(file).Length) select File.ReadAllBytes(file)) - { - string c; - PKM temp = PKMConverter.getPKMfromBytes(data, prefer: SAV.Generation); - PKM pk = PKMConverter.convertToFormat(temp, SAV.PKMType, out c); - - if (pk != null) // Write to save - { - if (verifyPKMtoSAV(pk).Length > 0) - continue; - - while (SAV.getIsSlotLocked(ctr/SAV.BoxSlotCount, ctr%SAV.BoxSlotCount)) - ctr++; - - SAV.setStoredSlot(pk, SAV.getBoxOffset(ctr/SAV.BoxSlotCount) + ctr%SAV.BoxSlotCount * SAV.SIZE_STORED, noSetb); - if (pk.Format != temp.Format) // Transferred - pastctr++; - if (++ctr == SAV.BoxCount*SAV.BoxSlotCount) // Boxes full! - break; - } - Console.WriteLine(c); - } - ctr -= SAV.BoxSlotCount * CB_BoxSelect.SelectedIndex; // actual imported count - if (ctr <= 0) - return; - - setPKXBoxes(); - updateBoxViewers(); - string result = $"Loaded {ctr} files to boxes."; - if (pastctr > 0) - WinFormsUtil.Alert(result, $"Conversion successful for {pastctr} past generation files."); - else - WinFormsUtil.Alert(result); + SAV.loadBoxes(path, out result, CB_BoxSelect.SelectedIndex, clearAll, noSetb); + WinFormsUtil.Alert(result); } private void B_SaveBoxBin_Click(object sender, EventArgs e) { @@ -4262,7 +4176,7 @@ private void pbBoxSlot_DragDrop(object sender, DragEventArgs e) if (pk == null) { WinFormsUtil.Error(c); Console.WriteLine(c); return; } - string[] errata = verifyPKMtoSAV(pk); + string[] errata = SAV.IsPKMCompatible(pk); if (errata.Length > 0) { string concat = string.Join(Environment.NewLine, errata); diff --git a/PKHeX.WinForms/PKHeX.WinForms.csproj b/PKHeX.WinForms/PKHeX.WinForms.csproj index b199118ad..d1f69f1df 100644 --- a/PKHeX.WinForms/PKHeX.WinForms.csproj +++ b/PKHeX.WinForms/PKHeX.WinForms.csproj @@ -396,6 +396,7 @@ + Main.cs diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs index 63bf1272a..c42ee42a6 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs @@ -269,7 +269,7 @@ private void pbBoxSlot_DragDrop(object sender, DragEventArgs e) if (pk == null) { WinFormsUtil.Error(c); Console.WriteLine(c); return; } - string[] errata = verifyPKMtoSAV(pk); + string[] errata = SAV.IsPKMCompatible(pk); if (errata.Length > 0) { string concat = string.Join(Environment.NewLine, errata); diff --git a/PKHeX.WinForms/Util/SAVUtil.cs b/PKHeX.WinForms/Util/SAVUtil.cs new file mode 100644 index 000000000..7c9059819 --- /dev/null +++ b/PKHeX.WinForms/Util/SAVUtil.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using PKHeX.Core; + +namespace PKHeX.WinForms +{ + /// + /// Contains extension methods for use with a . + /// + public static class SAVUtil + { + /// + /// Dumps a folder of files to the . + /// + /// that is being dumped from. + /// Folder to store files. + /// Result message from the method. + /// Option to save in child folders with the Box Name as the folder name. + /// + public static bool dumpBoxes(this SaveFile SAV, string path, out string result, bool boxFolders = false) + { + PKM[] boxdata = SAV.BoxData; + if (boxdata == null) + { result = "Invalid Box Data, unable to dump."; return false; } + + int ctr = 0; + foreach (PKM pk in boxdata) + { + if (pk.Species == 0 || !pk.Valid) + continue; + + ctr++; + string fileName = Util.CleanFileName(pk.FileName); + string boxfolder = ""; + if (boxFolders) + { + boxfolder = SAV.getBoxName(pk.Box); + Directory.CreateDirectory(Path.Combine(path, boxfolder)); + } + if (!File.Exists(Path.Combine(Path.Combine(path, boxfolder), fileName))) + File.WriteAllBytes(Path.Combine(Path.Combine(path, boxfolder), fileName), pk.DecryptedBoxData); + } + + result = $"Dumped Boxes ({ctr} pkm) to path:\n" + path; + return true; + } + + /// + /// Loads a folder of files to the . + /// + /// to load folder to. + /// Folder to load files from. Files are only loaded from the top directory. + /// Result message from the method. + /// First box to start loading to. All prior boxes are not modified. + /// Instruction to clear boxes after the starting box. + /// Bypass option to not modify properties when setting to Save File. + /// + public static bool loadBoxes(this SaveFile SAV, string path, out string result, int boxStart = 0, bool boxClear = false, bool? noSetb = null) + { + if (string.IsNullOrWhiteSpace(path)) + { result = "Invalid path specified."; return false; } + if (!SAV.HasBox) + { result = "Save file does not have boxes."; return false; } + + if (boxClear) + SAV.resetBoxes(boxStart); + + int startCount = boxStart*SAV.BoxSlotCount; + int maxCount = SAV.BoxCount*SAV.BoxSlotCount; + int ctr = startCount; + int pastctr = 0; + string[] filepaths = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly); + + foreach (var file in filepaths) + { + if (!PKX.getIsPKM(new FileInfo(file).Length)) + continue; + + // Check for format compatibility with save; if transfer is necessary => convert. + string c; // format conversion comment + byte[] data = File.ReadAllBytes(file); + PKM temp = PKMConverter.getPKMfromBytes(data, prefer: SAV.Generation); + PKM pk = PKMConverter.convertToFormat(temp, SAV.PKMType, out c); + + if (pk == null) + { Console.WriteLine(c); continue; } + + if (SAV.IsPKMCompatible(pk).Length > 0) + continue; + + while (SAV.getIsSlotLocked(ctr/SAV.BoxSlotCount, ctr%SAV.BoxSlotCount)) + ctr++; + + int offset = SAV.getBoxOffset(ctr/SAV.BoxSlotCount) + ctr%SAV.BoxSlotCount*SAV.SIZE_STORED; + SAV.setStoredSlot(pk, offset, noSetb); + if (pk.Format != temp.Format) // Transferred + pastctr++; + if (++ctr == maxCount) // Boxes full! + break; + } + + ctr -= startCount; // actual imported count + if (ctr <= 0) + { result = "No files loaded"; return false; } + + result = $"Loaded {ctr} files to boxes."; + if (pastctr > 0) + result += Environment.NewLine + $"Conversion successful for {pastctr} past generation files."; + + return true; + } + + /// + /// Checks a file for compatibility to the . + /// + /// that is being checked. + /// that is being tested for compatibility. + /// + public static string[] IsPKMCompatible(this SaveFile SAV, PKM pkm) + { + // Check if PKM properties are outside of the valid range + List errata = new List(); + if (SAV.Generation > 1) + { + ushort held = (ushort)pkm.HeldItem; + + if (held > GameInfo.Strings.itemlist.Length) + errata.Add($"Item Index beyond range: {held}"); + else if (held > SAV.MaxItemID) + errata.Add($"Game can't obtain item: {GameInfo.Strings.itemlist[held]}"); + else if (!pkm.CanHoldItem(SAV.HeldItems)) + errata.Add($"Game can't hold item: {GameInfo.Strings.itemlist[held]}"); + } + + if (pkm.Species > GameInfo.Strings.specieslist.Length) + errata.Add($"Species Index beyond range: {pkm.HeldItem}"); + else if (SAV.MaxSpeciesID < pkm.Species) + errata.Add($"Game can't obtain species: {GameInfo.Strings.specieslist[pkm.Species]}"); + + if (pkm.Moves.Any(m => m > GameInfo.Strings.movelist.Length)) + errata.Add($"Item Index beyond range: {string.Join(", ", pkm.Moves.Where(m => m > GameInfo.Strings.movelist.Length).Select(m => m.ToString()))}"); + else if (pkm.Moves.Any(m => m > SAV.MaxMoveID)) + errata.Add($"Game can't have move: {string.Join(", ", pkm.Moves.Where(m => m > SAV.MaxMoveID).Select(m => GameInfo.Strings.movelist[m]))}"); + + if (pkm.Ability > GameInfo.Strings.abilitylist.Length) + errata.Add($"Ability Index beyond range: {pkm.Ability}"); + else if (pkm.Ability > SAV.MaxAbilityID) + errata.Add($"Game can't have ability: {GameInfo.Strings.abilitylist[pkm.Ability]}"); + + return errata.ToArray(); + } + } +}