add champions side-data storage

note lack of training values being stored in home; possibly they're managed server-side in champions. wonder if they'll allow inter-player training transfer?
the 0x10 could be a hash of immutable core data... still have to wait for Champions to release to see what data is filled in, since HOME doesn't seem to manage it?
This commit is contained in:
Kurt
2026-04-02 08:48:51 -05:00
parent d15526a0be
commit 5f44fb75d4
2 changed files with 17 additions and 51 deletions

View File

@@ -1,14 +1,13 @@
using System;
using System.Text;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
// TODO -- NOTHING HERE IS CORRECT
/// <summary>
/// Side game data for Champions data linked to HOME (assumedly, not FR/LG).
/// Side game data for Champions data linked to HOME.
/// </summary>
public sealed class GameDataPC9 : HomeOptional1, IScaledSize3, IGameDataSide
public sealed class GameDataPC9 : HomeOptional1
{
private const HomeGameDataFormat ExpectFormat = HomeGameDataFormat.PC9;
private const int SIZE = HomeCrypto.SIZE_4GAME_PC9;
@@ -20,20 +19,10 @@ public sealed class GameDataPC9 : HomeOptional1, IScaledSize3, IGameDataSide
public int WriteTo(Span<byte> 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); }
public bool IsTransferred { get => Data[0x00] != 0; set => Data[0x00] = value ? (byte)1 : (byte)0; }
public ulong Timestamp { get => ReadUInt64LittleEndian(Data[0x01..]); set => WriteUInt64LittleEndian(Data[0x01..], value); }
public Span<byte> TransferID { get => Data.Slice(0x09, 0x10); set => value.CopyTo(Data.Slice(0x09, 0x10)); }
public string TransferText { get => Encoding.UTF8.GetString(TransferID); set => Encoding.UTF8.GetBytes(value, TransferID); } // todo, this is just a guess
#endregion
@@ -47,39 +36,16 @@ public sealed class GameDataPC9 : HomeOptional1, IScaledSize3, IGameDataSide
#endregion
/// <summary> Reconstructive logic to best apply suggested values. </summary>
public static GameDataPC9? TryCreate(PKH pkh)
public static GameDataPC9? TryCreate(PKH pkh) => CreateInternal();
private static GameDataPC9? CreateInternal()
{
if (!PersonalTable.ZA.IsPresentInGame(pkh.Species, pkh.Form))
return null;
var result = CreateInternal(pkh);
if (result is null)
return null;
result.PopulateFromCore(pkh);
var result = new GameDataPC9()
{
IsTransferred = true,
Timestamp = (ulong)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
// TODO HOME CP -- transfer ID?
};
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)
{
}
}

View File

@@ -57,7 +57,7 @@ private void ReadGameData1(Memory<byte> data)
}
}
private IGameDataSide ReadGameData1(Memory<byte> chunk, HomeGameDataFormat format) => format switch
private object ReadGameData1(Memory<byte> chunk, HomeGameDataFormat format) => format switch
{
HomeGameDataFormat.PB7 => DataPB7 = new GameDataPB7(chunk),
HomeGameDataFormat.PK8 => DataPK8 = new GameDataPK8(chunk),