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;
+ }
+ }
+}