From 7b6ecd11ba46be74ec815e898e0e2642e077985f Mon Sep 17 00:00:00 2001 From: Kaphotics Date: Fri, 30 Sep 2016 19:05:35 -0700 Subject: [PATCH] Add strategy memo editing Saves folder getting pretty populated, move to substructures --- PKHeX/PKHeX.csproj | 10 +- PKHeX/Saves/SAV3Colosseum.cs | 24 +++- PKHeX/Saves/SAV3XD.cs | 28 ++++- PKHeX/Saves/{ => Substructures}/BlockInfo.cs | 0 .../Saves/{ => Substructures}/BoxWallpaper.cs | 0 PKHeX/Saves/{ => Substructures}/Inventory.cs | 0 .../Saves/{ => Substructures}/SaveObjects.cs | 0 PKHeX/Saves/Substructures/ShadowInfo.cs | 33 ++++++ PKHeX/Saves/Substructures/StrategyMemo.cs | 107 ++++++++++++++++++ 9 files changed, 194 insertions(+), 8 deletions(-) rename PKHeX/Saves/{ => Substructures}/BlockInfo.cs (100%) rename PKHeX/Saves/{ => Substructures}/BoxWallpaper.cs (100%) rename PKHeX/Saves/{ => Substructures}/Inventory.cs (100%) rename PKHeX/Saves/{ => Substructures}/SaveObjects.cs (100%) create mode 100644 PKHeX/Saves/Substructures/ShadowInfo.cs create mode 100644 PKHeX/Saves/Substructures/StrategyMemo.cs diff --git a/PKHeX/PKHeX.csproj b/PKHeX/PKHeX.csproj index 2e9666a7c..a1ff41251 100644 --- a/PKHeX/PKHeX.csproj +++ b/PKHeX/PKHeX.csproj @@ -168,9 +168,9 @@ QR.cs - - - + + + @@ -183,6 +183,8 @@ + + Form @@ -232,7 +234,7 @@ True Resources.resx - + diff --git a/PKHeX/Saves/SAV3Colosseum.cs b/PKHeX/Saves/SAV3Colosseum.cs index de34892a1..e676ed9a1 100644 --- a/PKHeX/Saves/SAV3Colosseum.cs +++ b/PKHeX/Saves/SAV3Colosseum.cs @@ -24,6 +24,8 @@ public sealed class SAV3Colosseum : SaveFile private readonly int SaveCount = -1; private readonly int SaveIndex = -1; + private readonly StrategyMemo StrategyMemo; + private readonly int Memo; private readonly ushort[] LegalItems, LegalKeyItems, LegalBalls, LegalTMHMs, LegalBerries, LegalCologne; private readonly int OFS_PouchCologne; public SAV3Colosseum(byte[] data = null) @@ -72,6 +74,8 @@ public SAV3Colosseum(byte[] data = null) Box = 0x00B90; Daycare = 0x08170; + Memo = 0x082B0; + StrategyMemo = new StrategyMemo(Data, Memo, xd:false); LegalItems = Legal.Pouch_Items_COLO; LegalKeyItems = Legal.Pouch_Key_COLO; @@ -90,6 +94,7 @@ public SAV3Colosseum(byte[] data = null) private readonly byte[] OriginalData; public override byte[] Write(bool DSV) { + StrategyMemo.FinalData.CopyTo(Data, Memo); setChecksums(); // Get updated save slot data @@ -267,7 +272,24 @@ public override byte[] decryptPKM(byte[] data) return data; } - protected override void setDex(PKM pkm) { } + protected override void setDex(PKM pkm) + { + // Dex Related + var entry = StrategyMemo.GetEntry(pkm.Species); + if (entry.IsEmpty) // Populate + { + entry.Species = pkm.Species; + entry.PID = pkm.PID; + entry.TID = pkm.TID; + entry.SID = pkm.SID; + } + if (entry.Matches(pkm.Species, pkm.PID, pkm.TID, pkm.SID)) + { + entry.Seen = true; + entry.Owned = true; + } + StrategyMemo.SetEntry(entry); + } private TimeSpan PlayedSpan { diff --git a/PKHeX/Saves/SAV3XD.cs b/PKHeX/Saves/SAV3XD.cs index 789ad3aab..257f23ca8 100644 --- a/PKHeX/Saves/SAV3XD.cs +++ b/PKHeX/Saves/SAV3XD.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; namespace PKHeX @@ -15,6 +16,8 @@ public sealed class SAV3XD : SaveFile private readonly int SaveCount = -1; private readonly int SaveIndex = -1; + private readonly int Memo; + private readonly StrategyMemo StrategyMemo; private readonly ushort[] LegalItems, LegalKeyItems, LegalBalls, LegalTMHMs, LegalBerries, LegalCologne, LegalDisc; private readonly int OFS_PouchCologne, OFS_PouchDisc; private readonly int[] subOffsets = new int[16]; @@ -67,11 +70,11 @@ public SAV3XD(byte[] data = null) Party = Trainer1 + 0x30; Box = subOffsets[2] + 0xA8; Daycare = subOffsets[4] + 0xA8; - // Memo = subOffsets[5] + 0xA8; + Memo = subOffsets[5] + 0xA8; // Shadow = subOffsets[7] + 0xA8; // Purifier = subOffsets[14] + 0xA8; - System.IO.File.WriteAllBytes("xd", Data); + StrategyMemo = new StrategyMemo(Data, Memo, xd: true); OFS_PouchHeldItem = Trainer1 + 0x4C8; OFS_PouchKeyItem = Trainer1 + 0x540; @@ -99,6 +102,8 @@ public SAV3XD(byte[] data = null) private readonly byte[] OriginalData; public override byte[] Write(bool DSV) { + // Set Memo Back + StrategyMemo.FinalData.CopyTo(Data, Memo); setChecksums(); // Get updated save slot data @@ -239,7 +244,24 @@ public override byte[] decryptPKM(byte[] data) return data; } - protected override void setDex(PKM pkm) { } + protected override void setDex(PKM pkm) + { + // Dex Related + var entry = StrategyMemo.GetEntry(pkm.Species); + if (entry.IsEmpty) // Populate + { + entry.Species = pkm.Species; + entry.PID = pkm.PID; + entry.TID = pkm.TID; + entry.SID = pkm.SID; + } + if (entry.Matches(pkm.Species, pkm.PID, pkm.TID, pkm.SID)) + { + entry.Seen = true; + entry.Owned = true; + } + StrategyMemo.SetEntry(entry); + } public override InventoryPouch[] Inventory { diff --git a/PKHeX/Saves/BlockInfo.cs b/PKHeX/Saves/Substructures/BlockInfo.cs similarity index 100% rename from PKHeX/Saves/BlockInfo.cs rename to PKHeX/Saves/Substructures/BlockInfo.cs diff --git a/PKHeX/Saves/BoxWallpaper.cs b/PKHeX/Saves/Substructures/BoxWallpaper.cs similarity index 100% rename from PKHeX/Saves/BoxWallpaper.cs rename to PKHeX/Saves/Substructures/BoxWallpaper.cs diff --git a/PKHeX/Saves/Inventory.cs b/PKHeX/Saves/Substructures/Inventory.cs similarity index 100% rename from PKHeX/Saves/Inventory.cs rename to PKHeX/Saves/Substructures/Inventory.cs diff --git a/PKHeX/Saves/SaveObjects.cs b/PKHeX/Saves/Substructures/SaveObjects.cs similarity index 100% rename from PKHeX/Saves/SaveObjects.cs rename to PKHeX/Saves/Substructures/SaveObjects.cs diff --git a/PKHeX/Saves/Substructures/ShadowInfo.cs b/PKHeX/Saves/Substructures/ShadowInfo.cs new file mode 100644 index 000000000..ef7d6e793 --- /dev/null +++ b/PKHeX/Saves/Substructures/ShadowInfo.cs @@ -0,0 +1,33 @@ +namespace PKHeX +{ + public class ShadowInfoXD + { + private readonly byte[] Data; + private const int SIZE_ENTRY = 72; + public ShadowInfoXD(byte[] data) + { + Data = (byte[])(data?.Clone() ?? new byte[SIZE_ENTRY]); + } + + public bool IsSnagged => Data[0] >> 6 != 0; + public bool IsPurified { get { return Data[0] >> 7 == 1; } set { Data[0] &= 0x7F; if (value) Data[0] |= 0x80; } } + public ushort Species { get { return BigEndian.ToUInt16(Data, 0x1A); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x1A); } } + public uint PID { get { return BigEndian.ToUInt32(Data, 0x1C); }set { BigEndian.GetBytes(value).CopyTo(Data, 0x1C); } } + public int Purification { get { return BigEndian.ToInt32(Data, 0x24); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x24); } } + + public uint EXP { get { return BigEndian.ToUInt32(Data, 0x04) >> 12; } set { BigEndian.GetBytes((BigEndian.ToUInt32(Data, 0x04) & 0xFFF) | (value << 12)).CopyTo(Data, 0x04); } } + } + + public class ShadowInfoColo + { + private readonly byte[] Data; + private const int SIZE_ENTRY = 12; + public ShadowInfoColo(byte[] data = null) + { + Data = (byte[])(data?.Clone() ?? new byte[SIZE_ENTRY]); + } + public uint PID { get { return BigEndian.ToUInt32(Data, 0x00); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x00); } } + public int Met_Location { get { return BigEndian.ToUInt16(Data, 0x06); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 0x06); } } + public uint _0x08 { get { return BigEndian.ToUInt32(Data, 0x08); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x08); } } + } +} \ No newline at end of file diff --git a/PKHeX/Saves/Substructures/StrategyMemo.cs b/PKHeX/Saves/Substructures/StrategyMemo.cs new file mode 100644 index 000000000..de049d371 --- /dev/null +++ b/PKHeX/Saves/Substructures/StrategyMemo.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PKHeX +{ + public class StrategyMemo + { + private readonly bool XD; + private const int SIZE_ENTRY = 12; + private readonly List Entries = new List(); + private StrategyMemoEntry this[int Species] => Entries.FirstOrDefault(e => e.Species == Species); + + public StrategyMemo(byte[] input, int offset, bool xd) + { + XD = xd; + int count = BigEndian.ToInt16(input, offset); + if (count > 500) + count = 500; + for (int i = 0; i < count; i++) + { + byte[] data = new byte[SIZE_ENTRY]; + Array.Copy(input, 4 + offset + SIZE_ENTRY * i, data, 0, SIZE_ENTRY); + Entries.Add(new StrategyMemoEntry(XD, data)); + } + } + public byte[] FinalData => BigEndian.GetBytes(Entries.Count) // count followed by populated entries + .Concat(Entries.Where(entry => entry.Species != 0).SelectMany(entry => entry.Data)).ToArray(); + + public StrategyMemoEntry GetEntry(int Species) + { + return this[Species] ?? new StrategyMemoEntry(XD); + } + public void SetEntry(StrategyMemoEntry entry) + { + int index = Array.FindIndex(Entries.ToArray(), ent => ent.Species == entry.Species); + if (index > 0) + Entries[index] = entry; + else + Entries.Add(entry); + } + public class StrategyMemoEntry + { + public readonly byte[] Data; + private readonly bool XD; + public StrategyMemoEntry(bool xd, byte[] data = null) + { + Data = data ?? new byte[SIZE_ENTRY]; + XD = xd; + } + + public int Species + { + get + { + int val = BigEndian.ToUInt16(Data, 0) & 0x1FF; + return PKX.getG4Species(val); + } + set + { + value = PKX.getG3Species(value); + int cval = BigEndian.ToUInt16(Data, 0); + cval &= 0xE00; value &= 0x1FF; cval |= value; + BigEndian.GetBytes((ushort)cval).CopyTo(Data, 0); + } + } + private bool Flag0 { get { return Data[0] >> 6 == 1; } set { Data[0] &= 0xBF; if (value) Data[0] |= 0x40; } } // Unused + private bool Flag1 { get { return Data[0] >> 7 == 1; } set { Data[0] &= 0x7F; if (value) Data[0] |= 0x80; } } // Complete Entry + public int SID { get { return BigEndian.ToUInt16(Data, 4); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 4); } } + public int TID { get { return BigEndian.ToUInt16(Data, 6); } set { BigEndian.GetBytes((ushort)value).CopyTo(Data, 6); } } + public uint PID { get { return BigEndian.ToUInt32(Data, 8); } set { BigEndian.GetBytes(value).CopyTo(Data, 8); } } + + public bool Seen + { + get + { + if (XD) return !Flag1; + return Species != 0; + } + set + { + if (XD) + Flag1 = !value; + else if (!value) + new byte[SIZE_ENTRY].CopyTo(Data, 0); + } + } + public bool Owned + { + get + { + if (XD) return false; + return Flag0 | Flag1 == false; + } + set + { + if (XD) return; + if (!value) + Flag1 = true; + } + } + + public bool IsEmpty => Species == 0; + public bool Matches(int species, uint pid, int tid, int sid) => Species == species && PID == pid && TID == tid && SID == sid; + } + } +}