From 49c4043e19d3de9cf96f44c7568d496281fc252c Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 13 Nov 2018 19:14:23 -0800 Subject: [PATCH] Update dex abstractions, add gg dex --- .../Saves/Substructures/PokeDex/Zukan.cs | 56 +++++--- .../Saves/Substructures/PokeDex/Zukan6.cs | 13 +- .../Saves/Substructures/PokeDex/Zukan7.cs | 12 +- .../Saves/Substructures/PokeDex/Zukan7b.cs | 136 ++++++++++++++++++ 4 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs index c7e9dab18..cc8415c82 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs @@ -16,36 +16,45 @@ namespace PKHeX.Core protected abstract int DexLangIDCount { get; } protected abstract int GetDexLangFlag(int lang); - protected Func DexFormIndexFetcher { get; set; } + public Func DexFormIndexFetcher { get; protected set; } protected abstract bool GetSaneFormsToIterate(int species, out int formStart, out int formEnd, int formIn); - protected abstract void SetSpindaDexData(PKM pkm, bool alreadySeen); + protected virtual void SetSpindaDexData(PKM pkm, bool alreadySeen) { } protected abstract void SetAllDexFlagsLanguage(int bit, int lang, bool value = true); protected abstract void SetAllDexSeenFlags(int baseBit, int altform, int gender, bool isShiny, bool value = true); - public bool GetFlag(int ofs, int bitIndex) => SAV.GetFlag(PokeDex + ofs, bitIndex); - public void SetFlag(int ofs, int bitIndex, bool value = true) => SAV.SetFlag(PokeDex + ofs, bitIndex, value); + protected bool GetFlag(int ofs, int bitIndex) => SAV.GetFlag(PokeDex + ofs + (bitIndex >> 3), bitIndex); + protected void SetFlag(int ofs, int bitIndex, bool value = true) => SAV.SetFlag(PokeDex + ofs + (bitIndex >> 3), bitIndex, value); - public bool GetCaught(int species) => GetFlag(OFS_CAUGHT, species - 1); - public void SetCaught(int species, bool value = true) => SetFlag(OFS_CAUGHT, species - 1, value); + public virtual bool GetCaught(int species) => GetFlag(OFS_CAUGHT, species - 1); + public virtual void SetCaught(int species, bool value = true) => SetFlag(OFS_CAUGHT, species - 1, value); public int SeenCount => Enumerable.Range(1, SAV.MaxSpeciesID).Count(GetSeen); public int CaughtCount => Enumerable.Range(1, SAV.MaxSpeciesID).Count(GetCaught); public decimal PercentSeen => (decimal)SeenCount / SAV.MaxSpeciesID; public decimal PercentCaught => (decimal)CaughtCount / SAV.MaxSpeciesID; - public bool GetSeen(int species) + public virtual bool GetSeen(int species) { // check all 4 seen flags (gender/shiny) for (int i = 0; i < 4; i++) { - if (GetFlag(OFS_SEEN + (i * BitSeenSize), species - 1)) + if (GetSeen(species, i)) return true; } return false; } - public void SetSeen(int species, bool value = true) + public bool GetSeen(int species, int i) => GetFlag(OFS_SEEN + (i * BitSeenSize), species - 1); + public void SetSeen(int species, int i, bool value) => SetFlag(OFS_SEEN + (i * BitSeenSize), species - 1, value); + + public bool GetDisplayed(int bit, int i) => GetFlag(OFS_SEEN + ((i + 4) * BitSeenSize), bit); + public void SetDisplayed(int bit, int i, bool value) => SetFlag(OFS_SEEN + ((i + 4) * BitSeenSize), bit, value); + + public bool GetLanguageFlag(int bit, int lang) => GetFlag(PokeDexLanguageFlags, (bit * DexLangIDCount) + lang); + public void SetLanguageFlag(int bit, int lang, bool value) => SetFlag(PokeDexLanguageFlags, (bit * DexLangIDCount) + lang, value); + + public virtual void SetSeen(int species, bool value = true) { if (!value) { @@ -79,12 +88,23 @@ namespace PKHeX.Core if (pkm.IsEgg) // do not add return; + int species = pkm.Species; + if (species == 327) // Spinda + SetSpindaDexData(pkm, GetSeen(species)); + int bit = pkm.Species - 1; - SetCaught(pkm.Species); // Set the Owned Flag - if (pkm.Species == 327) // Spinda - SetSpindaDexData(pkm, GetSeen(pkm.Species)); - SetAllDexSeenFlags(bit, pkm.AltForm, pkm.Gender & 1, pkm.IsShiny); // genderless -> male - SetAllDexFlagsLanguage(bit, pkm.Language); + int form = pkm.AltForm; + int gender = pkm.Gender & 1; + bool shiny = pkm.IsShiny; + int lang = pkm.Language; + SetDex(species, bit, form, gender, shiny, lang); + } + + protected virtual void SetDex(int species, int bit, int form, int gender, bool shiny, int lang) + { + SetCaught(species); // Set the Owned Flag + SetAllDexSeenFlags(bit, form, gender, shiny); // genderless -> male + SetAllDexFlagsLanguage(bit, lang); } protected void SetDexFlags(int baseBit, int formBit, int gender, int shiny, bool value = true) @@ -103,18 +123,18 @@ namespace PKHeX.Core private bool GetIsSpeciesFormAnyDisplayed(int baseBit, int formBit) { // Check Displayed Status for base form - for (int i = 4; i < 8; i++) + for (int i = 0; i < 4; i++) { - if (GetFlag(OFS_SEEN + (i * BitSeenSize), baseBit)) + if (GetDisplayed(baseBit, i)) return true; } if (baseBit == formBit) return false; // If form is not base form, check form too - for (int i = 4; i < 8; i++) + for (int i = 0; i < 4; i++) { - if (GetFlag(OFS_SEEN + (i * BitSeenSize), formBit)) + if (GetDisplayed(formBit, i)) return true; } return false; diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs index 408eb1c56..cac9fda65 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core { public class Zukan6 : Zukan @@ -8,6 +10,15 @@ namespace PKHeX.Core protected override int DexLangFlagByteCount => 7; protected override int DexLangIDCount => 7; + public Zukan6(SaveFile sav, int dex, int langflag) + { + SAV = sav; + PokeDex = dex; + PokeDexLanguageFlags = langflag; + var wrap = SAV.ORAS ? SaveUtil.GetDexFormIndexORAS : (Func)SaveUtil.GetDexFormIndexXY; + DexFormIndexFetcher = (spec, form, _) => wrap(spec, form); + } + protected override int GetDexLangFlag(int lang) { lang--; @@ -103,7 +114,7 @@ namespace PKHeX.Core private void SetFormFlags(int species, int form, int shiny, bool value = true) { int fc = SAV.Personal[species].FormeCount; - int f = SAV.ORAS ? SaveUtil.GetDexFormIndexORAS(species, fc) : SaveUtil.GetDexFormIndexXY(species, fc); + int f = DexFormIndexFetcher(species, fc, SAV.MaxSpeciesID - 1); if (f < 0) return; diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs index 33809c604..57a7be500 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs @@ -19,9 +19,11 @@ namespace PKHeX.Core protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block. protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused) - private readonly IList FormBaseSpecies; + private IList FormBaseSpecies; - protected Zukan7() { } + protected Zukan7() + { + } public Zukan7(SaveFile sav, int dex, int langflag) { @@ -29,10 +31,12 @@ namespace PKHeX.Core PokeDex = dex; PokeDexLanguageFlags = langflag; DexFormIndexFetcher = SAV.USUM ? (Func) SaveUtil.GetDexFormIndexSM : SaveUtil.GetDexFormIndexSM; - FormBaseSpecies = GetFormIndexBaseSpeciesList(); + LoadDexList(); Debug.Assert(BitConverter.ToUInt32(SAV.Data, PokeDex) == MAGIC); } + protected void LoadDexList() => FormBaseSpecies = GetFormIndexBaseSpeciesList(); + protected override void SetAllDexSeenFlags(int baseBit, int altform, int gender, bool isShiny, bool value = true) { int species = baseBit + 1; @@ -191,7 +195,7 @@ namespace PKHeX.Core return index + SAV.MaxSpeciesID - 1; } - public IEnumerable GetEntryNames(IReadOnlyList Species) + public IList GetEntryNames(IReadOnlyList Species) { var names = new List(); for (int i = 1; i <= SAV.MaxSpeciesID; i++) diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs new file mode 100644 index 000000000..d7a4d3907 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs @@ -0,0 +1,136 @@ +namespace PKHeX.Core +{ + /// + /// Beluga specific Dex manipulator, slightly modified from Gen7. + /// + public class Zukan7b : Zukan7 + { + private const int SIZE_MAGIC = 4; // 0x2F120F17 magic + private const int SIZE_FLAGS = 4; + private const int SIZE_MISC = 0x80; // Misc Data (1024 bits) + private const int SIZE_CAUGHT = 0x68; // 832 bits + + protected override int OFS_CAUGHT => SIZE_MAGIC + SIZE_FLAGS + SIZE_MISC; + protected override int OFS_SEEN => OFS_CAUGHT + SIZE_CAUGHT; + + protected override int BitSeenSize => 0x8C; // 1120 bits + protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block. + protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused) + + public Zukan7b(SaveFile sav, int dex, int langflag) + { + SAV = sav; + PokeDex = dex; + PokeDexLanguageFlags = langflag; + DexFormIndexFetcher = SaveUtil.GetDexFormIndexGG; + LoadDexList(); + } + + public override void SetDex(PKM pkm) + { + if (!TryGetIndex(pkm.AltForm, pkm.Species, out _)) + return; + SetSizeData(pkm); + base.SetDex(pkm); + } + + protected override void SetDex(int species, int bit, int form, int gender, bool shiny, int lang) + { + if (IsBuddy(species, form)) + form = 0; + base.SetDex(species, bit, form, gender, shiny, lang); + } + + private static bool IsBuddy(int species, int form) => (species == 25 && form == 8) || (species == 133 && form == 1); + + private void SetSizeData(PKM pkm) + { + int species = pkm.Species; + int form = pkm.AltForm; + if (!TryGetIndex(form, species, out int index)) + return; + + const int group = 0; // what differentiates the 4 groups? + int offset = 0x3978 + (index * 6) + (group * 0x45C); //0x1170/4 + // todo? + } + + private static bool TryGetIndex(int form, int species, out int index) + { + index = -1; + if (form == 0 && species <= 151) + { + index = species - 1; + return true; + } + for (int i = 0; i < SizeDexInfoTable.Length; i += 3) + { + if (SizeDexInfoTable[i] != species) + continue; + if (SizeDexInfoTable[i + 1] != form) + continue; + index = SizeDexInfoTable[i + 2]; + return true; + } + return false; + } + + public static readonly ushort[] SizeDexInfoTable = + { + // spec, form, index + 808, 0, 151, + 809, 0, 152, + + 003, 1, 153, + 006, 1, 154, + 006, 2, 155, + 009, 1, 156, + 015, 1, 157, + 018, 1, 158, + 019, 1, 159, + 020, 1, 160, + 026, 1, 161, + 027, 1, 162, + 028, 1, 163, + 037, 1, 164, + 038, 1, 165, + 050, 1, 166, + 051, 1, 167, + 052, 1, 168, + 053, 1, 169, + 065, 1, 170, + 074, 1, 171, + 075, 1, 172, + 076, 1, 173, + 080, 1, 174, + 088, 1, 175, + 089, 1, 176, + 094, 1, 177, + 103, 1, 178, + 105, 1, 179, + 115, 1, 180, + 127, 1, 181, + 130, 1, 182, + 142, 1, 183, + 150, 1, 184, + 150, 2, 185, + }; + + protected override bool GetSaneFormsToIterate(int species, out int formStart, out int formEnd, int formIn) + { + switch (species) + { + case 020: // Raticate + case 105: // Marowak + formStart = 0; + formEnd = 1; + return true; + + default: + int count = SaveUtil.GetDexFormCountGG(species); + formStart = formEnd = 0; + return count < formIn; + } + } + } +} \ No newline at end of file