Make mysterygifts memory-backed objects

This commit is contained in:
Kurt 2025-05-24 00:10:57 -05:00
parent be67b007d5
commit 48954533b5
21 changed files with 409 additions and 391 deletions

View File

@ -70,19 +70,19 @@ public static class EncounterEvent
public static WC9[] EGDB_G9 { get; private set; } = [];
#endregion
private static PCD[] GetPCDDB(ReadOnlySpan<byte> bin) => Get(bin, PCD.Size, static d => new PCD(d));
private static PGF[] GetPGFDB(ReadOnlySpan<byte> bin) => Get(bin, PGF.Size, static d => new PGF(d));
private static PCD[] GetPCDDB(Memory<byte> bin) => Get(bin, PCD.Size, static d => new PCD(d));
private static PGF[] GetPGFDB(Memory<byte> bin) => Get(bin, PGF.Size, static d => new PGF(d));
private static WC6[] GetWC6DB(ReadOnlySpan<byte> wc6bin, ReadOnlySpan<byte> wc6full) => WC6Full.GetArray(wc6full, wc6bin);
private static WC7[] GetWC7DB(ReadOnlySpan<byte> wc7bin, ReadOnlySpan<byte> wc7full) => WC7Full.GetArray(wc7full, wc7bin);
private static WC6[] GetWC6DB(Memory<byte> wc6bin, Memory<byte> wc6full) => WC6Full.GetArray(wc6full, wc6bin);
private static WC7[] GetWC7DB(Memory<byte> wc7bin, Memory<byte> wc7full) => WC7Full.GetArray(wc7full, wc7bin);
private static WB7[] GetWB7DB(ReadOnlySpan<byte> bin) => Get(bin, WB7.Size, static d => new WB7(d));
private static WC8[] GetWC8DB(ReadOnlySpan<byte> bin) => Get(bin, WC8.Size, static d => new WC8(d));
private static WB8[] GetWB8DB(ReadOnlySpan<byte> bin) => Get(bin, WB8.Size, static d => new WB8(d));
private static WA8[] GetWA8DB(ReadOnlySpan<byte> bin) => Get(bin, WA8.Size, static d => new WA8(d));
private static WC9[] GetWC9DB(ReadOnlySpan<byte> bin) => Get(bin, WC9.Size, static d => new WC9(d));
private static WB7[] GetWB7DB(Memory<byte> bin) => Get(bin, WB7.Size, static d => new WB7(d));
private static WC8[] GetWC8DB(Memory<byte> bin) => Get(bin, WC8.Size, static d => new WC8(d));
private static WB8[] GetWB8DB(Memory<byte> bin) => Get(bin, WB8.Size, static d => new WB8(d));
private static WA8[] GetWA8DB(Memory<byte> bin) => Get(bin, WA8.Size, static d => new WA8(d));
private static WC9[] GetWC9DB(Memory<byte> bin) => Get(bin, WC9.Size, static d => new WC9(d));
private static T[] Get<T>(ReadOnlySpan<byte> bin, int size, Func<byte[], T> ctor)
private static T[] Get<T>(Memory<byte> bin, int size, Func<Memory<byte>, T> ctor)
{
// bin is a multiple of size
// bin.Length % size == 0
@ -91,7 +91,7 @@ private static T[] Get<T>(ReadOnlySpan<byte> bin, int size, Func<byte[], T> ctor
for (int i = 0; i < result.Length; i++)
{
var offset = i * size;
var slice = bin.Slice(offset, size).ToArray();
var slice = bin.Slice(offset, size);
result[i] = ctor(slice);
}
return result;

View File

@ -11,7 +11,7 @@ public sealed class EncounterGenerator4 : IEncounterGenerator
public bool CanGenerateEggs => true;
// Utility
internal static readonly PGT RangerManaphy = new() { Data = { [0] = 7, [8] = 1 } };
internal static readonly PGT RangerManaphy = new() { CardType = (ushort)GiftType4.ManaphyEgg, ItemSubID = 1 /* pid never shiny */ };
public IEnumerable<IEncounterable> GetEncounters(PKM pk, LegalInfo info)
{

View File

@ -5,14 +5,14 @@ namespace PKHeX.Core;
/// <summary>
/// Mystery Gift backed by serialized fields from ROM/SAV data, rather than observed specifications.
/// </summary>
public abstract class DataMysteryGift(byte[] Data) : MysteryGift
public abstract class DataMysteryGift(Memory<byte> Raw) : MysteryGift
{
public readonly byte[] Data = Data;
public Span<byte> Data => Raw.Span;
/// <summary>
/// Returns an array for exporting outside the program (to disk, etc.).
/// </summary>
public virtual byte[] Write() => Data;
public virtual ReadOnlySpan<byte> Write() => Data;
public override int GetHashCode()
{
@ -27,11 +27,13 @@ public override int GetHashCode()
/// </summary>
public override MysteryGift Clone()
{
byte[] data = (byte[])Data.Clone();
var data = Data.ToArray();
var result = GetMysteryGift(data);
ArgumentNullException.ThrowIfNull(result);
return result;
}
public override bool Empty => !Data.AsSpan().ContainsAnyExcept<byte>(0);
public sealed override bool Empty => !Data.ContainsAnyExcept<byte>(0);
public void Clear() => Data.Clear();
}

View File

@ -27,8 +27,8 @@ public abstract class MysteryGift : IEncounterable, IMoveset, ITrainerID32, IFat
/// <param name="data">Raw data of the mystery gift.</param>
/// <param name="ext">Extension of the file from which the <paramref name="data"/> was retrieved.</param>
/// <returns>An instance of <see cref="MysteryGift"/> representing the given data, or null if <paramref name="data"/> or <paramref name="ext"/> is invalid.</returns>
/// <remarks>This overload differs from <see cref="GetMysteryGift(byte[])"/> by checking the <paramref name="data"/>/<paramref name="ext"/> combo for validity. If either is invalid, a null reference is returned.</remarks>
public static DataMysteryGift? GetMysteryGift(byte[] data, ReadOnlySpan<char> ext) => data.Length switch
/// <remarks>This overload differs from <see cref="GetMysteryGift(Memory{byte})"/> by checking the <paramref name="data"/>/<paramref name="ext"/> combo for validity. If either is invalid, a null reference is returned.</remarks>
public static DataMysteryGift? GetMysteryGift(Memory<byte> data, ReadOnlySpan<char> ext) => data.Length switch
{
PGT.Size when Equals(ext, ".pgt") => new PGT(data),
PCD.Size when Equals(ext, ".pcd", ".wc4") => new PCD(data),
@ -56,7 +56,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, ITrainerID32, IFat
/// </summary>
/// <param name="data">Raw data of the mystery gift.</param>
/// <returns>An instance of <see cref="MysteryGift"/> representing the given data, or null if <paramref name="data"/> is invalid.</returns>
public static DataMysteryGift? GetMysteryGift(byte[] data) => data.Length switch
public static DataMysteryGift? GetMysteryGift(Memory<byte> data) => data.Length switch
{
PGT.Size => new PGT(data),
PCD.Size => new PCD(data),
@ -65,15 +65,15 @@ public abstract class MysteryGift : IEncounterable, IMoveset, ITrainerID32, IFat
WB8.Size => new WB8(data),
// WC8/WC5Full: WC8 0x2CF always 0, WC5Full 0x2CF contains card checksum
WC8.Size => data[0x2CF] == 0 ? new WC8(data) : new PGF(data),
WC8.Size => data.Span[0x2CF] == 0 ? new WC8(data) : new PGF(data),
// WA8/WC9: WA8 CardType >0 for WA8, 0 for WC9.
WA8.Size => data[0xF] > 0 ? new WA8(data) : new WC9(data),
WA8.Size => data.Span[0xF] > 0 ? new WA8(data) : new WC9(data),
// WC6/WC7: Check year
WC6.Size => ReadUInt32LittleEndian(data.AsSpan(0x4C)) / 10000 < 2000 ? new WC7(data) : new WC6(data),
WC6.Size => ReadUInt32LittleEndian(data.Span[0x4C..]) / 10000 < 2000 ? new WC7(data) : new WC6(data),
// WC6Full/WC7Full: 0x205 has 3 * 0x46 for Gen6, now only 2.
WC6Full.Size => data[0x205] == 0 ? new WC7Full(data).Gift : new WC6Full(data).Gift,
WC6Full.Size => data.Span[0x205] == 0 ? new WC7Full(data).Gift : new WC6Full(data).Gift,
_ => null,
};

View File

@ -12,10 +12,11 @@ namespace PKHeX.Core;
/// https://projectpokemon.org/home/forums/topic/5870-pok%C3%A9mon-mystery-gift-editor-v143-now-with-bw-support/
/// See also: http://tccphreak.shiny-clique.net/debugger/pcdfiles.htm
/// </remarks>
public sealed class PCD(byte[] Data)
: DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, IRestrictVersion, IRandomCorrelation
public sealed class PCD(Memory<byte> raw)
: DataMysteryGift(raw), IRibbonSetEvent3, IRibbonSetEvent4, IRestrictVersion, IRandomCorrelation
{
public PCD() : this(new byte[Size]) { }
private readonly Memory<byte> _raw = raw;
public const int Size = 0x358; // 856
public override byte Generation => 4;
@ -35,26 +36,22 @@ public override byte Ball
set => Gift.Ball = value;
}
public override byte[] Write()
public override ReadOnlySpan<byte> Write()
{
// Ensure PGT content is encrypted
var clone = new PCD((byte[])Data.Clone());
if (clone.Gift.VerifyPKEncryption())
clone.Gift = clone.Gift;
var clone = new PCD(Data.ToArray());
clone.Gift.VerifyPKEncryption();
return clone.Data;
}
public PGT Gift
{
get => _gift ??= new PGT(Data[..PGT.Size]);
set => (_gift = value).Data.CopyTo(Data, 0);
}
public PGT Gift => _gift ??= new PGT(_raw[..PGT.Size]);
private PGT? _gift;
public GiftType4 GiftType => Gift.GiftType;
public Span<byte> GetMetadata() => Data.AsSpan(PGT.Size);
public void SetMetadata(ReadOnlySpan<byte> data) => data.CopyTo(Data.AsSpan(PGT.Size));
public Span<byte> GetMetadata() => Data[PGT.Size..];
public void SetMetadata(ReadOnlySpan<byte> data) => data.CopyTo(Data[PGT.Size..]);
public override bool GiftUsed { get => Gift.GiftUsed; set => Gift.GiftUsed = value; }
public override bool IsEntity { get => Gift.IsEntity; set => Gift.IsEntity = value; }
@ -65,13 +62,13 @@ public PGT Gift
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x150));
set => WriteUInt16LittleEndian(Data.AsSpan(0x150), (ushort)value);
get => ReadUInt16LittleEndian(Data[0x150..0x152]);
set => WriteUInt16LittleEndian(Data[0x150..0x152], (ushort)value);
}
private const int TitleLength = 0x48;
private Span<byte> CardTitleSpan => Data.AsSpan(0x104, TitleLength);
private Span<byte> CardTitleSpan => Data.Slice(0x104, TitleLength);
public override string CardTitle
{
@ -79,7 +76,7 @@ public override string CardTitle
set => StringConverter4.SetString(CardTitleSpan, value, TitleLength / 2, 0, StringConverterOption.ClearFF);
}
public ushort CardCompatibility => ReadUInt16LittleEndian(Data.AsSpan(0x14C)); // rest of bytes we don't really care about
public ushort CardCompatibility => ReadUInt16LittleEndian(Data[0x14C..0x14E]); // rest of bytes we don't really care about
public override ushort Species { get => Gift.IsManaphyEgg ? (ushort)490 : Gift.Species; set => Gift.Species = value; }
public override Moveset Moves { get => Gift.Moves; set => Gift.Moves = value; }

View File

@ -6,10 +6,12 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 5 Mystery Gift Template File
/// </summary>
public sealed class PGF(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, ILangNick,
public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick,
IContestStats, INature, IMetLevel, IRestrictVersion
{
public PGF() : this(new byte[Size]) { }
public PGF(Memory<byte> raw) : base(raw) { }
public int RestrictLanguage { get; set; } // None
public byte RestrictVersion { get; set; } // Permit All
@ -29,12 +31,12 @@ public sealed class PGF(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3,
public override bool FatefulEncounter => true;
public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); }
public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); }
public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); }
public override uint ID32 { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
public override ushort TID16 { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public override ushort SID16 { get => ReadUInt16LittleEndian(Data[0x02..]); set => WriteUInt16LittleEndian(Data[0x02..], value); }
public byte OriginGame { get => Data[0x04]; set => Data[0x04] = value; }
// Unused 0x05 0x06, 0x07
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); }
public uint PID { get => ReadUInt32LittleEndian(Data[0x08..]); set => WriteUInt32LittleEndian(Data[0x08..], value); }
private byte RIB0 { get => Data[0x0C]; set => Data[0x0C] = value; }
private byte RIB1 { get => Data[0x0D]; set => Data[0x0D] = value; }
@ -56,27 +58,27 @@ public sealed class PGF(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3,
public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)((RIB1 & ~(1 << 7)) | (value ? 1 << 7 : 0)); }
public override byte Ball { get => Data[0x0E]; set => Data[0x0E] = value; }
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x1A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), value); }
public override int HeldItem { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], (ushort)value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x14..]); set => WriteUInt16LittleEndian(Data[0x14..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x16..]); set => WriteUInt16LittleEndian(Data[0x16..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x18..]); set => WriteUInt16LittleEndian(Data[0x18..], value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data[0x1A..]); set => WriteUInt16LittleEndian(Data[0x1A..], value); }
public override byte Form { get => Data[0x1C]; set => Data[0x1C] = value; }
public int Language { get => Data[0x1D]; set => Data[0x1D] = (byte)value; }
public string Nickname
{
get => StringConverter5.GetString(Data.AsSpan(0x1E, 11 * 2));
set => StringConverter5.SetString(Data.AsSpan(0x1E, 11 * 2), value, 11, Language, StringConverterOption.ClearFF);
get => StringConverter5.GetString(Data.Slice(0x1E, 11 * 2));
set => StringConverter5.SetString(Data.Slice(0x1E, 11 * 2), value, 11, Language, StringConverterOption.ClearFF);
}
public Nature Nature { get => (Nature)Data[0x34]; set => Data[0x34] = (byte)value; }
public override byte Gender { get => Data[0x35]; set => Data[0x35] = value; }
public override int AbilityType { get => Data[0x36]; set => Data[0x36] = (byte)value; }
public int PIDType { get => Data[0x37]; set => Data[0x37] = (byte)value; }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x38)); set => WriteUInt16LittleEndian(Data.AsSpan(0x38), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x3A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3A), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x38..]); set => WriteUInt16LittleEndian(Data[0x38..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[0x3A..]); set => WriteUInt16LittleEndian(Data[0x3A..], value); }
public byte MetLevel { get => Data[0x3C]; set => Data[0x3C] = value; }
public byte ContestCool { get => Data[0x3D]; set => Data[0x3D] = value; }
public byte ContestBeauty { get => Data[0x3E]; set => Data[0x3E] = value; }
@ -93,8 +95,8 @@ public string Nickname
// Unused 0x49
public override string OriginalTrainerName
{
get => StringConverter5.GetString(Data.AsSpan(0x4A, 8 * 2));
set => StringConverter5.SetString(Data.AsSpan(0x4A, 8 * 2), value, 8, Language, StringConverterOption.ClearFF);
get => StringConverter5.GetString(Data.Slice(0x4A, 8 * 2));
set => StringConverter5.SetString(Data.Slice(0x4A, 8 * 2), value, 8, Language, StringConverterOption.ClearFF);
}
public byte OTGender { get => Data[0x5A]; set => Data[0x5A] = value; }
@ -103,14 +105,14 @@ public override string OriginalTrainerName
// Unused 0x5D 0x5E 0x5F
public override string CardTitle
{
get => StringConverter5.GetString(Data.AsSpan(0x60, 37 * 2));
set => StringConverter5.SetString(Data.AsSpan(0x60, 37 * 2), value, 36, Language, StringConverterOption.ClearZero);
get => StringConverter5.GetString(Data.Slice(0x60, 37 * 2));
set => StringConverter5.SetString(Data.Slice(0x60, 37 * 2), value, 36, Language, StringConverterOption.ClearZero);
}
// Card Attributes
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); }
public override int ItemID { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, (ushort)value); }
private ushort Year { get => ReadUInt16LittleEndian(Data.AsSpan(0xAE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xAE), value); }
private ushort Year { get => ReadUInt16LittleEndian(Data[0xAE..]); set => WriteUInt16LittleEndian(Data[0xAE..], value); }
private byte Month { get => Data[0xAD]; set => Data[0xAD] = value; }
private byte Day { get => Data[0xAC]; set => Data[0xAC] = value; }
@ -149,8 +151,8 @@ public override string CardTitle
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(0xB0));
set => WriteUInt16LittleEndian(Data.AsSpan(0xB0), (ushort)value);
get => ReadUInt16LittleEndian(Data[0xB0..]);
set => WriteUInt16LittleEndian(Data[0xB0..], (ushort)value);
}
public int CardLocation { get => Data[0xB2]; set => Data[0xB2] = (byte)value; }

View File

@ -8,9 +8,10 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 4 Mystery Gift Template File (Inner Gift Data, no card data)
/// </summary>
public sealed class PGT(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, IRandomCorrelation
public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, IRandomCorrelation
{
public PGT() : this(new byte[Size]) { }
public PGT(Memory<byte> raw) : base(raw) { }
public const int Size = 0x104; // 260
public override byte Generation => 4;
@ -37,16 +38,16 @@ public override byte Ball
public override bool GiftUsed { get => false; set { } }
public override Shiny Shiny => IsEgg ? Shiny.Random : PK.PID == 1 ? Shiny.Never : IsShiny ? Shiny.Always : Shiny.Never;
public ushort CardType { get => ReadUInt16LittleEndian(Data.AsSpan(0x0)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0), value); }
public ushort CardType { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public byte Slot { get => Data[2]; set => Data[2] = value; }
public byte Detail { get => Data[3]; set => Data[3] = value; }
public override int ItemID { get => ReadInt32LittleEndian(Data.AsSpan(0x4)); set => WriteInt32LittleEndian(Data.AsSpan(0x4), value); }
public int ItemSubID { get => ReadInt32LittleEndian(Data.AsSpan(0x8)); set => WriteInt32LittleEndian(Data.AsSpan(0x8), value); }
public override int ItemID { get => ReadInt32LittleEndian(Data[0x4..]); set => WriteInt32LittleEndian(Data[0x4..], value); }
public int ItemSubID { get => ReadInt32LittleEndian(Data[0x8..]); set => WriteInt32LittleEndian(Data[0x8..], value); }
public int PokewalkerCourseID { get => Data[0x4]; set => Data[0x4] = (byte)value; }
public PK4 PK
{
get => _pk ??= new PK4(Data.AsSpan(8, PokeCrypto.SIZE_4PARTY).ToArray());
get => _pk ??= new PK4(Data.Slice(8, PokeCrypto.SIZE_4PARTY).ToArray());
set
{
_pk = value;
@ -54,14 +55,14 @@ public PK4 PK
bool zero = Array.TrueForAll(data, static z => z == 0); // all zero
if (!zero)
data = PokeCrypto.EncryptArray45(data);
data.CopyTo(Data, 8);
data.CopyTo(Data[8..]);
}
}
public override byte[] Write()
public override ReadOnlySpan<byte> Write()
{
// Ensure PGT content is encrypted
var clone = new PGT((byte[])Data.Clone());
var clone = new PGT(Data.ToArray());
clone.VerifyPKEncryption();
return clone.Data;
}
@ -76,7 +77,7 @@ public bool VerifyPKEncryption()
{
if (GiftType is not (Pokémon or PokémonEgg))
return false; // not encrypted
if (ReadUInt32LittleEndian(Data.AsSpan(0x64 + 8)) != 0)
if (ReadUInt32LittleEndian(Data[(0x64 + 8)..]) != 0)
return false; // already encrypted (unused PK4 field, zero)
EncryptPK();
return true;
@ -84,7 +85,7 @@ public bool VerifyPKEncryption()
private void EncryptPK()
{
var span = Data.AsSpan(8, PokeCrypto.SIZE_4PARTY);
var span = Data.Slice(8, PokeCrypto.SIZE_4PARTY);
var ekdata = PokeCrypto.EncryptArray45(span);
ekdata.CopyTo(span);
}

View File

@ -89,8 +89,8 @@ public sealed class LinkEntity6(Memory<byte> Raw) : IRibbonSetEvent3, IRibbonSet
public TrainerIDFormat TrainerIDDisplayFormat => TrainerIDFormat.SixteenBit;
public uint ID32 { get => ReadUInt32LittleEndian(Data[..]); set => WriteUInt32LittleEndian(Data[..], value); }
public ushort TID16 { get => ReadUInt16LittleEndian(Data[..]); set => WriteUInt16LittleEndian(Data[..], value); }
public uint ID32 { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
public ushort TID16 { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public ushort SID16 { get => ReadUInt16LittleEndian(Data[0x02..]); set => WriteUInt16LittleEndian(Data[0x02..], value); }
public byte OriginGame { get => Data[0x04]; set => Data[0x04] = value; }
public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data[0x08..]); set => WriteUInt32LittleEndian(Data[0x08..], value); }
@ -216,7 +216,7 @@ public Moveset Relearn
public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
{
var wc6 = new WC6();
Data.CopyTo(wc6.Data.AsSpan(0x68));
Data.CopyTo(wc6.Data[0x68..]);
return wc6.ConvertToPKM(tr, criteria);
}
}

View File

@ -7,13 +7,14 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 8 Mystery Gift Template File, same as <see cref="WC8"/> with <see cref="IGanbaru"/> fields at the end.
/// </summary>
public sealed class WA8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel,
public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDynamaxLevel,
IRibbonIndex, IMemoryOT, IRelearn, IEncounterServerDate,
ILangNicknamedTemplate, IGanbaru, IAlpha, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7,
IRibbonSetCommon8, IRibbonSetMark8
{
public WA8() : this(new byte[Size]) { }
public WA8(Memory<byte> raw) : base(raw) { }
public const int Size = 0x2C8;
@ -37,8 +38,8 @@ public enum GiftType : byte
// General Card Properties
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x8));
set => WriteUInt16LittleEndian(Data.AsSpan(0x8), (ushort)value);
get => ReadUInt16LittleEndian(Data[0x8..]);
set => WriteUInt16LittleEndian(Data[0x8..], (ushort)value);
}
public byte CardFlags { get => Data[0x0E]; set => Data[0x0E] = value; }
@ -73,10 +74,10 @@ public override int Quantity
set => SetQuantity(0, (ushort)value);
}
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x18 + (0x4 * index)));
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(0x18 + (4 * index)), item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x1A + (0x4 * index)));
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(0x1A + (4 * index)), quantity);
public int GetItem(int index) => ReadUInt16LittleEndian(Data[(0x18 + (0x4 * index))..]);
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data[(0x18 + (4 * index))..], item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data[(0x1A + (0x4 * index))..]);
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data[(0x1A + (4 * index))..], quantity);
// Pokémon Properties
public override bool IsEntity { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
@ -110,66 +111,66 @@ private uint GetShinyXor()
public override uint ID32
{
get => ReadUInt32LittleEndian(Data.AsSpan(0x18));
set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value);
get => ReadUInt32LittleEndian(Data[0x18..]);
set => WriteUInt32LittleEndian(Data[0x18..], value);
}
public override ushort TID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x18));
set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value);
get => ReadUInt16LittleEndian(Data[0x18..]);
set => WriteUInt16LittleEndian(Data[0x18..], value);
}
public override ushort SID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x1A));
set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), value);
get => ReadUInt16LittleEndian(Data[0x1A..]);
set => WriteUInt16LittleEndian(Data[0x1A..], value);
}
public int OriginGame
{
get => ReadInt32LittleEndian(Data.AsSpan(0x1C));
set => WriteInt32LittleEndian(Data.AsSpan(0x1C), value);
get => ReadInt32LittleEndian(Data[0x1C..]);
set => WriteInt32LittleEndian(Data[0x1C..], value);
}
public uint EncryptionConstant
{
get => ReadUInt32LittleEndian(Data.AsSpan(0x20));
set => WriteUInt32LittleEndian(Data.AsSpan(0x20), value);
get => ReadUInt32LittleEndian(Data[0x20..]);
set => WriteUInt32LittleEndian(Data[0x20..], value);
}
public uint PID
{
get => ReadUInt32LittleEndian(Data.AsSpan(0x24));
set => WriteUInt32LittleEndian(Data.AsSpan(0x24), value);
get => ReadUInt32LittleEndian(Data[0x24..]);
set => WriteUInt32LittleEndian(Data[0x24..], value);
}
// Nicknames, OT Names 0x30 - 0x228
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x220)); set => WriteUInt16LittleEndian(Data.AsSpan(0x220), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x222)); set => WriteUInt16LittleEndian(Data.AsSpan(0x222), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x220..]); set => WriteUInt16LittleEndian(Data[0x220..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[0x222..]); set => WriteUInt16LittleEndian(Data[0x222..], value); }
public override byte Ball
{
get => (byte)ReadUInt16LittleEndian(Data.AsSpan(0x224));
set => WriteUInt16LittleEndian(Data.AsSpan(0x224), value);
get => (byte)ReadUInt16LittleEndian(Data[0x224..]);
set => WriteUInt16LittleEndian(Data[0x224..], value);
}
public override int HeldItem
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x226));
set => WriteUInt16LittleEndian(Data.AsSpan(0x226), (ushort)value);
get => ReadUInt16LittleEndian(Data[0x226..]);
set => WriteUInt16LittleEndian(Data[0x226..], (ushort)value);
}
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x228)); set => WriteUInt16LittleEndian(Data.AsSpan(0x228), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x22A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x22A), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x22C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x22C), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x22E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x22E), value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x230)); set => WriteUInt16LittleEndian(Data.AsSpan(0x230), value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x232)); set => WriteUInt16LittleEndian(Data.AsSpan(0x232), value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x234)); set => WriteUInt16LittleEndian(Data.AsSpan(0x234), value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x236)); set => WriteUInt16LittleEndian(Data.AsSpan(0x236), value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x228..]); set => WriteUInt16LittleEndian(Data[0x228..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x22A..]); set => WriteUInt16LittleEndian(Data[0x22A..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x22C..]); set => WriteUInt16LittleEndian(Data[0x22C..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x22E..]); set => WriteUInt16LittleEndian(Data[0x22E..], value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x230..]); set => WriteUInt16LittleEndian(Data[0x230..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x232..]); set => WriteUInt16LittleEndian(Data[0x232..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0x234..]); set => WriteUInt16LittleEndian(Data[0x234..], value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0x236..]); set => WriteUInt16LittleEndian(Data[0x236..], value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x238)); set => WriteUInt16LittleEndian(Data.AsSpan(0x238), value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data[0x238..]); set => WriteUInt16LittleEndian(Data[0x238..], value); }
public override byte Form { get => Data[0x23A]; set => Data[0x23A] = value; }
public override byte Gender { get => Data[0x23B]; set => Data[0x23B] = value; }
public override byte Level { get => Data[0x23C]; set => Data[0x23C] = value; }
@ -198,7 +199,7 @@ public override int HeldItem
private const int RibbonBytesCount = 0x20;
private const byte RibbonByteNone = 0xFF; // signed -1
private Span<byte> RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount);
private Span<byte> RibbonSpan => Data.Slice(RibbonBytesOffset, RibbonBytesCount);
public bool HasMarkEncounter8
{
@ -246,7 +247,7 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex)
public byte OriginalTrainerMemoryIntensity { get => Data[0x271]; set => Data[0x271] = value; }
public byte OriginalTrainerMemory { get => Data[0x272]; set => Data[0x272] = value; }
public byte OriginalTrainerMemoryFeeling { get => Data[0x273]; set => Data[0x273] = value; }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x274)); set => WriteUInt16LittleEndian(Data.AsSpan(0x274), value); }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0x274..]); set => WriteUInt16LittleEndian(Data[0x274..], value); }
// Only derivations to WC8
public byte GV_HP { get => Data[0x276]; set => Data[0x276] = value; }
@ -293,14 +294,14 @@ public int[] EVs
}
}
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetNicknameOffset(language))) != 0;
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data[(GetNicknameOffset(language))..]) != 0;
public bool CanBeAnyLanguage()
{
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[(ofs)..]);
if (lang != 0)
return false;
}
@ -318,7 +319,7 @@ public bool CanHaveLanguage(int language)
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[(ofs)..]);
if (lang == language)
return true;
}
@ -328,7 +329,7 @@ public bool CanHaveLanguage(int language)
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
private static int GetLanguageOffset(int index) => 0x28 + (index * 0x1C) + 0x1A;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data[(GetOTOffset(language))..]) != 0;
private static int GetLanguageIndex(int language)
{
@ -376,11 +377,11 @@ public override string OriginalTrainerName
public bool IsNicknamed => false;
public int Language => 2;
private Span<byte> GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A);
private Span<byte> GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A);
public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language));
public void SetNickname(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero);
private Span<byte> GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A);
private Span<byte> GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A);
public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language));
public void SetOT(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero);

View File

@ -1,20 +1,20 @@
using System;
using static System.Buffers.Binary. BinaryPrimitives;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
/// <summary>
/// Generation 7 Mystery Gift Template File (LGP/E)
/// </summary>
public sealed class WB7(byte[] Data)
: DataMysteryGift(Data), ILangNick, IAwakened, IRelearn, IEncounterServerDate, INature, ILangNicknamedTemplate,
IMetLevel, IRestrictVersion, IRibbonSetEvent3, IRibbonSetEvent4
public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, IRelearn, IEncounterServerDate, INature, ILangNicknamedTemplate,
IMetLevel, IRestrictVersion, IRibbonSetEvent3, IRibbonSetEvent4
{
public WB7() : this(new byte[Size]) { }
public WB7(Memory<byte> raw) : base(raw) { }
public const int Size = 0x310;
private const int CardStart = 0x208;
private Span<byte> Card => Data.AsSpan(CardStart, 0x108);
private Span<byte> Card => Data.Slice(CardStart, 0x108);
public override bool FatefulEncounter => true;
@ -333,13 +333,13 @@ public int GetLanguage(int redeemLanguage)
return redeemLanguage;
}
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.Slice(GetOTOffset(language))) != 0;
private Span<byte> GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A);
private Span<byte> GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A);
public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language));
public void SetNickname(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero);
private Span<byte> GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A);
private Span<byte> GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A);
public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language));
public void SetOT(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero);
@ -589,7 +589,7 @@ public bool CanHaveLanguage(int language)
if (CanBeAnyLanguage())
return true;
return Array.IndexOf(Data, (byte)language, 0x1D8, 9) >= 0;
return Data.Slice(0x1D8, 9).Contains((byte)language);
}
public bool CanBeAnyLanguage()

View File

@ -7,13 +7,14 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 8b Mystery Gift Template File
/// </summary>
public sealed class WB8(byte[] Data) : DataMysteryGift(Data),
public sealed class WB8 : DataMysteryGift,
ILangNick, INature, IRibbonIndex, IContestStatsReadOnly, IRelearn,
ILangNicknamedTemplate, IEncounterServerDate, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7,
IRibbonSetCommon8, IRibbonSetMark8
{
public WB8() : this(new byte[Size]) { }
public WB8(Memory<byte> raw) : base(raw) { }
public const int Size = 0x2DC;
public const int CardStart = 0x0;
@ -47,8 +48,8 @@ public enum GiftType : byte
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x8));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x8), (ushort)value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x8)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x8)..], (ushort)value);
}
public byte CardFlags { get => Data[CardStart + 0x10]; set => Data[CardStart + 0x10] = value; }
@ -84,10 +85,10 @@ public override int Quantity
set => SetQuantity(0, (ushort)value);
}
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (0x10 * index)));
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (0x10 * index)), item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (0x10 * index)));
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (0x10 * index)), quantity);
public int GetItem(int index) => ReadUInt16LittleEndian(Data[(CardStart + 0x20 + (0x10 * index))..]);
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data[(CardStart + 0x20 + (0x10 * index))..], item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data[(CardStart + 0x22 + (0x10 * index))..]);
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data[(CardStart + 0x22 + (0x10 * index))..], quantity);
// Pokémon Properties
public override bool IsEntity { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
@ -121,66 +122,66 @@ private uint GetShinyXor()
public override uint ID32
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x20));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x20), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x20)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x20)..], value);
}
public override ushort TID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x20)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x20)..], value);
}
public override ushort SID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x22)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x22)..], value);
}
public int OriginGame
{
get => ReadInt32LittleEndian(Data.AsSpan(CardStart + 0x24));
set => WriteInt32LittleEndian(Data.AsSpan(CardStart + 0x24), value);
get => ReadInt32LittleEndian(Data[(CardStart + 0x24)..]);
set => WriteInt32LittleEndian(Data[(CardStart + 0x24)..], value);
}
public uint EncryptionConstant
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x28));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x28), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x28)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x28)..], value);
}
public uint PID
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x2C)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x2C)..], value);
}
// Nicknames, OT Names 0x30 - 0x270
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x270)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x270), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x272)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x272), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[(CardStart + 0x270)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x270)..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[(CardStart + 0x272)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x272)..], value); }
public override byte Ball
{
get => (byte)ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x274));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x274), value);
get => (byte)ReadUInt16LittleEndian(Data[(CardStart + 0x274)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x274)..], value);
}
public override int HeldItem
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x276));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x276), (ushort)value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x276)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x276)..], (ushort)value);
}
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x278)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x278), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27A), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27E)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27E), value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x280)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x280), value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x282)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x282), value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x284)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x284), value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x286)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x286), value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x278)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x278)..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x27A)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x27A)..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x27C)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x27C)..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x27E)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x27E)..], value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x280)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x280)..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x282)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x282)..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x284)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x284)..], value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x286)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x286)..], value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x288)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x288), value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data[(CardStart + 0x288)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x288)..], value); }
public override byte Form { get => Data[CardStart + 0x28A]; set => Data[CardStart + 0x28A] = value; }
public override byte Gender { get => Data[CardStart + 0x28B]; set => Data[CardStart + 0x28B] = value; }
public override byte Level { get => Data[CardStart + 0x28C]; set => Data[CardStart + 0x28C] = value; }
@ -199,7 +200,7 @@ public override int HeldItem
private const int RibbonBytesCount = 0x20;
private const byte RibbonByteNone = 0xFF; // signed -1
private Span<byte> RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount);
private Span<byte> RibbonSpan => Data.Slice(RibbonBytesOffset, RibbonBytesCount);
public bool HasMarkEncounter8
{
@ -287,14 +288,14 @@ public int[] EVs
}
}
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetNicknameOffset(language))) != 0;
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data[GetNicknameOffset(language)..]) != 0;
public bool CanBeAnyLanguage()
{
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[ofs..]);
if (lang != 0)
return false;
}
@ -312,7 +313,7 @@ public bool CanHaveLanguage(int language)
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[ofs..]);
if (lang == language)
return true;
}
@ -322,7 +323,7 @@ public bool CanHaveLanguage(int language)
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
private static int GetLanguageOffset(int index) => 0x30 + (index * 0x20) + 0x1A;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data[GetOTOffset(language)..]) != 0;
private static int GetLanguageIndex(int language)
{
@ -370,11 +371,11 @@ public override string OriginalTrainerName
public bool IsNicknamed => false;
public int Language => 2;
private Span<byte> GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A);
private Span<byte> GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A);
public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language));
public void SetNickname(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero);
private Span<byte> GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A);
private Span<byte> GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A);
public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language));
public void SetOT(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero);

View File

@ -6,15 +6,16 @@ namespace PKHeX.Core;
public sealed class WC5Full
{
public const int Size = 0x2D0;
public readonly byte[] Data;
public readonly PGF Gift;
private Span<byte> Metadata => Data.AsSpan(PGF.Size);
public readonly Memory<byte> Raw;
public Span<byte> Data => Raw.Span;
private Span<byte> Metadata => Data[PGF.Size..];
public WC5Full(byte[] data)
public WC5Full(Memory<byte> raw)
{
Data = data;
var wc5 = data.AsSpan(0, PGF.Size).ToArray();
Raw = raw[..Size];
var wc5 = raw[..PGF.Size];
Gift = new PGF(wc5)
{
Date = EncounterDate.GetDateNDS(),

View File

@ -6,10 +6,11 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 6 Mystery Gift Template File
/// </summary>
public sealed class WC6(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4,
public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4,
ILangNick, IContestStats, INature, IMemoryOT, IRelearn, IRestrictVersion
{
public WC6() : this(new byte[Size]) { }
public WC6(Memory<byte> raw) : base(raw) { }
public const int Size = 0x108;
public const uint EonTicketConst = 0x225D73C2;
@ -35,21 +36,21 @@ public bool CanBeReceivedByVersion(GameVersion version)
// General Card Properties
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(0));
set => WriteUInt16LittleEndian(Data.AsSpan(0), (ushort)value);
get => ReadUInt16LittleEndian(Data);
set => WriteUInt16LittleEndian(Data, (ushort)value);
}
public override string CardTitle
{
// Max len 36 char, followed by null terminator
get => StringConverter6.GetString(Data.AsSpan(2, 0x4A));
set => StringConverter6.SetString(Data.AsSpan(2, 0x4A), value, 36, Language, StringConverterOption.ClearZero);
get => StringConverter6.GetString(Data.Slice(2, 0x4A));
set => StringConverter6.SetString(Data.Slice(2, 0x4A), value, 36, Language, StringConverterOption.ClearZero);
}
internal uint RawDate
{
get => ReadUInt32LittleEndian(Data.AsSpan(0x4C));
set => WriteUInt32LittleEndian(Data.AsSpan(0x4C), value);
get => ReadUInt32LittleEndian(Data[0x4C..]);
set => WriteUInt32LittleEndian(Data[0x4C..], value);
}
private uint Year
@ -115,12 +116,12 @@ private uint Day
public override bool IsItem { get => CardType == 1; set { if (value) CardType = 1; } }
public override int ItemID {
get => ReadUInt16LittleEndian(Data.AsSpan(0x68));
set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); }
get => ReadUInt16LittleEndian(Data[0x68..]);
set => WriteUInt16LittleEndian(Data[0x68..], (ushort)value); }
public override int Quantity {
get => ReadUInt16LittleEndian(Data.AsSpan(0x70));
set => WriteUInt16LittleEndian(Data.AsSpan(0x70), (ushort)value); }
get => ReadUInt16LittleEndian(Data[0x70..]);
set => WriteUInt16LittleEndian(Data[0x70..], (ushort)value); }
// Pokémon Properties
public override bool IsEntity { get => CardType == 0; set { if (value) CardType = 0; } }
@ -150,35 +151,35 @@ private uint GetShinyXor()
return (xor >> 16) ^ (xor & 0xFFFF);
}
public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x68)); set => WriteUInt32LittleEndian(Data.AsSpan(0x68), value); }
public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), value); }
public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x6A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), value); }
public override uint ID32 { get => ReadUInt32LittleEndian(Data[0x68..]); set => WriteUInt32LittleEndian(Data[0x68..], value); }
public override ushort TID16 { get => ReadUInt16LittleEndian(Data[0x68..]); set => WriteUInt16LittleEndian(Data[0x68..], value); }
public override ushort SID16 { get => ReadUInt16LittleEndian(Data[0x6A..]); set => WriteUInt16LittleEndian(Data[0x6A..], value); }
public byte OriginGame { get => Data[0x6C]; set => Data[0x6C] = value; }
public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x70)); set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value); }
public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data[0x70..]); set => WriteUInt32LittleEndian(Data[0x70..], value); }
public override byte Ball { get => Data[0x76]; set => Data[0x76] = value; }
public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x78)); set => WriteUInt16LittleEndian(Data.AsSpan(0x78), (ushort)value); }
public override int HeldItem { get => ReadUInt16LittleEndian(Data[0x78..]); set => WriteUInt16LittleEndian(Data[0x78..], (ushort)value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7C), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x7A..]); set => WriteUInt16LittleEndian(Data[0x7A..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x7C..]); set => WriteUInt16LittleEndian(Data[0x7C..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x7E..]); set => WriteUInt16LittleEndian(Data[0x7E..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x80..]); set => WriteUInt16LittleEndian(Data[0x80..], value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x82)); set => WriteUInt16LittleEndian(Data.AsSpan(0x82), value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data[0x82..]); set => WriteUInt16LittleEndian(Data[0x82..], value); }
public override byte Form { get => Data[0x84]; set => Data[0x84] = value; }
public int Language { get => Data[0x85]; set => Data[0x85] = (byte)value; }
public string Nickname
{
get => StringConverter6.GetString(Data.AsSpan(0x86, 0x1A));
set => StringConverter6.SetString(Data.AsSpan(0x86, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
get => StringConverter6.GetString(Data.Slice(0x86, 0x1A));
set => StringConverter6.SetString(Data.Slice(0x86, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
}
public Nature Nature { get => (Nature)Data[0xA0]; set => Data[0xA0] = (byte)value; }
public override byte Gender { get => Data[0xA1]; set => Data[0xA1] = value; }
public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; }
public ShinyType6 PIDType { get => (ShinyType6)Data[0xA3]; set => Data[0xA3] = (byte)value; }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0xA4..]); set => WriteUInt16LittleEndian(Data[0xA4..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[0xA6..]); set => WriteUInt16LittleEndian(Data[0xA6..], value); }
public byte ContestCool { get => Data[0xA9]; set => Data[0xA9] = value; }
public byte ContestBeauty { get => Data[0xAA]; set => Data[0xAA] = value; }
@ -198,24 +199,24 @@ public string Nickname
public override string OriginalTrainerName
{
get => StringConverter6.GetString(Data.AsSpan(0xB6, 0x1A));
set => StringConverter6.SetString(Data.AsSpan(0xB6, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
get => StringConverter6.GetString(Data.Slice(0xB6, 0x1A));
set => StringConverter6.SetString(Data.Slice(0xB6, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
}
public bool IsOriginalTrainerNameSet => Data[0xB6] != 0 || Data[0xB7] != 0;
public override byte Level { get => Data[0xD0]; set => Data[0xD0] = value; }
public override bool IsEgg { get => Data[0xD1] == 1; set => Data[0xD1] = value ? (byte)1 : (byte)0; }
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0xD4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xD4), value); }
public uint PID { get => ReadUInt32LittleEndian(Data[0xD4..]); set => WriteUInt32LittleEndian(Data[0xD4..], value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDE), value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0xD8..]); set => WriteUInt16LittleEndian(Data[0xD8..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0xDA..]); set => WriteUInt16LittleEndian(Data[0xDA..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0xDC..]); set => WriteUInt16LittleEndian(Data[0xDC..], value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0xDE..]); set => WriteUInt16LittleEndian(Data[0xDE..], value); }
public byte OriginalTrainerMemoryIntensity { get => Data[0xE0]; set => Data[0xE0] = value; }
public byte OriginalTrainerMemory { get => Data[0xE1]; set => Data[0xE1] = value; }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), value); }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0xE2..]); set => WriteUInt16LittleEndian(Data[0xE2..], value); }
public byte OriginalTrainerMemoryFeeling { get => Data[0xE4]; set => Data[0xE4] = value; }
public int EV_HP { get => Data[0xE5]; set => Data[0xE5] = (byte)value; }

View File

@ -6,25 +6,29 @@ public sealed class WC6Full
{
public const int Size = 0x310;
private const int GiftStart = Size - WC6.Size;
public readonly byte[] Data;
public readonly WC6 Gift;
public readonly Memory<byte> Raw;
public Span<byte> Data => Raw.Span;
public byte RestrictVersion { get => Data[0]; set => Data[0] = value; }
public byte RestrictLanguage { get => Data[0x1FF]; set => Data[0x1FF] = value; }
public WC6Full(byte[] data)
public WC6Full(Memory<byte> raw)
{
Data = data;
var wc6 = data.AsSpan(GiftStart).ToArray();
Raw = raw[..Size];
var wc6 = raw[GiftStart..];
Gift = new WC6(wc6);
var now = EncounterDate.GetDate3DS();
Gift.RawDate = WC6.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
Gift.RawDate = GetDate(now);
Gift.RestrictVersion = RestrictVersion;
Gift.RestrictLanguage = RestrictLanguage;
}
public static WC6[] GetArray(ReadOnlySpan<byte> WC6Full, ReadOnlySpan<byte> data)
private static uint GetDate(DateOnly date) => WC6.SetDate((uint)date.Year, (uint)date.Month, (uint)date.Day);
public static WC6[] GetArray(Memory<byte> WC6Full, Memory<byte> data)
{
var countfull = WC6Full.Length / Size;
var countgift = data.Length / WC6.Size;
@ -39,20 +43,21 @@ public static WC6[] GetArray(ReadOnlySpan<byte> WC6Full, ReadOnlySpan<byte> data
return result;
}
private static WC6 ReadWC6(ReadOnlySpan<byte> data, int ofs, DateOnly date)
private static WC6 ReadWC6(Memory<byte> data, int ofs, DateOnly date)
{
var slice = data.Slice(ofs + GiftStart, WC6.Size).ToArray();
var slice = data.Slice(ofs + GiftStart, WC6.Size);
var span = data.Span[ofs..];
return new WC6(slice)
{
RestrictVersion = data[ofs],
RestrictLanguage = data[ofs + 0x1FF],
RawDate = WC6.SetDate((uint)date.Year, (uint)date.Month, (uint)date.Day),
RestrictVersion = span[0],
RestrictLanguage = span[0x1FF],
RawDate = GetDate(date),
};
}
private static WC6 ReadWC6Only(ReadOnlySpan<byte> data, int ofs)
private static WC6 ReadWC6Only(Memory<byte> data, int ofs)
{
var slice = data.Slice(ofs, WC6.Size).ToArray();
var slice = data.Slice(ofs, WC6.Size);
return new WC6(slice);
}
}

View File

@ -6,10 +6,11 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 7 Mystery Gift Template File
/// </summary>
public sealed class WC7(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, ILangNick,
public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick,
IContestStats, INature, IMemoryOT, IRelearn, IMetLevel, IRestrictVersion
{
public WC7() : this(new byte[Size]) { }
public WC7(Memory<byte> raw) : base(raw) { }
public const int Size = 0x108;
public override byte Generation => 7;
@ -35,21 +36,21 @@ public bool CanBeReceivedByVersion(GameVersion version)
// General Card Properties
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(0));
set => WriteUInt16LittleEndian(Data.AsSpan(0), (ushort)value);
get => ReadUInt16LittleEndian(Data);
set => WriteUInt16LittleEndian(Data, (ushort)value);
}
public override string CardTitle
{
// Max len 36 char, followed by null terminator
get => StringConverter7.GetString(Data.AsSpan(2, 0x4A));
set => StringConverter7.SetString(Data.AsSpan(2, 0x4A), value, 36, Language, StringConverterOption.ClearZero);
get => StringConverter7.GetString(Data.Slice(2, 0x4A));
set => StringConverter7.SetString(Data.Slice(2, 0x4A), value, 36, Language, StringConverterOption.ClearZero);
}
internal uint RawDate
{
get => ReadUInt32LittleEndian(Data.AsSpan(0x4C));
set => WriteUInt32LittleEndian(Data.AsSpan(0x4C), value);
get => ReadUInt32LittleEndian(Data[0x4C..]);
set => WriteUInt32LittleEndian(Data[0x4C..], value);
}
private uint Year
@ -126,16 +127,16 @@ private uint Day
// Item Properties
public override bool IsItem { get => CardType == 1; set { if (value) CardType = 1; } }
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); }
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x68 + (0x4 * index)));
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(0x68 + (4 * index)), item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x6A + (0x4 * index)));
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(0x6A + (4 * index)), quantity);
public override int ItemID { get => ReadUInt16LittleEndian(Data[0x68..]); set => WriteUInt16LittleEndian(Data[0x68..], (ushort)value); }
public int GetItem(int index) => ReadUInt16LittleEndian(Data[(0x68 + (0x4 * index))..]);
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data[(0x68 + (4 * index))..], item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data[(0x6A + (0x4 * index))..]);
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data[(0x6A + (4 * index))..], quantity);
public override int Quantity
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value);
get => ReadUInt16LittleEndian(Data[0x6A..]);
set => WriteUInt16LittleEndian(Data[0x6A..], (ushort)value);
}
// Pokémon Properties
@ -168,20 +169,20 @@ private uint GetShinyXor()
public override uint ID32
{
get => ReadUInt32LittleEndian(Data.AsSpan(0x68));
set => WriteUInt32LittleEndian(Data.AsSpan(0x68), value);
get => ReadUInt32LittleEndian(Data[0x68..]);
set => WriteUInt32LittleEndian(Data[0x68..], value);
}
public override ushort TID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x68));
set => WriteUInt16LittleEndian(Data.AsSpan(0x68), value);
get => ReadUInt16LittleEndian(Data[0x68..]);
set => WriteUInt16LittleEndian(Data[0x68..], value);
}
public override ushort SID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x6A));
set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), value);
get => ReadUInt16LittleEndian(Data[0x6A..]);
set => WriteUInt16LittleEndian(Data[0x6A..], value);
}
public byte OriginGame
@ -191,8 +192,8 @@ public byte OriginGame
}
public uint EncryptionConstant {
get => ReadUInt32LittleEndian(Data.AsSpan(0x70));
set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value);
get => ReadUInt32LittleEndian(Data[0x70..]);
set => WriteUInt32LittleEndian(Data[0x70..], value);
}
public override byte Ball
@ -202,30 +203,30 @@ public override byte Ball
public override int HeldItem
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x78));
set => WriteUInt16LittleEndian(Data.AsSpan(0x78), (ushort)value);
get => ReadUInt16LittleEndian(Data[0x78..]);
set => WriteUInt16LittleEndian(Data[0x78..], (ushort)value);
}
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7C), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x82)); set => WriteUInt16LittleEndian(Data.AsSpan(0x82), value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x7A..]); set => WriteUInt16LittleEndian(Data[0x7A..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x7C..]); set => WriteUInt16LittleEndian(Data[0x7C..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x7E..]); set => WriteUInt16LittleEndian(Data[0x7E..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x80..]); set => WriteUInt16LittleEndian(Data[0x80..], value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data[0x82..]); set => WriteUInt16LittleEndian(Data[0x82..], value); }
public override byte Form { get => Data[0x84]; set => Data[0x84] = value; }
public int Language { get => Data[0x85]; set => Data[0x85] = (byte)value; }
public string Nickname
{
get => StringConverter7.GetString(Data.AsSpan(0x86, 0x1A));
set => StringConverter7.SetString(Data.AsSpan(0x86, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
get => StringConverter7.GetString(Data.Slice(0x86, 0x1A));
set => StringConverter7.SetString(Data.Slice(0x86, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
}
public Nature Nature { get => (Nature)Data[0xA0]; set => Data[0xA0] = (byte)value; }
public override byte Gender { get => Data[0xA1]; set => Data[0xA1] = value; }
public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; }
public ShinyType6 PIDType { get => (ShinyType6)Data[0xA3]; set => Data[0xA3] = (byte)value; }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0xA4..]); set => WriteUInt16LittleEndian(Data[0xA4..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[0xA6..]); set => WriteUInt16LittleEndian(Data[0xA6..], value); }
public byte MetLevel { get => Data[0xA8]; set => Data[0xA8] = value; }
public byte ContestCool { get => Data[0xA9]; set => Data[0xA9] = value; }
@ -246,25 +247,25 @@ public string Nickname
public override string OriginalTrainerName
{
get => StringConverter7.GetString(Data.AsSpan(0xB6, 0x1A));
set => StringConverter7.SetString(Data.AsSpan(0xB6, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
get => StringConverter7.GetString(Data.Slice(0xB6, 0x1A));
set => StringConverter7.SetString(Data.Slice(0xB6, 0x1A), value, 12, Language, StringConverterOption.ClearZero);
}
public bool IsOriginalTrainerNameSet => Data[0xB6] != 0 || Data[0xB7] != 0;
public override byte Level { get => Data[0xD0]; set => Data[0xD0] = value; }
public override bool IsEgg { get => Data[0xD1] == 1; set => Data[0xD1] = value ? (byte)1 : (byte)0; }
public ushort AdditionalItem { get => ReadUInt16LittleEndian(Data.AsSpan(0xD2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD2), value); }
public ushort AdditionalItem { get => ReadUInt16LittleEndian(Data[0xD2..]); set => WriteUInt16LittleEndian(Data[0xD2..], value); }
public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0xD4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xD4), value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDE), value); }
public uint PID { get => ReadUInt32LittleEndian(Data[0xD4..]); set => WriteUInt32LittleEndian(Data[0xD4..], value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0xD8..]); set => WriteUInt16LittleEndian(Data[0xD8..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0xDA..]); set => WriteUInt16LittleEndian(Data[0xDA..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0xDC..]); set => WriteUInt16LittleEndian(Data[0xDC..], value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0xDE..]); set => WriteUInt16LittleEndian(Data[0xDE..], value); }
public byte OriginalTrainerMemoryIntensity { get => Data[0xE0]; set => Data[0xE0] = value; }
public byte OriginalTrainerMemory { get => Data[0xE1]; set => Data[0xE1] = value; }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), value); }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0xE2..]); set => WriteUInt16LittleEndian(Data[0xE2..], value); }
public byte OriginalTrainerMemoryFeeling { get => Data[0xE4]; set => Data[0xE4] = value; }
public int EV_HP { get => Data[0xE5]; set => Data[0xE5] = (byte)value; }

View File

@ -6,25 +6,29 @@ public sealed class WC7Full
{
public const int Size = 0x310;
private const int GiftStart = Size - WC7.Size;
public readonly byte[] Data;
public readonly WC7 Gift;
public readonly Memory<byte> Raw;
public Span<byte> Data => Raw.Span;
public byte RestrictVersion { get => Data[0]; set => Data[0] = value; }
public byte RestrictLanguage { get => Data[0x1FF]; set => Data[0x1FF] = value; }
public WC7Full(byte[] data)
public WC7Full(Memory<byte> raw)
{
Data = data;
var wc7 = data.AsSpan(GiftStart).ToArray();
Raw = raw[..Size];
var wc7 = raw[GiftStart..];
Gift = new WC7(wc7);
var now = EncounterDate.GetDate3DS();
Gift.RawDate = WC7.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
Gift.RawDate = GetDate(now);
Gift.RestrictVersion = RestrictVersion;
Gift.RestrictLanguage = RestrictLanguage;
}
public static WC7[] GetArray(ReadOnlySpan<byte> wc7Full, ReadOnlySpan<byte> data)
private static uint GetDate(DateOnly date) => WC7.SetDate((uint)date.Year, (uint)date.Month, (uint)date.Day);
public static WC7[] GetArray(Memory<byte> wc7Full, Memory<byte> data)
{
var countfull = wc7Full.Length / Size;
var countgift = data.Length / WC7.Size;
@ -39,20 +43,21 @@ public static WC7[] GetArray(ReadOnlySpan<byte> wc7Full, ReadOnlySpan<byte> data
return result;
}
private static WC7 ReadWC7(ReadOnlySpan<byte> data, int ofs, DateOnly date)
private static WC7 ReadWC7(Memory<byte> data, int ofs, DateOnly date)
{
var slice = data.Slice(ofs + GiftStart, WC7.Size).ToArray();
var slice = data.Slice(ofs + GiftStart, WC7.Size);
var span = data.Span[ofs..];
return new WC7(slice)
{
RestrictVersion = data[ofs],
RestrictLanguage = data[ofs + 0x1FF],
RawDate = WC7.SetDate((uint) date.Year, (uint) date.Month, (uint) date.Day),
RestrictVersion = span[0],
RestrictLanguage = span[0x1FF],
RawDate = GetDate(date),
};
}
private static WC7 ReadWC7Only(ReadOnlySpan<byte> data, int ofs)
private static WC7 ReadWC7Only(Memory<byte> data, int ofs)
{
var slice = data.Slice(ofs, WC7.Size).ToArray();
var slice = data.Slice(ofs, WC7.Size);
return new WC7(slice);
}
}

View File

@ -7,11 +7,12 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 8 Mystery Gift Template File
/// </summary>
public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel, IRibbonIndex, IMemoryOT,
public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDynamaxLevel, IRibbonIndex, IMemoryOT,
ILangNicknamedTemplate, IRelearn, IEncounterServerDate, IRestrictVersion, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, ITrashUnderlaySpecies
{
public WC8() : this(new byte[Size]) { }
public WC8(Memory<byte> raw) : base(raw) { }
public const int Size = 0x2D0;
public const int CardStart = 0x0;
@ -43,8 +44,8 @@ public enum GiftType : byte
// General Card Properties
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x8));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x8), (ushort)value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x8)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x8)..], (ushort)value);
}
public byte CardFlags { get => Data[CardStart + 0x10]; set => Data[CardStart + 0x10] = value; }
@ -79,10 +80,10 @@ public override int Quantity
set => SetQuantity(0, (ushort)value);
}
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (0x4 * index)));
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20 + (4 * index)), item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (0x4 * index)));
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22 + (4 * index)), quantity);
public int GetItem(int index) => ReadUInt16LittleEndian(Data[(CardStart + 0x20 + (0x4 * index))..]);
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data[(CardStart + 0x20 + (4 * index))..], item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data[(CardStart + 0x22 + (0x4 * index))..]);
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data[(CardStart + 0x22 + (4 * index))..], quantity);
// Pokémon Properties
public override bool IsEntity { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
@ -118,66 +119,66 @@ private uint GetShinyXor()
public override uint ID32
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x20));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x20), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x20)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x20)..], value);
}
public override ushort TID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x20)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x20)..], value);
}
public override ushort SID16
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x22)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x22)..], value);
}
public int OriginGame
{
get => ReadInt32LittleEndian(Data.AsSpan(CardStart + 0x24));
set => WriteInt32LittleEndian(Data.AsSpan(CardStart + 0x24), value);
get => ReadInt32LittleEndian(Data[(CardStart + 0x24)..]);
set => WriteInt32LittleEndian(Data[(CardStart + 0x24)..], value);
}
public uint EncryptionConstant
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x28));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x28), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x28)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x28)..], value);
}
public uint PID
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x2C), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x2C)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x2C)..], value);
}
// Nicknames, OT Names 0x30 - 0x228
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x228)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x228), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[(CardStart + 0x228)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x228)..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[(CardStart + 0x22A)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x22A)..], value); }
public override byte Ball
{
get => (byte)ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C), value);
get => (byte)ReadUInt16LittleEndian(Data[(CardStart + 0x22C)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x22C)..], value);
}
public override int HeldItem
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22E));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22E), (ushort)value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x22E)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x22E)..], (ushort)value);
}
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x230)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x230), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x232)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x232), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x234)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x234), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x236)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x236), value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x238)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x238), value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x23A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x23A), value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x23C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x23C), value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x23E)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x23E), value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x230)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x230)..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x232)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x232)..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x234)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x234)..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x236)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x236)..], value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x238)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x238)..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x23A)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x23A)..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x23C)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x23C)..], value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x23E)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x23E)..], value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x240)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x240), value); }
public override ushort Species { get => ReadUInt16LittleEndian(Data[(CardStart + 0x240)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x240)..], value); }
public override byte Form { get => Data[CardStart + 0x242]; set => Data[CardStart + 0x242] = value; }
public override byte Gender { get => Data[CardStart + 0x243]; set => Data[CardStart + 0x243] = value; }
public override byte Level { get => Data[CardStart + 0x244]; set => Data[CardStart + 0x244] = value; }
@ -196,7 +197,7 @@ public override int HeldItem
private const int RibbonBytesCount = 0x20;
private const byte RibbonByteNone = 0xFF; // signed -1
private Span<byte> RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount);
private Span<byte> RibbonSpan => Data.Slice(RibbonBytesOffset, RibbonBytesCount);
public bool HasMarkEncounter8
{
@ -245,9 +246,9 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex)
public byte OriginalTrainerMemoryIntensity { get => Data[CardStart + 0x279]; set => Data[CardStart + 0x279] = value; }
public byte OriginalTrainerMemory { get => Data[CardStart + 0x27A]; set => Data[CardStart + 0x27A] = value; }
public byte OriginalTrainerMemoryFeeling { get => Data[CardStart + 0x27B]; set => Data[CardStart + 0x27B] = value; }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C), value); }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[(CardStart + 0x27C)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x27C)..], value); }
public ushort Checksum => ReadUInt16LittleEndian(Data.AsSpan(0x2CC));
public ushort Checksum => ReadUInt16LittleEndian(Data[0x2CC..]);
// Meta Accessible Properties
public int[] IVs
@ -286,14 +287,14 @@ public int[] EVs
}
}
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetNicknameOffset(language))) != 0;
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data[GetNicknameOffset(language)..]) != 0;
public bool CanBeAnyLanguage()
{
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[ofs..]);
if (lang != 0)
return false;
}
@ -311,7 +312,7 @@ public bool CanHaveLanguage(int language)
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[ofs..]);
if (lang == language)
return true;
}
@ -321,7 +322,7 @@ public bool CanHaveLanguage(int language)
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
private static int GetLanguageOffset(int index) => 0x30 + (index * 0x1C) + 0x1A;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data[GetOTOffset(language)..]) != 0;
private static int GetLanguageIndex(int language)
{
@ -369,11 +370,11 @@ public override string OriginalTrainerName
public bool IsNicknamed => false;
public int Language => 2;
private Span<byte> GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A);
private Span<byte> GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A);
public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language));
public void SetNickname(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero);
private Span<byte> GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A);
private Span<byte> GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A);
public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language));
public void SetOT(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero);

View File

@ -7,12 +7,13 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 9 Mystery Gift Template File
/// </summary>
public sealed class WC9(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, ITeraType, IRibbonIndex, IMemoryOT,
public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbonIndex, IMemoryOT,
ILangNicknamedTemplate, IEncounterServerDate, IRelearn, IMetLevel,
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7,
IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetCommon9, IRibbonSetMark9, IEncounterMarkExtra
{
public WC9() : this(new byte[Size]) { }
public WC9(Memory<byte> raw) : base(raw) { }
public const int Size = 0x2C8;
public const int CardStart = 0x0;
@ -43,15 +44,15 @@ public enum GiftType : byte
// General Card Properties
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x8));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x8), (ushort)value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x8)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x8)..], (ushort)value);
}
// Added in 1.2.0; now can enforce a fixed scale if not 256.
public ushort Scale
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x0C));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x0C), value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x0C)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x0C)..], value);
}
public byte CardFlags { get => Data[CardStart + 0x10]; set => Data[CardStart + 0x10] = value; }
@ -86,10 +87,10 @@ public override int Quantity
set => SetQuantity(0, (ushort)value);
}
public int GetItem(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x18 + (0x4 * index)));
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x18 + (4 * index)), item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x1A + (0x4 * index)));
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x1A + (4 * index)), quantity);
public int GetItem(int index) => ReadUInt16LittleEndian(Data[(CardStart + 0x18 + (0x4 * index))..]);
public void SetItem(int index, ushort item) => WriteUInt16LittleEndian(Data[(CardStart + 0x18 + (4 * index))..], item);
public int GetQuantity(int index) => ReadUInt16LittleEndian(Data[(CardStart + 0x1A + (0x4 * index))..]);
public void SetQuantity(int index, ushort quantity) => WriteUInt16LittleEndian(Data[(CardStart + 0x1A + (4 * index))..], quantity);
// Pokémon Properties
public override bool IsEntity { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
@ -127,14 +128,14 @@ private uint GetShinyXor()
// Since we expose the 16bit (pk9) component values here, just adjust them accordingly with an inlined calc.
public override uint ID32
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x18));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x18), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x18)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x18)..], value);
}
public uint ID32Old
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x18)) - (1000000u * (uint)CardID);
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x18), value + (1000000u * (uint)CardID));
get => ReadUInt32LittleEndian(Data[(CardStart + 0x18)..]) - (1000000u * (uint)CardID);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x18)..], value + (1000000u * (uint)CardID));
}
public override ushort TID16
@ -151,48 +152,48 @@ public override ushort SID16
public int OriginGame
{
get => ReadInt32LittleEndian(Data.AsSpan(CardStart + 0x1C));
set => WriteInt32LittleEndian(Data.AsSpan(CardStart + 0x1C), value);
get => ReadInt32LittleEndian(Data[(CardStart + 0x1C)..]);
set => WriteInt32LittleEndian(Data[(CardStart + 0x1C)..], value);
}
public uint EncryptionConstant
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x20));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x20), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x20)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x20)..], value);
}
public uint PID
{
get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x24));
set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x24), value);
get => ReadUInt32LittleEndian(Data[(CardStart + 0x24)..]);
set => WriteUInt32LittleEndian(Data[(CardStart + 0x24)..], value);
}
// Nicknames, OT Names 0x28 - 0x220
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x220)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x220), value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x222)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x222), value); }
public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[(CardStart + 0x220)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x220)..], value); }
public override ushort Location { get => ReadUInt16LittleEndian(Data[(CardStart + 0x222)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x222)..], value); }
public override byte Ball
{
get => (byte)ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x224));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x224), value);
get => (byte)ReadUInt16LittleEndian(Data[(CardStart + 0x224)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x224)..], value);
}
public override int HeldItem
{
get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x226));
set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x226), (ushort)value);
get => ReadUInt16LittleEndian(Data[(CardStart + 0x226)..]);
set => WriteUInt16LittleEndian(Data[(CardStart + 0x226)..], (ushort)value);
}
public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x228)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x228), value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A), value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C), value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22E)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22E), value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x230)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x230), value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x232)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x232), value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x234)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x234), value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x236)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x236), value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x228)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x228)..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x22A)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x22A)..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x22C)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x22C)..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x22E)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x22E)..], value); }
public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x230)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x230)..], value); }
public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x232)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x232)..], value); }
public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x234)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x234)..], value); }
public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[(CardStart + 0x236)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x236)..], value); }
public override ushort Species { get => SpeciesConverter.GetNational9(ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x238))); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x238), SpeciesConverter.GetInternal9(value)); }
public override ushort Species { get => SpeciesConverter.GetNational9(ReadUInt16LittleEndian(Data[(CardStart + 0x238)..])); set => WriteUInt16LittleEndian(Data[(CardStart + 0x238)..], SpeciesConverter.GetInternal9(value)); }
public override byte Form { get => Data[CardStart + 0x23A]; set => Data[CardStart + 0x23A] = value; }
public override byte Gender { get => Data[CardStart + 0x23B]; set => Data[CardStart + 0x23B] = value; }
public override byte Level { get => Data[CardStart + 0x23C]; set => Data[CardStart + 0x23C] = value; }
@ -211,15 +212,15 @@ public MoveType TeraTypeOverride
}
public MoveType TeraType => TeraTypeOriginal;
public short HeightValue { get => ReadInt16LittleEndian(Data.AsSpan(CardStart + 0x244)); set => WriteInt16LittleEndian(Data.AsSpan(CardStart + 0x244), value); }
public short WeightValue { get => ReadInt16LittleEndian(Data.AsSpan(CardStart + 0x246)); set => WriteInt16LittleEndian(Data.AsSpan(CardStart + 0x246), value); }
public short HeightValue { get => ReadInt16LittleEndian(Data[(CardStart + 0x244)..]); set => WriteInt16LittleEndian(Data[(CardStart + 0x244)..], value); }
public short WeightValue { get => ReadInt16LittleEndian(Data[(CardStart + 0x246)..]); set => WriteInt16LittleEndian(Data[(CardStart + 0x246)..], value); }
// Ribbons 0x24C-0x26C
private const int RibbonBytesOffset = 0x248;
private const int RibbonBytesCount = 0x20;
private const byte RibbonByteNone = 0xFF; // signed -1
private Span<byte> RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount);
private Span<byte> RibbonSpan => Data.Slice(RibbonBytesOffset, RibbonBytesCount);
public bool HasMarkEncounter8
{
@ -278,9 +279,9 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex)
public byte OriginalTrainerMemoryIntensity { get => Data[CardStart + 0x275]; set => Data[CardStart + 0x275] = value; }
public byte OriginalTrainerMemory { get => Data[CardStart + 0x276]; set => Data[CardStart + 0x276] = value; }
public byte OriginalTrainerMemoryFeeling { get => Data[CardStart + 0x277]; set => Data[CardStart + 0x277] = value; }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x278)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x278), value); }
public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[(CardStart + 0x278)..]); set => WriteUInt16LittleEndian(Data[(CardStart + 0x278)..], value); }
public ushort Checksum => ReadUInt16LittleEndian(Data.AsSpan(0x2C4));
public ushort Checksum => ReadUInt16LittleEndian(Data[0x2C4..]);
// Meta Accessible Properties
public int[] IVs
@ -319,14 +320,14 @@ public int[] EVs
}
}
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetNicknameOffset(language))) != 0;
public bool GetIsNicknamed(int language) => ReadUInt16LittleEndian(Data[GetNicknameOffset(language)..]) != 0;
public bool CanBeAnyLanguage()
{
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[ofs..]);
if (lang != 0)
return false;
}
@ -344,7 +345,7 @@ public bool CanHaveLanguage(int language)
for (int i = 0; i < 9; i++)
{
var ofs = GetLanguageOffset(i);
var lang = ReadInt16LittleEndian(Data.AsSpan(ofs));
var lang = ReadInt16LittleEndian(Data[ofs..]);
if (lang == language)
return true;
}
@ -354,7 +355,7 @@ public bool CanHaveLanguage(int language)
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
private static int GetLanguageOffset(int index) => 0x28 + (index * 0x1C) + 0x1A;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0;
public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data[GetOTOffset(language)..]) != 0;
private static int GetLanguageIndex(int language)
{
@ -402,11 +403,11 @@ public override string OriginalTrainerName
public bool IsNicknamed => false;
public int Language => 2;
private Span<byte> GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A);
private Span<byte> GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A);
public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language));
public void SetNickname(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero);
private Span<byte> GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A);
private Span<byte> GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A);
public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language));
public void SetOT(int language, ReadOnlySpan<char> value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero);

View File

@ -10,9 +10,10 @@ namespace PKHeX.Core;
/// A full <see cref="WB7"/> is not stored in the <see cref="SAV7b"/> structure, as it is immediately converted to <see cref="PKM"/> upon receiving from server.
/// The save file just stores a summary of the received data for the user to look back at.
/// </remarks>
public sealed class WR7(byte[] Data) : DataMysteryGift(Data)
public sealed class WR7 : DataMysteryGift
{
public WR7() : this(new byte[Size]) { }
public WR7(Memory<byte> raw) : base(raw) { }
public const int Size = 0x140;
public override byte Generation => 7;
@ -25,22 +26,22 @@ public sealed class WR7(byte[] Data) : DataMysteryGift(Data)
public long Epoch
{
get => ReadInt64LittleEndian(Data.AsSpan(0x00));
set => WriteInt64LittleEndian(Data.AsSpan(0x00), value);
get => ReadInt64LittleEndian(Data);
set => WriteInt64LittleEndian(Data, value);
}
public DateOnly Date => new DateOnly(1970, 1, 1).AddDays((int)(Epoch / 86400));
public override int CardID
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x08));
set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value);
get => ReadUInt16LittleEndian(Data[0x08..]);
set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value);
}
public ushort CardType
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x0A));
set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), value);
get => ReadUInt16LittleEndian(Data[0x0A..]);
set => WriteUInt16LittleEndian(Data[0x0A..], value);
}
public WR7GiftType GiftType
@ -59,8 +60,8 @@ public int ItemCount
public override ushort Species
{
get => ReadUInt16LittleEndian(Data.AsSpan(0x10C));
set => WriteUInt16LittleEndian(Data.AsSpan(0x10C), value);
get => ReadUInt16LittleEndian(Data[0x10C..]);
set => WriteUInt16LittleEndian(Data[0x10C..], value);
}
public override bool GiftUsed { get; set; }
@ -71,18 +72,18 @@ public override ushort Species
set => Data[0x10E] = value;
}
public override int ItemID { get => ReadUInt16LittleEndian(Data.AsSpan(0x110)); set => WriteUInt16LittleEndian(Data.AsSpan(0x110), (ushort)value); }
public ushort ItemIDCount { get => ReadUInt16LittleEndian(Data.AsSpan(0x112)); set => WriteUInt16LittleEndian(Data.AsSpan(0x112), value); }
public ushort ItemSet2Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x114)); set => WriteUInt16LittleEndian(Data.AsSpan(0x114), value); }
public ushort ItemSet2Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), value); }
public ushort ItemSet3Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x118)); set => WriteUInt16LittleEndian(Data.AsSpan(0x118), value); }
public ushort ItemSet3Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x11A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x11A), value); }
public ushort ItemSet4Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x11C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x11C), value); }
public ushort ItemSet4Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x11E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x11E), value); }
public ushort ItemSet5Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), value); } // struct union overlaps OT Name data, beware!
public ushort ItemSet5Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), value); }
public ushort ItemSet6Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x124)); set => WriteUInt16LittleEndian(Data.AsSpan(0x124), value); }
public ushort ItemSet6Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x126)); set => WriteUInt16LittleEndian(Data.AsSpan(0x126), value); }
public override int ItemID { get => ReadUInt16LittleEndian(Data[0x110..]); set => WriteUInt16LittleEndian(Data[0x110..], (ushort)value); }
public ushort ItemIDCount { get => ReadUInt16LittleEndian(Data[0x112..]); set => WriteUInt16LittleEndian(Data[0x112..], value); }
public ushort ItemSet2Item { get => ReadUInt16LittleEndian(Data[0x114..]); set => WriteUInt16LittleEndian(Data[0x114..], value); }
public ushort ItemSet2Count { get => ReadUInt16LittleEndian(Data[0x116..]); set => WriteUInt16LittleEndian(Data[0x116..], value); }
public ushort ItemSet3Item { get => ReadUInt16LittleEndian(Data[0x118..]); set => WriteUInt16LittleEndian(Data[0x118..], value); }
public ushort ItemSet3Count { get => ReadUInt16LittleEndian(Data[0x11A..]); set => WriteUInt16LittleEndian(Data[0x11A..], value); }
public ushort ItemSet4Item { get => ReadUInt16LittleEndian(Data[0x11C..]); set => WriteUInt16LittleEndian(Data[0x11C..], value); }
public ushort ItemSet4Count { get => ReadUInt16LittleEndian(Data[0x11E..]); set => WriteUInt16LittleEndian(Data[0x11E..], value); }
public ushort ItemSet5Item { get => ReadUInt16LittleEndian(Data[0x120..]); set => WriteUInt16LittleEndian(Data[0x120..], value); } // struct union overlaps OT Name data, beware!
public ushort ItemSet5Count { get => ReadUInt16LittleEndian(Data[0x122..]); set => WriteUInt16LittleEndian(Data[0x122..], value); }
public ushort ItemSet6Item { get => ReadUInt16LittleEndian(Data[0x124..]); set => WriteUInt16LittleEndian(Data[0x124..], value); }
public ushort ItemSet6Count { get => ReadUInt16LittleEndian(Data[0x126..]); set => WriteUInt16LittleEndian(Data[0x126..], value); }
public override byte Gender { get; set; }
public override byte Form { get; set; }
@ -92,8 +93,8 @@ public override ushort Species
public override string OriginalTrainerName
{
get => StringConverter8.GetString(Data.AsSpan(0x120, 0x1A));
set => StringConverter8.SetString(Data.AsSpan(0x120, 0x1A), value, 12, StringConverterOption.ClearZero);
get => StringConverter8.GetString(Data.Slice(0x120, 0x1A));
set => StringConverter8.SetString(Data.Slice(0x120, 0x1A), value, 12, StringConverterOption.ClearZero);
}
public LanguageID LanguageReceived

View File

@ -813,8 +813,7 @@ public virtual void SetMysteryGift(int index, PCD pcd)
if (pcd.Data.Length != PCD.Size)
throw new InvalidCastException(nameof(pcd));
var gift = pcd.Gift;
if (gift.VerifyPKEncryption())
pcd.Gift = gift; // ensure data is encrypted in the object
gift.VerifyPKEncryption();
SAV.SetData(GetCardSpanPCD(index), pcd.Data);
}

View File

@ -270,8 +270,7 @@ private void ClickDelete(object sender, EventArgs e)
return;
int index = pba.IndexOf(pb);
var arr = Album[index].Data;
Array.Clear(arr, 0, arr.Length);
Album[index].Clear();
// Shuffle blank card down
int i = index;
@ -497,7 +496,7 @@ private async void BoxSlot_MouseDown(object? sender, MouseEventArgs e)
string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(gift.FileName));
try
{
await File.WriteAllBytesAsync(newfile, gift.Write()).ConfigureAwait(true);
File.WriteAllBytes(newfile, gift.Write());
DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Copy | DragDropEffects.Move);
}
// Sometimes the drag-drop is canceled or ends up at a bad location. Don't bother recovering from an exception; just display a safe error message.