diff --git a/PKHeX.Core/PKM/HOME/GameDataPA8.cs b/PKHeX.Core/PKM/HOME/GameDataPA8.cs
index 48bd844b5..dacd89886 100644
--- a/PKHeX.Core/PKM/HOME/GameDataPA8.cs
+++ b/PKHeX.Core/PKM/HOME/GameDataPA8.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core;
///
/// Side game data for data transferred into HOME.
///
-public sealed class GameDataPA8 : HomeOptional1, IGameDataSide, IScaledSizeAbsolute, IScaledSize3, IGameDataSplitAbility, IPokerusStatus, IAlpha
+public sealed class GameDataPA8 : HomeOptional1, IGameDataSide, IScaledSizeAbsolute, IScaledSize3, IGameDataSplitAbility, IPokerusStatus, IAlpha, IGameDataSidePP
{
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PA8;
private const int SIZE = HomeCrypto.SIZE_2GAME_PA8;
@@ -29,10 +29,10 @@ public sealed class GameDataPA8 : HomeOptional1, IGameDataSide, IScaledSize
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x09..]); set => WriteUInt16LittleEndian(Data[0x09..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x0B..]); set => WriteUInt16LittleEndian(Data[0x0B..], value); }
- public int Move1_PP { get => Data[0x0D]; set => Data[0x0D] = (byte)value; }
- public int Move2_PP { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
- public int Move3_PP { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
- public int Move4_PP { get => Data[0x10]; set => Data[0x10] = (byte)value; }
+ public byte Move1_PP { get => Data[0x0D]; set => Data[0x0D] = value; }
+ public byte Move2_PP { get => Data[0x0E]; set => Data[0x0E] = value; }
+ public byte Move3_PP { get => Data[0x0F]; set => Data[0x0F] = value; }
+ public byte Move4_PP { get => Data[0x10]; set => Data[0x10] = value; }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x11..]); set => WriteUInt16LittleEndian(Data[0x11..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x13..]); set => WriteUInt16LittleEndian(Data[0x13..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0x15..]); set => WriteUInt16LittleEndian(Data[0x15..], value); }
@@ -67,10 +67,10 @@ public sealed class GameDataPA8 : HomeOptional1, IGameDataSide, IScaledSize
// Not stored.
public PersonalInfo GetPersonalInfo(ushort species, byte form) => PersonalTable.LA.GetFormEntry(species, form);
- public int Move1_PPUps { get => 0; set { } }
- public int Move2_PPUps { get => 0; set { } }
- public int Move3_PPUps { get => 0; set { } }
- public int Move4_PPUps { get => 0; set { } }
+ public byte Move1_PPUps { get => 0; set { } }
+ public byte Move2_PPUps { get => 0; set { } }
+ public byte Move3_PPUps { get => 0; set { } }
+ public byte Move4_PPUps { get => 0; set { } }
#endregion
diff --git a/PKHeX.Core/PKM/HOME/GameDataPA9.cs b/PKHeX.Core/PKM/HOME/GameDataPA9.cs
index daf6603de..65126293e 100644
--- a/PKHeX.Core/PKM/HOME/GameDataPA9.cs
+++ b/PKHeX.Core/PKM/HOME/GameDataPA9.cs
@@ -3,8 +3,6 @@
namespace PKHeX.Core;
-// TODO HOME ZA -- Simply copied from SV, needs to be updated to ZA when official support is added.
-
///
/// Side game data for data transferred into HOME.
///
@@ -26,145 +24,75 @@ public sealed class GameDataPA9 : HomeOptional1, IGameDataSide, IScaledSize
public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x03..]); set => WriteUInt16LittleEndian(Data[0x03..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x05..]); set => WriteUInt16LittleEndian(Data[0x05..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x07..]); set => WriteUInt16LittleEndian(Data[0x07..], value); }
+ public bool IsAlpha { get => Data[0x9] != 0; set => Data[0x9] = value ? (byte)1 : (byte)0; }
- public int Move1_PP { get => Data[0x09]; set => Data[0x09] = (byte)value; }
- public int Move2_PP { get => Data[0x0A]; set => Data[0x0A] = (byte)value; }
- public int Move3_PP { get => Data[0x0B]; set => Data[0x0B] = (byte)value; }
- public int Move4_PP { get => Data[0x0C]; set => Data[0x0C] = (byte)value; }
- public int Move1_PPUps { get => Data[0x0D]; set => Data[0x0D] = (byte)value; }
- public int Move2_PPUps { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
- public int Move3_PPUps { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
- public int Move4_PPUps { get => Data[0x10]; set => Data[0x10] = (byte)value; }
+ // Second set of flags is stored in the second block of PA9, devs declared it matching block order, not sequential bitflag order.
+ private const int PlusStartB = 0xA;
+ internal const int PlusCountB = PA9.PlusCount1;
+ private const int PlusLengthB = PlusCountB / 8; // 12
+ public Span PlusFlagsB => Data.Slice(PlusStartB, PlusLengthB);
- public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x11..]); set => WriteUInt16LittleEndian(Data[0x11..], value); }
- public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x13..]); set => WriteUInt16LittleEndian(Data[0x13..], value); }
- public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0x15..]); set => WriteUInt16LittleEndian(Data[0x15..], value); }
- public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0x17..]); set => WriteUInt16LittleEndian(Data[0x17..], value); }
- public bool IsAlpha { get => Data[0x19] != 0; set => Data[0x19] = value ? (byte)1 : (byte)0; }
- // 0x1A Padding (???) TODO HOME ZA; this is adapted from SV's structure, replacing the 2 byte properties for Tera Type.
- public byte Ball { get => Data[0x1B]; set => Data[0x1B] = value; }
- public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], value); }
- public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], value); }
+ // First set of flags is stored in the third block of PA9, devs declared it matching block order, not sequential bitflag order.
+ private const int PlusStartC = PlusStartB + PlusLengthB;
+ internal const int PlusCountC = PA9.PlusCount0;
+ private const int PlusLengthC = PlusCountC / 8; // 33
+ public Span PlusFlagsC => Data.Slice(PlusStartC, PlusLengthC);
- private const int RecordStartBase = 0x20;
- internal const int COUNT_RECORD_BASE = PA9.COUNT_RECORD_BASE; // Up to 200 TM flags, but not all are used.
- private const int RecordLengthBase = COUNT_RECORD_BASE / 8; // 0x19 bytes, 8 bits
- public Span RecordFlagsBase => Data.Slice(RecordStartBase, RecordLengthBase);
+ public byte Ball { get => Data[0x37]; set => Data[0x37] = value; }
+ public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x38..]); set => WriteUInt16LittleEndian(Data[0x38..], value); }
+ public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x3A..]); set => WriteUInt16LittleEndian(Data[0x3A..], value); }
+ public byte Obedience_Level { get => Data[0x3C]; set => Data[0x3C] = value; }
+ public ushort Ability { get => ReadUInt16LittleEndian(Data[0x3D..]); set => WriteUInt16LittleEndian(Data[0x3D..], value); }
+ public byte AbilityNumber { get => Data[0x3F]; set => Data[0x3F] = value; }
- // Rev2 Additions
- public byte Obedience_Level { get => Data[0x39]; set => Data[0x39] = value; }
- public ushort Ability { get => ReadUInt16LittleEndian(Data[0x3A..]); set => WriteUInt16LittleEndian(Data[0x3A..], value); }
- public byte AbilityNumber { get => Data[0x3C]; set => Data[0x3C] = value; }
+ // not sure how best to handle the dropping of these
+ public ushort RelearnMove1 { get => 0; set { } }
+ public ushort RelearnMove2 { get => 0; set { } }
+ public ushort RelearnMove3 { get => 0; set { } }
+ public ushort RelearnMove4 { get => 0; set { } }
- // Rev3 Additions
- private const int RecordStartDLC = 0x3D;
- internal const int COUNT_RECORD_DLC = PA9.COUNT_RECORD_DLC; // 13 additional bytes allocated for DLC1/2 TM Flags
- private const int RecordLengthDLC = COUNT_RECORD_DLC / 8;
- public Span RecordFlagsDLC => Data.Slice(RecordStartDLC, RecordLengthDLC);
-
- // Rev4 Additions (ZA)
- private const int PlusStart0 = 0x4A;
- internal const int PlusCount0 = PA9.PlusCount0;
- private const int PlusLength0 = PlusCount0 / 8;
- public Span PlusFlags0 => Data.Slice(PlusStart0, PlusLength0);
-
- private const int PlusStart1 = PlusStart0 + PlusLength0; // 0x6B
- internal const int PlusCount1 = PA9.PlusCount1;
- private const int PlusLength1 = PlusCount1 / 8;
- public Span PlusFlags1 => Data.Slice(PlusStart1, PlusLength1);
-
- #endregion
-
- #region TM Flag Methods
- public bool GetMoveRecordFlag(int index)
- {
- if ((uint)index >= COUNT_RECORD_BASE)
- return GetMoveRecordFlagDLC(index - COUNT_RECORD_BASE);
- int ofs = index >> 3;
- return FlagUtil.GetFlag(Data, RecordStartBase + ofs, index & 7);
- }
-
- private bool GetMoveRecordFlagDLC(int index)
- {
- if ((uint)index >= COUNT_RECORD_DLC)
- throw new ArgumentOutOfRangeException(nameof(index));
- int ofs = index >> 3;
- return FlagUtil.GetFlag(Data, RecordStartDLC + ofs, index & 7);
- }
-
- public void SetMoveRecordFlag(int index, bool value = true)
- {
- if ((uint)index >= COUNT_RECORD_BASE)
- {
- SetMoveRecordFlagDLC(value, index - COUNT_RECORD_BASE);
- return;
- }
- int ofs = index >> 3;
- FlagUtil.SetFlag(Data, RecordStartBase + ofs, index & 7, value);
- }
-
- private void SetMoveRecordFlagDLC(bool value, int index)
- {
- if ((uint)index >= COUNT_RECORD_DLC)
- throw new ArgumentOutOfRangeException(nameof(index));
- int ofs = index >> 3;
- FlagUtil.SetFlag(Data, RecordStartDLC + ofs, index & 7, value);
- }
-
- public bool GetMoveRecordFlagAny() => GetMoveRecordFlagAnyBase() || GetMoveRecordFlagAnyDLC();
- private bool GetMoveRecordFlagAnyBase() => RecordFlagsBase.ContainsAnyExcept(0);
- private bool GetMoveRecordFlagAnyDLC() => RecordFlagsDLC.ContainsAnyExcept(0);
-
- public void ClearMoveRecordFlags()
- {
- ClearMoveRecordFlagsBase();
- ClearMoveRecordFlagsDLC();
- }
-
- private void ClearMoveRecordFlagsBase() => RecordFlagsBase.Clear();
- private void ClearMoveRecordFlagsDLC() => RecordFlagsDLC.Clear();
#endregion
#region Plus Moves
public bool GetMovePlusFlag(int index)
{
- if ((uint)index >= PlusCount0)
- return GetMovePlusFlag1(index - PlusCount0);
+ if ((uint)index >= PlusCountC)
+ return GetMovePlusFlag1(index - PlusCountC);
int ofs = index >> 3;
- return FlagUtil.GetFlag(Data, PlusStart0 + ofs, index & 7);
+ return FlagUtil.GetFlag(Data, PlusStartC + ofs, index & 7);
}
private bool GetMovePlusFlag1(int index)
{
- if ((uint)index >= PlusCount1)
+ if ((uint)index >= PlusCountB)
throw new ArgumentOutOfRangeException(nameof(index));
int ofs = index >> 3;
- return FlagUtil.GetFlag(Data, PlusStart1 + ofs, index & 7);
+ return FlagUtil.GetFlag(Data, PlusStartB + ofs, index & 7);
}
public void SetMovePlusFlag(int index, bool value = true)
{
- if ((uint)index >= PlusCount0)
+ if ((uint)index >= PlusCountC)
{
- SetMovePlusFlag1(value, index - PlusCount0);
+ SetMovePlusFlag1(value, index - PlusCountC);
return;
}
int ofs = index >> 3;
- FlagUtil.SetFlag(Data, PlusStart0 + ofs, index & 7, value);
+ FlagUtil.SetFlag(Data, PlusStartC + ofs, index & 7, value);
}
private void SetMovePlusFlag1(bool value, int index)
{
- if ((uint)index >= PlusCount1)
+ if ((uint)index >= PlusCountB)
throw new ArgumentOutOfRangeException(nameof(index));
int ofs = index >> 3;
- FlagUtil.SetFlag(Data, PlusStart1 + ofs, index & 7, value);
+ FlagUtil.SetFlag(Data, PlusStartB + ofs, index & 7, value);
}
public bool GetMovePlusFlagAny() => GetMovePlusFlagAny0() || GetMovePlusFlagAny1();
- private bool GetMovePlusFlagAny0() => PlusFlags0.ContainsAnyExcept(0);
- private bool GetMovePlusFlagAny1() => PlusFlags1.ContainsAnyExcept(0);
+ private bool GetMovePlusFlagAny0() => PlusFlagsC.ContainsAnyExcept(0);
+ private bool GetMovePlusFlagAny1() => PlusFlagsB.ContainsAnyExcept(0);
public void ClearMovePlusFlags()
{
@@ -172,8 +100,8 @@ public void ClearMovePlusFlags()
ClearMovePlusFlags1();
}
- private void ClearMovePlusFlags0() => PlusFlags0.Clear();
- private void ClearMovePlusFlags1() => PlusFlags1.Clear();
+ private void ClearMovePlusFlags0() => PlusFlagsC.Clear();
+ private void ClearMovePlusFlags1() => PlusFlagsB.Clear();
#endregion
#region Conversion
@@ -184,10 +112,8 @@ public void CopyTo(PA9 pk, PKH pkh)
{
this.CopyTo(pk);
pk.Scale = Scale;
- PlusFlags0.CopyTo(pk.PlusFlags0);
- PlusFlags1.CopyTo(pk.PlusFlags1);
- RecordFlagsBase.CopyTo(pk.RecordFlagsBase);
- RecordFlagsDLC.CopyTo(pk.RecordFlagsDLC);
+ PlusFlagsC.CopyTo(pk.PlusFlags0);
+ PlusFlagsB.CopyTo(pk.PlusFlags1);
pk.ObedienceLevel = Obedience_Level;
pk.Ability = Ability;
pk.AbilityNumber = AbilityNumber;
@@ -197,10 +123,8 @@ public void CopyFrom(PA9 pk, PKH pkh)
{
this.CopyFrom(pk);
pkh.HeightScalar = Scale = pk.Scale; // Overwrite Height
- pk.PlusFlags0.CopyTo(PlusFlags0);
- pk.PlusFlags1.CopyTo(PlusFlags1);
- pk.RecordFlagsBase.CopyTo(RecordFlagsBase);
- pk.RecordFlagsDLC.CopyTo(RecordFlagsDLC);
+ pk.PlusFlags0.CopyTo(PlusFlagsC);
+ pk.PlusFlags1.CopyTo(PlusFlagsB);
Obedience_Level = pk.ObedienceLevel;
Ability = (ushort)pk.Ability;
AbilityNumber = (byte)pk.AbilityNumber;
@@ -244,11 +168,8 @@ public PA9 ConvertToPKM(PKH pkh)
return result;
}
- private static IGameDataSide? GetNearestNeighbor(PKH pkh) => pkh.DataPK9 as IGameDataSide
- ?? pkh.DataPK8 as IGameDataSide
- ?? pkh.DataPB8 as IGameDataSide
- ?? pkh.DataPB7 as IGameDataSide
- ?? pkh.DataPA8;
+ private static IGameDataSide? GetNearestNeighbor(PKH pkh)
+ => pkh.DataPK9 ?? pkh.DataPK8 ?? pkh.DataPB8 ?? pkh.DataPB7 ?? pkh.DataPA8 as IGameDataSide;
public void InitializeFrom(IGameDataSide side, PKH pkh)
{
diff --git a/PKHeX.Core/PKM/HOME/GameDataPB7.cs b/PKHeX.Core/PKM/HOME/GameDataPB7.cs
index 5b0d1de30..638681676 100644
--- a/PKHeX.Core/PKM/HOME/GameDataPB7.cs
+++ b/PKHeX.Core/PKM/HOME/GameDataPB7.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core;
///
/// Side game data for data transferred into HOME.
///
-public sealed class GameDataPB7 : HomeOptional1, IGameDataSide, IScaledSizeAbsolute, IGameDataSplitAbility
+public sealed class GameDataPB7 : HomeOptional1, IGameDataSide, IScaledSizeAbsolute, IGameDataSplitAbility, IGameDataSidePP
{
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PB7;
private const int SIZE = HomeCrypto.SIZE_2GAME_PB7;
@@ -32,14 +32,14 @@ public sealed class GameDataPB7 : HomeOptional1, IGameDataSide, IScaledSize
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x0B..]); set => WriteUInt16LittleEndian(Data[0x0B..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x0D..]); set => WriteUInt16LittleEndian(Data[0x0D..], value); }
- public int Move1_PP { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
- public int Move2_PP { get => Data[0x10]; set => Data[0x10] = (byte)value; }
- public int Move3_PP { get => Data[0x11]; set => Data[0x11] = (byte)value; }
- public int Move4_PP { get => Data[0x12]; set => Data[0x12] = (byte)value; }
- public int Move1_PPUps { get => Data[0x13]; set => Data[0x13] = (byte)value; }
- public int Move2_PPUps { get => Data[0x14]; set => Data[0x14] = (byte)value; }
- public int Move3_PPUps { get => Data[0x15]; set => Data[0x15] = (byte)value; }
- public int Move4_PPUps { get => Data[0x16]; set => Data[0x16] = (byte)value; }
+ public byte Move1_PP { get => Data[0x0F]; set => Data[0x0F] = value; }
+ public byte Move2_PP { get => Data[0x10]; set => Data[0x10] = value; }
+ public byte Move3_PP { get => Data[0x11]; set => Data[0x11] = value; }
+ public byte Move4_PP { get => Data[0x12]; set => Data[0x12] = value; }
+ public byte Move1_PPUps { get => Data[0x13]; set => Data[0x13] = value; }
+ public byte Move2_PPUps { get => Data[0x14]; set => Data[0x14] = value; }
+ public byte Move3_PPUps { get => Data[0x15]; set => Data[0x15] = value; }
+ public byte Move4_PPUps { get => Data[0x16]; set => Data[0x16] = value; }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x17..]); set => WriteUInt16LittleEndian(Data[0x17..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x19..]); set => WriteUInt16LittleEndian(Data[0x19..], value); }
@@ -209,10 +209,8 @@ private void PopulateFromCore(PKH pkh)
Ability = (ushort)pi.GetAbilityAtIndex(index);
}
- private static IGameDataSide? GetNearestNeighbor(PKH pkh) => pkh.DataPK9 as IGameDataSide
- ?? pkh.DataPB8 as IGameDataSide
- ?? pkh.DataPK8 as IGameDataSide
- ?? pkh.DataPB7;
+ private static IGameDataSide? GetNearestNeighbor(PKH pkh)
+ => pkh.DataPA9 ?? pkh.DataPK9 ?? pkh.DataPB8 ?? pkh.DataPK8 ?? pkh.DataPB7 as IGameDataSide;
public static T Create(GameDataPB7 data) where T : IGameDataSide, new() => new()
{
diff --git a/PKHeX.Core/PKM/HOME/GameDataPB8.cs b/PKHeX.Core/PKM/HOME/GameDataPB8.cs
index 5bdbad4c2..34c3216c9 100644
--- a/PKHeX.Core/PKM/HOME/GameDataPB8.cs
+++ b/PKHeX.Core/PKM/HOME/GameDataPB8.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core;
///
/// Side game data for data transferred into HOME.
///
-public sealed class GameDataPB8 : HomeOptional1, IGameDataSide, IGameDataSplitAbility, IPokerusStatus
+public sealed class GameDataPB8 : HomeOptional1, IGameDataSide, IGameDataSplitAbility, IPokerusStatus, IGameDataSidePP
{
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PB8;
private const int SIZE = HomeCrypto.SIZE_2GAME_PB8;
@@ -24,14 +24,14 @@ public sealed class GameDataPB8 : HomeOptional1, IGameDataSide, IGameDataSp
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt16LittleEndian(Data[0x04..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x06..]); set => WriteUInt16LittleEndian(Data[0x06..], value); }
- public int Move1_PP { get => Data[0x08]; set => Data[0x08] = (byte)value; }
- public int Move2_PP { get => Data[0x09]; set => Data[0x09] = (byte)value; }
- public int Move3_PP { get => Data[0x0A]; set => Data[0x0A] = (byte)value; }
- public int Move4_PP { get => Data[0x0B]; set => Data[0x0B] = (byte)value; }
- public int Move1_PPUps { get => Data[0x0C]; set => Data[0x0C] = (byte)value; }
- public int Move2_PPUps { get => Data[0x0D]; set => Data[0x0D] = (byte)value; }
- public int Move3_PPUps { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
- public int Move4_PPUps { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
+ public byte Move1_PP { get => Data[0x08]; set => Data[0x08] = value; }
+ public byte Move2_PP { get => Data[0x09]; set => Data[0x09] = value; }
+ public byte Move3_PP { get => Data[0x0A]; set => Data[0x0A] = value; }
+ public byte Move4_PP { get => Data[0x0B]; set => Data[0x0B] = value; }
+ public byte Move1_PPUps { get => Data[0x0C]; set => Data[0x0C] = value; }
+ public byte Move2_PPUps { get => Data[0x0D]; set => Data[0x0D] = value; }
+ public byte Move3_PPUps { get => Data[0x0E]; set => Data[0x0E] = value; }
+ public byte Move4_PPUps { get => Data[0x0F]; set => Data[0x0F] = value; }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], value); }
@@ -102,10 +102,8 @@ public PB8 ConvertToPKM(PKH pkh)
return result;
}
- private static IGameDataSide? GetNearestNeighbor(PKH pkh) => pkh.DataPK9 as IGameDataSide
- ?? pkh.DataPK8 as IGameDataSide
- ?? pkh.DataPB7 as IGameDataSide
- ?? pkh.DataPA8;
+ private static IGameDataSide? GetNearestNeighbor(PKH pkh)
+ => pkh.DataPA9 ?? pkh.DataPK9 ?? pkh.DataPK8 ?? pkh.DataPB7 ?? pkh.DataPA8 as IGameDataSide;
public void InitializeFrom(IGameDataSide side, PKH pkh)
{
diff --git a/PKHeX.Core/PKM/HOME/GameDataPC9.cs b/PKHeX.Core/PKM/HOME/GameDataPC9.cs
new file mode 100644
index 000000000..483a04ca1
--- /dev/null
+++ b/PKHeX.Core/PKM/HOME/GameDataPC9.cs
@@ -0,0 +1,85 @@
+using System;
+using static System.Buffers.Binary.BinaryPrimitives;
+
+namespace PKHeX.Core;
+
+// TODO -- NOTHING HERE IS CORRECT
+
+///
+/// Side game data for Champions data linked to HOME (assumedly, not FR/LG).
+///
+public sealed class GameDataPC9 : HomeOptional1, IScaledSize3, IGameDataSide
+{
+ private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PC9;
+ private const int SIZE = HomeCrypto.SIZE_4GAME_PC9;
+ protected override HomeGameDataFormat Format => ExpectFormat;
+
+ public GameDataPC9() : base(SIZE) { }
+ public GameDataPC9(Memory data) : base(data) => EnsureSize(SIZE);
+ public GameDataPC9 Clone() => new(ToArray());
+ public int WriteTo(Span result) => WriteWithHeader(result);
+
+ #region Structure
+ public byte Scale { get => Data[0x00]; set => Data[0x00] = value; }
+ public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x01..]); set => WriteUInt16LittleEndian(Data[0x01..], value); }
+ public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x03..]); set => WriteUInt16LittleEndian(Data[0x03..], value); }
+ public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x05..]); set => WriteUInt16LittleEndian(Data[0x05..], value); }
+ public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x07..]); set => WriteUInt16LittleEndian(Data[0x07..], value); }
+
+ public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x11..]); set => WriteUInt16LittleEndian(Data[0x11..], value); }
+ public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x13..]); set => WriteUInt16LittleEndian(Data[0x13..], value); }
+ public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0x15..]); set => WriteUInt16LittleEndian(Data[0x15..], value); }
+ public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0x17..]); set => WriteUInt16LittleEndian(Data[0x17..], value); }
+ public byte Ball { get => Data[0x1B]; set => Data[0x1B] = value; }
+ public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], value); }
+ public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], value); }
+
+
+ #endregion
+
+
+ #region Conversion
+
+ public PersonalInfo GetPersonalInfo(ushort species, byte form) => PersonalTable.ZA.GetFormEntry(species, form);
+
+ public PKM ConvertToPKM(PKH pkh) => throw new NotSupportedException("No conversion routine.");
+
+ #endregion
+
+ /// Reconstructive logic to best apply suggested values.
+ public static GameDataPC9? TryCreate(PKH pkh)
+ {
+ if (!PersonalTable.ZA.IsPresentInGame(pkh.Species, pkh.Form))
+ return null;
+
+ var result = CreateInternal(pkh);
+ if (result is null)
+ return null;
+
+ result.PopulateFromCore(pkh);
+ return result;
+ }
+
+ private static GameDataPC9? CreateInternal(PKH pkh)
+ {
+ var side = GetNearestNeighbor(pkh);
+ if (side is null)
+ return null;
+
+ var result = new GameDataPC9();
+ result.InitializeFrom(side, pkh);
+ return result;
+ }
+
+ private static IGameDataSide? GetNearestNeighbor(PKH pkh)
+ => pkh.DataPA9 ?? pkh.DataPK9 ?? pkh.DataPK8 ?? pkh.DataPB8 ?? pkh.DataPB7 ?? pkh.DataPA8 as IGameDataSide;
+
+ public void InitializeFrom(IGameDataSide side, PKH pkh)
+ {
+ PopulateFromCore(pkh);
+ }
+
+ private void PopulateFromCore(PKH pkh)
+ {
+ }
+}
diff --git a/PKHeX.Core/PKM/HOME/GameDataPK8.cs b/PKHeX.Core/PKM/HOME/GameDataPK8.cs
index bcc763cf3..792621acf 100644
--- a/PKHeX.Core/PKM/HOME/GameDataPK8.cs
+++ b/PKHeX.Core/PKM/HOME/GameDataPK8.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core;
///
/// Side game data for data transferred into HOME.
///
-public sealed class GameDataPK8 : HomeOptional1, IGameDataSide, IGigantamax, IDynamaxLevel, ISociability, IGameDataSplitAbility, IPokerusStatus
+public sealed class GameDataPK8 : HomeOptional1, IGameDataSide, IGigantamax, IDynamaxLevel, ISociability, IGameDataSplitAbility, IPokerusStatus, IGameDataSidePP
{
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PK8;
private const int SIZE = HomeCrypto.SIZE_2GAME_PK8;
@@ -27,14 +27,14 @@ public sealed class GameDataPK8 : HomeOptional1, IGameDataSide, IGigantamax
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x09..]); set => WriteUInt16LittleEndian(Data[0x09..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x0B..]); set => WriteUInt16LittleEndian(Data[0x0B..], value); }
- public int Move1_PP { get => Data[0x0D]; set => Data[0x0D] = (byte)value; }
- public int Move2_PP { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
- public int Move3_PP { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
- public int Move4_PP { get => Data[0x10]; set => Data[0x10] = (byte)value; }
- public int Move1_PPUps { get => Data[0x11]; set => Data[0x11] = (byte)value; }
- public int Move2_PPUps { get => Data[0x12]; set => Data[0x12] = (byte)value; }
- public int Move3_PPUps { get => Data[0x13]; set => Data[0x13] = (byte)value; }
- public int Move4_PPUps { get => Data[0x14]; set => Data[0x14] = (byte)value; }
+ public byte Move1_PP { get => Data[0x0D]; set => Data[0x0D] = value; }
+ public byte Move2_PP { get => Data[0x0E]; set => Data[0x0E] = value; }
+ public byte Move3_PP { get => Data[0x0F]; set => Data[0x0F] = value; }
+ public byte Move4_PP { get => Data[0x10]; set => Data[0x10] = value; }
+ public byte Move1_PPUps { get => Data[0x11]; set => Data[0x11] = value; }
+ public byte Move2_PPUps { get => Data[0x12]; set => Data[0x12] = value; }
+ public byte Move3_PPUps { get => Data[0x13]; set => Data[0x13] = value; }
+ public byte Move4_PPUps { get => Data[0x14]; set => Data[0x14] = value; }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x15..]); set => WriteUInt16LittleEndian(Data[0x15..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x17..]); set => WriteUInt16LittleEndian(Data[0x17..], value); }
@@ -153,9 +153,8 @@ public PK8 ConvertToPKM(PKH pkh)
}
// Ignores LGP/E, already preferred if exists.
- private static IGameDataSide? GetNearestNeighbor(PKH pkh) => pkh.DataPK9 as IGameDataSide
- ?? pkh.DataPB8 as IGameDataSide
- ?? pkh.DataPA8;
+ private static IGameDataSide? GetNearestNeighbor(PKH pkh)
+ => pkh.DataPA9 ?? pkh.DataPK9 ?? pkh.DataPB8 ?? pkh.DataPA8 as IGameDataSide;
private static GameDataPK8 CreateViaPB7(PKH pkh, GameDataPB7 x)
{
diff --git a/PKHeX.Core/PKM/HOME/GameDataPK9.cs b/PKHeX.Core/PKM/HOME/GameDataPK9.cs
index cee285682..50395ebd9 100644
--- a/PKHeX.Core/PKM/HOME/GameDataPK9.cs
+++ b/PKHeX.Core/PKM/HOME/GameDataPK9.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core;
///
/// Side game data for data transferred into HOME.
///
-public sealed class GameDataPK9 : HomeOptional1, IGameDataSide, IScaledSize3, IGameDataSplitAbility
+public sealed class GameDataPK9 : HomeOptional1, IGameDataSide, IScaledSize3, IGameDataSplitAbility, IGameDataSidePP
{
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PK9;
private const int SIZE = HomeCrypto.SIZE_3GAME_PK9;
@@ -25,14 +25,14 @@ public sealed class GameDataPK9 : HomeOptional1, IGameDataSide, IScaledSize
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x05..]); set => WriteUInt16LittleEndian(Data[0x05..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x07..]); set => WriteUInt16LittleEndian(Data[0x07..], value); }
- public int Move1_PP { get => Data[0x09]; set => Data[0x09] = (byte)value; }
- public int Move2_PP { get => Data[0x0A]; set => Data[0x0A] = (byte)value; }
- public int Move3_PP { get => Data[0x0B]; set => Data[0x0B] = (byte)value; }
- public int Move4_PP { get => Data[0x0C]; set => Data[0x0C] = (byte)value; }
- public int Move1_PPUps { get => Data[0x0D]; set => Data[0x0D] = (byte)value; }
- public int Move2_PPUps { get => Data[0x0E]; set => Data[0x0E] = (byte)value; }
- public int Move3_PPUps { get => Data[0x0F]; set => Data[0x0F] = (byte)value; }
- public int Move4_PPUps { get => Data[0x10]; set => Data[0x10] = (byte)value; }
+ public byte Move1_PP { get => Data[0x09]; set => Data[0x09] = value; }
+ public byte Move2_PP { get => Data[0x0A]; set => Data[0x0A] = value; }
+ public byte Move3_PP { get => Data[0x0B]; set => Data[0x0B] = value; }
+ public byte Move4_PP { get => Data[0x0C]; set => Data[0x0C] = value; }
+ public byte Move1_PPUps { get => Data[0x0D]; set => Data[0x0D] = value; }
+ public byte Move2_PPUps { get => Data[0x0E]; set => Data[0x0E] = value; }
+ public byte Move3_PPUps { get => Data[0x0F]; set => Data[0x0F] = value; }
+ public byte Move4_PPUps { get => Data[0x10]; set => Data[0x10] = value; }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x11..]); set => WriteUInt16LittleEndian(Data[0x11..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x13..]); set => WriteUInt16LittleEndian(Data[0x13..], value); }
diff --git a/PKHeX.Core/PKM/HOME/HomeCrypto.cs b/PKHeX.Core/PKM/HOME/HomeCrypto.cs
index e9ade3239..e3ceef310 100644
--- a/PKHeX.Core/PKM/HOME/HomeCrypto.cs
+++ b/PKHeX.Core/PKM/HOME/HomeCrypto.cs
@@ -13,6 +13,7 @@ public static class HomeCrypto
public const int Version1 = 1;
public const int Version2 = 2;
public const int Version3 = 3;
+ public const int Version4 = 4;
public const int SIZE_1HEADER = 0x10; // 16
@@ -34,17 +35,18 @@ public static class HomeCrypto
public const int SIZE_3GAME_PK9 = 0x3D + 0xD; // 74
public const int SIZE_3STORED = 0x247; // 583
+ public const int SIZE_4GAME_PA9 = 0x40; // 64 TODO HOME ZA
+ public const int SIZE_4GAME_PC9 = 0x19; // 25
+ public const int SIZE_4STORED = 0x2A6; // 702 TODO HOME ZA
+
/// Latest maximum size of a Pokémon Home entity.
- public const int SIZE_STORED = SIZE_3STORED;
+ public const int SIZE_STORED = SIZE_4STORED;
/// Latest maximum size of a Pokémon Home entity's core data shared with all side-games.
public const int SIZE_CORE = SIZE_2CORE;
/// Latest Version identifier stored in the header.
- public const int VersionLatest = Version3;
+ public const int VersionLatest = Version4;
- public const int SIZE_4GAME_PA9 = 0x77; // TODO HOME ZA
- public const int SIZE_4STORED = 0x2BE; // 702
-
- public static bool IsKnownVersion(ushort version) => version is Version1 or Version2 or Version3;
+ public static bool IsKnownVersion(ushort version) => version is Version1 or Version2 or Version3 or Version4;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetEncryptionKey(Span key, ulong seed)
diff --git a/PKHeX.Core/PKM/HOME/HomeGameDataFormat.cs b/PKHeX.Core/PKM/HOME/HomeGameDataFormat.cs
index 6fc2a10b9..7b4847d5e 100644
--- a/PKHeX.Core/PKM/HOME/HomeGameDataFormat.cs
+++ b/PKHeX.Core/PKM/HOME/HomeGameDataFormat.cs
@@ -11,5 +11,6 @@ public enum HomeGameDataFormat : byte
PA8 = 3,
PB8 = 4,
PK9 = 5,
- PA9 = 6,
+ PC9 = 6,
+ PA9 = 7,
}
diff --git a/PKHeX.Core/PKM/HOME/IGameDataSide.cs b/PKHeX.Core/PKM/HOME/IGameDataSide.cs
index 5549a3eb3..f787ebbbc 100644
--- a/PKHeX.Core/PKM/HOME/IGameDataSide.cs
+++ b/PKHeX.Core/PKM/HOME/IGameDataSide.cs
@@ -41,10 +41,10 @@ public interface IGameDataSide : IGameDataSide where T : PKM, new()
///
public interface IGameDataSide
{
- ushort Move1 { get; set; } int Move1_PP { get; set; } int Move1_PPUps { get; set; } ushort RelearnMove1 { get; set; }
- ushort Move2 { get; set; } int Move2_PP { get; set; } int Move2_PPUps { get; set; } ushort RelearnMove2 { get; set; }
- ushort Move3 { get; set; } int Move3_PP { get; set; } int Move3_PPUps { get; set; } ushort RelearnMove3 { get; set; }
- ushort Move4 { get; set; } int Move4_PP { get; set; } int Move4_PPUps { get; set; } ushort RelearnMove4 { get; set; }
+ ushort Move1 { get; set; } ushort RelearnMove1 { get; set; }
+ ushort Move2 { get; set; } ushort RelearnMove2 { get; set; }
+ ushort Move3 { get; set; } ushort RelearnMove3 { get; set; }
+ ushort Move4 { get; set; } ushort RelearnMove4 { get; set; }
byte Ball { get; set; }
ushort MetLocation { get; set; }
ushort EggLocation { get; set; }
@@ -55,6 +55,14 @@ public interface IGameDataSide
PersonalInfo GetPersonalInfo(ushort species, byte form);
}
+public interface IGameDataSidePP
+{
+ byte Move1_PP { get; set; } byte Move1_PPUps { get; set; }
+ byte Move2_PP { get; set; } byte Move2_PPUps { get; set; }
+ byte Move3_PP { get; set; } byte Move3_PPUps { get; set; }
+ byte Move4_PP { get; set; } byte Move4_PPUps { get; set; }
+}
+
public static class GameDataSideExtensions
{
extension(IGameDataSide data)
@@ -65,13 +73,21 @@ public static class GameDataSideExtensions
/// Destination entity
public void CopyTo(PKM pk)
{
- pk.Move1 = data.Move1; pk.Move1_PP = data.Move1_PP; pk.Move1_PPUps = data.Move1_PPUps; pk.RelearnMove1 = data.RelearnMove1;
- pk.Move2 = data.Move2; pk.Move2_PP = data.Move2_PP; pk.Move2_PPUps = data.Move2_PPUps; pk.RelearnMove2 = data.RelearnMove2;
- pk.Move3 = data.Move3; pk.Move3_PP = data.Move3_PP; pk.Move3_PPUps = data.Move3_PPUps; pk.RelearnMove3 = data.RelearnMove3;
- pk.Move4 = data.Move4; pk.Move4_PP = data.Move4_PP; pk.Move4_PPUps = data.Move4_PPUps; pk.RelearnMove4 = data.RelearnMove4;
+ pk.Move1 = data.Move1; pk.RelearnMove1 = data.RelearnMove1;
+ pk.Move2 = data.Move2; pk.RelearnMove2 = data.RelearnMove2;
+ pk.Move3 = data.Move3; pk.RelearnMove3 = data.RelearnMove3;
+ pk.Move4 = data.Move4; pk.RelearnMove4 = data.RelearnMove4;
pk.Ball = data.Ball;
pk.MetLocation = data.MetLocation;
pk.EggLocation = data.EggLocation;
+
+ if (data is IGameDataSidePP pps)
+ {
+ pk.Move1_PP = pps.Move1_PP; pk.Move1_PPUps = pps.Move1_PPUps;
+ pk.Move2_PP = pps.Move2_PP; pk.Move2_PPUps = pps.Move2_PPUps;
+ pk.Move3_PP = pps.Move3_PP; pk.Move3_PPUps = pps.Move3_PPUps;
+ pk.Move4_PP = pps.Move4_PP; pk.Move4_PPUps = pps.Move4_PPUps;
+ }
}
///
@@ -80,13 +96,21 @@ public void CopyTo(PKM pk)
/// Destination entity
public void CopyTo(IGameDataSide pk)
{
- pk.Move1 = data.Move1; pk.Move1_PP = data.Move1_PP; pk.Move1_PPUps = data.Move1_PPUps; pk.RelearnMove1 = data.RelearnMove1;
- pk.Move2 = data.Move2; pk.Move2_PP = data.Move2_PP; pk.Move2_PPUps = data.Move2_PPUps; pk.RelearnMove2 = data.RelearnMove2;
- pk.Move3 = data.Move3; pk.Move3_PP = data.Move3_PP; pk.Move3_PPUps = data.Move3_PPUps; pk.RelearnMove3 = data.RelearnMove3;
- pk.Move4 = data.Move4; pk.Move4_PP = data.Move4_PP; pk.Move4_PPUps = data.Move4_PPUps; pk.RelearnMove4 = data.RelearnMove4;
+ pk.Move1 = data.Move1; pk.RelearnMove1 = data.RelearnMove1;
+ pk.Move2 = data.Move2; pk.RelearnMove2 = data.RelearnMove2;
+ pk.Move3 = data.Move3; pk.RelearnMove3 = data.RelearnMove3;
+ pk.Move4 = data.Move4; pk.RelearnMove4 = data.RelearnMove4;
pk.Ball = data.Ball;
pk.MetLocation = data.MetLocation;
pk.EggLocation = data.EggLocation;
+
+ if (data is IGameDataSidePP pps && pk is IGameDataSidePP ppk)
+ {
+ ppk.Move1_PP = pps.Move1_PP; ppk.Move1_PPUps = pps.Move1_PPUps;
+ ppk.Move2_PP = pps.Move2_PP; ppk.Move2_PPUps = pps.Move2_PPUps;
+ ppk.Move3_PP = pps.Move3_PP; ppk.Move3_PPUps = pps.Move3_PPUps;
+ ppk.Move4_PP = pps.Move4_PP; ppk.Move4_PPUps = pps.Move4_PPUps;
+ }
}
///
@@ -95,13 +119,21 @@ public void CopyTo(IGameDataSide pk)
/// Destination entity
public void CopyFrom(PKM pk)
{
- data.Move1 = pk.Move1; data.Move1_PP = pk.Move1_PP; data.Move1_PPUps = pk.Move1_PPUps; data.RelearnMove1 = pk.RelearnMove1;
- data.Move2 = pk.Move2; data.Move2_PP = pk.Move2_PP; data.Move2_PPUps = pk.Move2_PPUps; data.RelearnMove2 = pk.RelearnMove2;
- data.Move3 = pk.Move3; data.Move3_PP = pk.Move3_PP; data.Move3_PPUps = pk.Move3_PPUps; data.RelearnMove3 = pk.RelearnMove3;
- data.Move4 = pk.Move4; data.Move4_PP = pk.Move4_PP; data.Move4_PPUps = pk.Move4_PPUps; data.RelearnMove4 = pk.RelearnMove4;
+ data.Move1 = pk.Move1; data.RelearnMove1 = pk.RelearnMove1;
+ data.Move2 = pk.Move2; data.RelearnMove2 = pk.RelearnMove2;
+ data.Move3 = pk.Move3; data.RelearnMove3 = pk.RelearnMove3;
+ data.Move4 = pk.Move4; data.RelearnMove4 = pk.RelearnMove4;
data.Ball = pk.Ball;
data.MetLocation = pk.MetLocation;
data.EggLocation = pk.EggLocation;
+
+ if (pk is IGameDataSidePP ppk && data is IGameDataSidePP pps)
+ {
+ pps.Move1_PP = ppk.Move1_PP; pps.Move1_PPUps = ppk.Move1_PPUps;
+ pps.Move2_PP = ppk.Move2_PP; pps.Move2_PPUps = ppk.Move2_PPUps;
+ pps.Move3_PP = ppk.Move3_PP; pps.Move3_PPUps = ppk.Move3_PPUps;
+ pps.Move4_PP = ppk.Move4_PP; pps.Move4_PPUps = ppk.Move4_PPUps;
+ }
}
///
@@ -116,10 +148,15 @@ public void ResetMoves(ushort species, byte form, byte level, ILearnSource sourc
data.Move2 = moves[1];
data.Move3 = moves[2];
data.Move4 = moves[3];
- data.Move1_PP = MoveInfo.GetPP(context, moves[0]);
- data.Move2_PP = MoveInfo.GetPP(context, moves[1]);
- data.Move3_PP = MoveInfo.GetPP(context, moves[2]);
- data.Move4_PP = MoveInfo.GetPP(context, moves[3]);
+
+ if (data is IGameDataSidePP pps)
+ {
+ pps.Move1_PPUps = 0; pps.Move2_PPUps = 0; pps.Move3_PPUps = 0; pps.Move4_PPUps = 0;
+ pps.Move1_PP = MoveInfo.GetPP(context, moves[0]);
+ pps.Move2_PP = MoveInfo.GetPP(context, moves[1]);
+ pps.Move3_PP = MoveInfo.GetPP(context, moves[2]);
+ pps.Move4_PP = MoveInfo.GetPP(context, moves[3]);
+ }
}
}
}
diff --git a/PKHeX.Core/PKM/HOME/PKH.cs b/PKHeX.Core/PKM/HOME/PKH.cs
index 86e5172e8..01ccf229b 100644
--- a/PKHeX.Core/PKM/HOME/PKH.cs
+++ b/PKHeX.Core/PKM/HOME/PKH.cs
@@ -14,6 +14,7 @@ public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBat
public GameDataPA8? DataPA8 { get; private set; }
public GameDataPB8? DataPB8 { get; private set; }
public GameDataPK9? DataPK9 { get; private set; }
+ public GameDataPC9? DataPC9 { get; private set; }
public GameDataPA9? DataPA9 { get; private set; }
public override EntityContext Context => EntityContext.None;
@@ -63,6 +64,7 @@ private void ReadGameData1(Memory data)
HomeGameDataFormat.PA8 => DataPA8 = new GameDataPA8(chunk),
HomeGameDataFormat.PB8 => DataPB8 = new GameDataPB8(chunk),
HomeGameDataFormat.PK9 => DataPK9 = new GameDataPK9(chunk),
+ HomeGameDataFormat.PC9 => DataPC9 = new GameDataPC9(chunk),
HomeGameDataFormat.PA9 => DataPA9 = new GameDataPA9(chunk),
_ => throw new ArgumentException($"Unknown {nameof(HomeGameDataFormat)} {format}"),
};
@@ -213,14 +215,14 @@ private static Memory DecryptHome(Memory data)
public override ushort Move2 { get => LatestGameData.Move2 ; set => LatestGameData.Move2 = value; }
public override ushort Move3 { get => LatestGameData.Move3 ; set => LatestGameData.Move3 = value; }
public override ushort Move4 { get => LatestGameData.Move4 ; set => LatestGameData.Move4 = value; }
- public override int Move1_PP { get => LatestGameData.Move1_PP ; set => LatestGameData.Move1_PP = value; }
- public override int Move2_PP { get => LatestGameData.Move2_PP ; set => LatestGameData.Move2_PP = value; }
- public override int Move3_PP { get => LatestGameData.Move3_PP ; set => LatestGameData.Move3_PP = value; }
- public override int Move4_PP { get => LatestGameData.Move4_PP ; set => LatestGameData.Move4_PP = value; }
- public override int Move1_PPUps { get => LatestGameData.Move1_PPUps; set => LatestGameData.Move1_PPUps = value; }
- public override int Move2_PPUps { get => LatestGameData.Move2_PPUps; set => LatestGameData.Move2_PPUps = value; }
- public override int Move3_PPUps { get => LatestGameData.Move3_PPUps; set => LatestGameData.Move3_PPUps = value; }
- public override int Move4_PPUps { get => LatestGameData.Move4_PPUps; set => LatestGameData.Move4_PPUps = value; }
+ public override int Move1_PP { get => (LatestGameData as IGameDataSidePP)?.Move1_PP ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move1_PP = (byte)value; }
+ public override int Move2_PP { get => (LatestGameData as IGameDataSidePP)?.Move2_PP ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move2_PP = (byte)value; }
+ public override int Move3_PP { get => (LatestGameData as IGameDataSidePP)?.Move3_PP ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move3_PP = (byte)value; }
+ public override int Move4_PP { get => (LatestGameData as IGameDataSidePP)?.Move4_PP ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move4_PP = (byte)value; }
+ public override int Move1_PPUps { get => (LatestGameData as IGameDataSidePP)?.Move1_PPUps ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move1_PPUps = (byte)value; }
+ public override int Move2_PPUps { get => (LatestGameData as IGameDataSidePP)?.Move2_PPUps ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move2_PPUps = (byte)value; }
+ public override int Move3_PPUps { get => (LatestGameData as IGameDataSidePP)?.Move3_PPUps ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move3_PPUps = (byte)value; }
+ public override int Move4_PPUps { get => (LatestGameData as IGameDataSidePP)?.Move4_PPUps ?? 0; set => (LatestGameData as IGameDataSidePP)?.Move4_PPUps = (byte)value; }
public override byte Ball { get => LatestGameData.Ball; set => LatestGameData.Ball = value; }
public override ushort MetLocation { get => LatestGameData.MetLocation; set => LatestGameData.MetLocation = value; }
@@ -309,6 +311,7 @@ private void WriteTo(Span span, int innerLength)
if (DataPA8 is { } pa8) ctr += pa8.WriteTo(span[ctr..]);
if (DataPB8 is { } pb8) ctr += pb8.WriteTo(span[ctr..]);
if (DataPK9 is { } pk9) ctr += pk9.WriteTo(span[ctr..]);
+ if (DataPC9 is { } pc9) ctr += pc9.WriteTo(span[ctr..]);
if (DataPA9 is { } pa9) ctr += pa9.WriteTo(span[ctr..]);
WriteUInt16LittleEndian(gameDataLengthSpan, GameDataSize = (ushort)(ctr - gameDataStart));