From c544a2e16dbfc8757bd3a0219448f873f40f3856 Mon Sep 17 00:00:00 2001 From: Kaphotics Date: Tue, 11 Oct 2016 19:11:24 -0700 Subject: [PATCH] Refactoring Redefine/move logic for maintainability. --- PKHeX/MainWindow/Main.cs | 109 +++++++++++++++++++-------------------- PKHeX/Saves/SAV3.cs | 3 ++ PKHeX/Saves/SaveFile.cs | 8 +-- PKHeX/Saves/SaveUtil.cs | 104 +++++++++++++++++++++---------------- 4 files changed, 119 insertions(+), 105 deletions(-) diff --git a/PKHeX/MainWindow/Main.cs b/PKHeX/MainWindow/Main.cs index 0096f76c0..6c99d57fa 100644 --- a/PKHeX/MainWindow/Main.cs +++ b/PKHeX/MainWindow/Main.cs @@ -181,7 +181,7 @@ public Main() if (path != null && File.Exists(path)) openQuick(path, force: true); else - loadSAV(SAV, null); + openSAV(SAV, null); } // Splash Screen closes on its own. @@ -633,10 +633,7 @@ private void openQuick(string path, bool force = false) } private void openFile(byte[] input, string path, string ext) { - MysteryGift tg; PKM temp; string c; - byte[] footer = new byte[0]; - byte[] header = new byte[0]; - SaveUtil.CheckHeaderFooter(ref input, ref header, ref footer); + SaveFile sav; MysteryGift tg; PKM temp; string c; #region Powersaves Read-Only Conversion if (input.Length == 0x10009C) // Resize to 1MB { @@ -661,23 +658,25 @@ private void openFile(byte[] input, string path, string ext) if (BitConverter.ToUInt32(psdata, psdata.Length - 0x1F0) != SaveUtil.BEEF) { Util.Error("The data file is not a valid save file", path); return; } - openSAV(psdata, path); + openSAV(new SAV6(psdata), path); } #endregion #region SAV/PKM - else if (SaveUtil.getSAVGeneration(input) != -1) + else if ((sav = SaveUtil.getVariantSAV(input)) != null) { - openSAV(input, path); - SAV.Footer = footer; - SAV.Header = header; + openSAV(sav, path); } else if ((temp = PKMConverter.getPKMfromBytes(input)) != null) { PKM pk = PKMConverter.convertToFormat(temp, SAV.PKMType, out c); if (pk == null) Util.Alert("Conversion failed.", c); - else if (SAV.Generation < 3 && (pk is PK1 ? ((PK1)pk).Japanese : ((PK2)pk).Japanese) != SAV.GetJapanese) - Util.Alert($"Cannot load {(SAV.GetJapanese ? "an International" : "a Japanese")} {pk.GetType().Name} in {(SAV.GetJapanese ? "a Japanese" : "an International")} save file."); + else if (SAV.Generation < 3 && ((pk as PK1)?.Japanese ?? ((PK2)pk).Japanese) != SAV.Japanese) + { + string a_lang = SAV.Japanese ? "an International" : "a Japanese"; + string pk_type = pk.GetType().Name; + Util.Alert($"Cannot load {a_lang} {pk_type} in {a_lang} save file."); + } else populateFields(pk); Console.WriteLine(c); @@ -723,17 +722,11 @@ private void openFile(byte[] input, string path, string ext) else if ((tg = MysteryGift.getMysteryGift(input, ext)) != null) { if (!tg.IsPokémon) - { - Util.Alert("Mystery Gift is not a Pokémon.", path); - return; - } + { Util.Alert("Mystery Gift is not a Pokémon.", path); return; } + temp = tg.convertToPKM(SAV); - if (temp.Format == SAV.Generation && ModifierKeys == Keys.Control && SAV.HasWondercards) - { - B_OpenWondercards_Click(tg, null); - return; - } PKM pk = PKMConverter.convertToFormat(temp, SAV.PKMType, out c); + if (pk == null) Util.Alert("Conversion failed.", c); else @@ -784,7 +777,7 @@ private bool openXOR(byte[] input, string path) // Save file is now decrypted! // Trigger Loading of the decrypted save file. - openSAV(decryptedPS, path); + openSAV(new SAV6(decryptedPS), path); // Abort the opening of a non-cyber file. return true; @@ -793,47 +786,49 @@ private bool openXOR(byte[] input, string path) if (xorpath != exepath || loop++ > 0) return false; // no xorpad compatible xorpath = Path.GetDirectoryName(path); goto check; } - private void openSAV(byte[] input, string path) + private void openSAV(SaveFile sav, string path) { - SaveFile sav = SaveUtil.getVariantSAV(input); if (sav == null || sav.Version == GameVersion.Invalid) { Util.Error("Invalid save file loaded. Aborting.", path); return; } - if (sav.Generation == 3) // Japanese Save files are different. Get isJapanese + + // Finish setting up the save file. + if (sav.IndeterminateGame && sav.Generation == 3) { - if (sav.Version == GameVersion.Unknown) + // Hacky cheats invalidated the Game Code value. + var drGame = Util.Prompt(MessageBoxButtons.YesNoCancel, + "Unknown Gen3 Game Detected. Select Origins:", + "Yes: Ruby / Sapphire" + Environment.NewLine + + "No: Emerald" + Environment.NewLine + + "Cancel: FireRed / LeafGreen"); + + switch (drGame) // Reset save file info { - // Hacky cheats invalidated the Game Code value. - var drGame = Util.Prompt(MessageBoxButtons.YesNoCancel, - "Unknown Gen3 Game Detected. Select Origins:", - "Yes: Ruby / Sapphire" + Environment.NewLine + - "No: Emerald" + Environment.NewLine + - "Cancel: FireRed / LeafGreen"); - - if (drGame == DialogResult.Yes) - sav = new SAV3(sav.BAK, GameVersion.RS); - else if (drGame == DialogResult.No) - sav = new SAV3(sav.BAK, GameVersion.E); - else - sav = new SAV3(sav.BAK, GameVersion.FRLG); - } - var drJP = Util.Prompt(MessageBoxButtons.YesNoCancel, $"Generation 3 ({sav.Version}) Save File detected. Select Origins:", "Yes: International" + Environment.NewLine + "No: Japanese"); - if (drJP == DialogResult.Cancel) - return; - sav.Japanese = drJP == DialogResult.No; - - if (sav.Version == GameVersion.FRLG) - { - var drFRLG = Util.Prompt(MessageBoxButtons.YesNoCancel, $"{sav.Version} detected. Select version...", "Yes: FireRed" + Environment.NewLine + "No: LeafGreen"); - if (drFRLG == DialogResult.Cancel) - return; - - sav.Personal = drFRLG == DialogResult.Yes ? PersonalTable.FR : PersonalTable.LG; + case DialogResult.Yes: sav = new SAV3(sav.BAK, GameVersion.RS); break; + case DialogResult.No: sav = new SAV3(sav.BAK, GameVersion.E); break; + case DialogResult.Cancel: sav = new SAV3(sav.BAK, GameVersion.FRLG); break; + default: return; } } - loadSAV(sav, path); - } - private void loadSAV(SaveFile sav, string path) - { + if (sav.IndeterminateLanguage) + { + // Japanese Save files are different. Get isJapanese + var drJP = Util.Prompt(MessageBoxButtons.YesNoCancel, $"{sav.Version} Save File detected. Select language...", + "Yes: International" + Environment.NewLine + "No: Japanese"); + if (drJP == DialogResult.Cancel) + return; + + sav.Japanese = drJP == DialogResult.No; + } + if (sav.IndeterminateSubVersion && sav.Version == GameVersion.FRLG) + { + var drFRLG = Util.Prompt(MessageBoxButtons.YesNoCancel, $"{sav.Version} detected. Select version...", + "Yes: FireRed" + Environment.NewLine + "No: LeafGreen"); + if (drFRLG == DialogResult.Cancel) + return; + + sav.Personal = drFRLG == DialogResult.Yes ? PersonalTable.FR : PersonalTable.LG; + } + // clean fields PKM pk = preparePKM(); populateFields(SAV.BlankPKM); @@ -2400,7 +2395,7 @@ private void updateOriginGame(object sender, EventArgs e) GameVersion Version = (GameVersion)Util.getIndex(CB_GameOrigin); // check if differs - GameVersion newTrack = SaveUtil.getVersionGroup(Version); + GameVersion newTrack = SaveUtil.getMetLocationVersionGroup(Version); if (newTrack != origintrack) { var met_list = getLocationList(Version, SAV.Generation, egg:false); diff --git a/PKHeX/Saves/SAV3.cs b/PKHeX/Saves/SAV3.cs index 835377a4e..61f9f22e7 100644 --- a/PKHeX/Saves/SAV3.cs +++ b/PKHeX/Saves/SAV3.cs @@ -157,6 +157,9 @@ public override byte[] Write(bool DSV) // Configuration public override SaveFile Clone() { return new SAV3(Write(DSV:false), Version); } + public override bool IndeterminateGame => Version == GameVersion.Unknown; + public override bool IndeterminateLanguage => true; // Unknown JP/International + public override bool IndeterminateSubVersion => Version == GameVersion.FRLG; public override int SIZE_STORED => PKX.SIZE_3STORED; public override int SIZE_PARTY => PKX.SIZE_3PARTY; diff --git a/PKHeX/Saves/SaveFile.cs b/PKHeX/Saves/SaveFile.cs index 4e00d1326..2a771a4c4 100644 --- a/PKHeX/Saves/SaveFile.cs +++ b/PKHeX/Saves/SaveFile.cs @@ -20,10 +20,11 @@ public abstract class SaveFile public abstract string Filter { get; } public byte[] Footer { protected get; set; } = new byte[0]; // .dsv public byte[] Header { protected get; set; } = new byte[0]; // .gci - public bool Japanese { protected get; set; } + public bool Japanese { get; set; } public string PlayTimeString => $"{PlayedHours}ː{PlayedMinutes.ToString("00")}ː{PlayedSeconds.ToString("00")}"; // not : - - public bool GetJapanese => Japanese; + public virtual bool IndeterminateGame => false; + public virtual bool IndeterminateLanguage => false; + public virtual bool IndeterminateSubVersion => false; // General PKM Properties public abstract Type PKMType { get; } @@ -367,7 +368,6 @@ public void setPartySlot(PKM pkm, int offset, bool? trade = null, bool? dex = nu PartyCount = i + 1; setData(pkm.EncryptedPartyData, offset); - Console.WriteLine(""); Edited = true; } public virtual void setStoredSlot(PKM pkm, int offset, bool? trade = null, bool? dex = null) diff --git a/PKHeX/Saves/SaveUtil.cs b/PKHeX/Saves/SaveUtil.cs index 4c77a0861..3b80c2820 100644 --- a/PKHeX/Saves/SaveUtil.cs +++ b/PKHeX/Saves/SaveUtil.cs @@ -37,6 +37,9 @@ public enum GameVersion ORASDEMO = 107, ORAS = 108, SM = 109, + + // Extra Game Groupings (Generation) + Gen1, Gen2, Gen3, Gen4, Gen5, Gen6, Gen7 } public static class SaveUtil @@ -75,29 +78,33 @@ public static class SaveUtil /// Determines the generation of the given save data. /// Save data of which to determine the generation /// Version Identifier or Invalid if type cannot be determined. - public static int getSAVGeneration(byte[] data) + public static GameVersion getSAVGeneration(byte[] data) { if (getIsG1SAV(data) != GameVersion.Invalid) - return 1; + return GameVersion.Gen1; if (getIsG2SAV(data) != GameVersion.Invalid) - return 2; + return GameVersion.Gen2; if (getIsG3SAV(data) != GameVersion.Invalid) - return 3; - if (getIsG3COLOSAV(data) != GameVersion.Invalid) - return (int)GameVersion.COLO; - if (getIsG3XDSAV(data) != GameVersion.Invalid) - return (int)GameVersion.XD; - if (getIsG3BOXSAV(data) != GameVersion.Invalid) - return (int)GameVersion.RSBOX; + return GameVersion.Gen3; if (getIsG4SAV(data) != GameVersion.Invalid) - return 4; - if (getIsG4BRSAV(data) != GameVersion.Invalid) - return (int) GameVersion.BATREV; + return GameVersion.Gen4; if (getIsG5SAV(data) != GameVersion.Invalid) - return 5; + return GameVersion.Gen5; if (getIsG6SAV(data) != GameVersion.Invalid) - return 6; - return -1; + return GameVersion.Gen6; + if (getIsG7SAV(data) != GameVersion.Invalid) + return GameVersion.Gen7; + + if (getIsG3COLOSAV(data) != GameVersion.Invalid) + return GameVersion.COLO; + if (getIsG3XDSAV(data) != GameVersion.Invalid) + return GameVersion.XD; + if (getIsG3BOXSAV(data) != GameVersion.Invalid) + return GameVersion.RSBOX; + if (getIsG4BRSAV(data) != GameVersion.Invalid) + return GameVersion.BATREV; + + return GameVersion.Invalid; } /// Determines the type of 1st gen save /// Save data of which to determine the type @@ -400,11 +407,16 @@ public static GameVersion getIsG6SAV(byte[] data) } return GameVersion.Invalid; } + public static GameVersion getIsG7SAV(byte[] data) + { + // return GameVersion.Gen7; + return GameVersion.Invalid; + } /// Determines the Version Grouping of an input Version ID /// Version of which to determine the group /// Version Group Identifier or Invalid if type cannot be determined. - public static GameVersion getVersionGroup(GameVersion Version) + public static GameVersion getMetLocationVersionGroup(GameVersion Version) { switch (Version) { @@ -466,31 +478,34 @@ public static GameVersion getVersionGroup(GameVersion Version) /// An appropriate type of save file for the given data, or null if the save data is invalid. public static SaveFile getVariantSAV(byte[] data) { + // Pre-check for header/footer signatures + SaveFile sav; + byte[] header = new byte[0], footer = new byte[0]; + CheckHeaderFooter(ref data, ref header, ref footer); + switch (getSAVGeneration(data)) { - case 1: - return new SAV1(data); - case 2: - return new SAV2(data); - case 3: - return new SAV3(data); - case (int)GameVersion.RSBOX: - return new SAV3RSBox(data); - case (int)GameVersion.COLO: - return new SAV3Colosseum(data); - case (int)GameVersion.XD: - return new SAV3XD(data); - case 4: - return new SAV4(data); - case (int)GameVersion.BATREV: - return new SAV4BR(data); - case 5: - return new SAV5(data); - case 6: - return new SAV6(data); - default: - return null; + // Main Games + case GameVersion.Gen1: sav = new SAV1(data); break; + case GameVersion.Gen2: sav = new SAV2(data); break; + case GameVersion.Gen3: sav = new SAV3(data); break; + case GameVersion.Gen4: sav = new SAV4(data); break; + case GameVersion.Gen5: sav = new SAV5(data); break; + case GameVersion.Gen6: sav = new SAV6(data); break; + //case GameVersion.Gen7: sav = new SAV7(data); break; + + // Side Games + case GameVersion.COLO: sav = new SAV3Colosseum(data); break; + case GameVersion.XD: sav = new SAV3XD(data); break; + case GameVersion.RSBOX: sav = new SAV3RSBox(data); break; + case GameVersion.BATREV: sav = new SAV4BR(data); break; + + // No pattern matched + default: return null; } + sav.Header = header; + sav.Footer = footer; + return sav; } /// @@ -546,7 +561,7 @@ public static IEnumerable getSavesFromFolder(string folderPath, bool dee } /// - /// Determines whether the save data size is valid for 6th generation saves. + /// Determines whether the save data size is valid for autodetecting saves. /// /// Size in bytes of the save data /// A boolean indicating whether or not the save data size is valid. @@ -554,13 +569,14 @@ public static bool SizeValidSAV(int size) { switch (size) { + case SIZE_G3RAW: + case SIZE_G3RAWHALF: + + case SIZE_G4RAW: // Gen4/5 + case SIZE_G6XY: case SIZE_G6ORASDEMO: case SIZE_G6ORAS: - case SIZE_G5B2W2: - case SIZE_G4RAW: - case SIZE_G3RAW: - case SIZE_G3RAWHALF: return true; default: return false;