From 48954533b53cd9c94c5732bb6bd3b6b8f4db89f2 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 24 May 2025 00:10:57 -0500 Subject: [PATCH] Make mysterygifts memory-backed objects --- .../Encounters/Data/EncounterEvent.cs | 22 ++--- .../ByGeneration/EncounterGenerator4.cs | 2 +- PKHeX.Core/MysteryGifts/DataMysteryGift.cs | 12 ++- PKHeX.Core/MysteryGifts/MysteryGift.cs | 14 +-- PKHeX.Core/MysteryGifts/PCD.cs | 31 +++---- PKHeX.Core/MysteryGifts/PGF.cs | 48 +++++----- PKHeX.Core/MysteryGifts/PGT.cs | 21 +++-- PKHeX.Core/MysteryGifts/PL6.cs | 6 +- PKHeX.Core/MysteryGifts/WA8.cs | 85 ++++++++--------- PKHeX.Core/MysteryGifts/WB7.cs | 18 ++-- PKHeX.Core/MysteryGifts/WB8.cs | 83 ++++++++--------- PKHeX.Core/MysteryGifts/WC5Full.cs | 11 ++- PKHeX.Core/MysteryGifts/WC6.cs | 67 +++++++------- PKHeX.Core/MysteryGifts/WC6Full.cs | 31 ++++--- PKHeX.Core/MysteryGifts/WC7.cs | 85 ++++++++--------- PKHeX.Core/MysteryGifts/WC7Full.cs | 31 ++++--- PKHeX.Core/MysteryGifts/WC8.cs | 87 +++++++++--------- PKHeX.Core/MysteryGifts/WC9.cs | 91 ++++++++++--------- PKHeX.Core/MysteryGifts/WR7.cs | 47 +++++----- PKHeX.Core/Saves/SAV4.cs | 3 +- .../Subforms/Save Editors/SAV_Wondercard.cs | 5 +- 21 files changed, 409 insertions(+), 391 deletions(-) diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs index 4d3826c3d..2bc232fcf 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs @@ -70,19 +70,19 @@ public static class EncounterEvent public static WC9[] EGDB_G9 { get; private set; } = []; #endregion - private static PCD[] GetPCDDB(ReadOnlySpan bin) => Get(bin, PCD.Size, static d => new PCD(d)); - private static PGF[] GetPGFDB(ReadOnlySpan bin) => Get(bin, PGF.Size, static d => new PGF(d)); + private static PCD[] GetPCDDB(Memory bin) => Get(bin, PCD.Size, static d => new PCD(d)); + private static PGF[] GetPGFDB(Memory bin) => Get(bin, PGF.Size, static d => new PGF(d)); - private static WC6[] GetWC6DB(ReadOnlySpan wc6bin, ReadOnlySpan wc6full) => WC6Full.GetArray(wc6full, wc6bin); - private static WC7[] GetWC7DB(ReadOnlySpan wc7bin, ReadOnlySpan wc7full) => WC7Full.GetArray(wc7full, wc7bin); + private static WC6[] GetWC6DB(Memory wc6bin, Memory wc6full) => WC6Full.GetArray(wc6full, wc6bin); + private static WC7[] GetWC7DB(Memory wc7bin, Memory wc7full) => WC7Full.GetArray(wc7full, wc7bin); - private static WB7[] GetWB7DB(ReadOnlySpan bin) => Get(bin, WB7.Size, static d => new WB7(d)); - private static WC8[] GetWC8DB(ReadOnlySpan bin) => Get(bin, WC8.Size, static d => new WC8(d)); - private static WB8[] GetWB8DB(ReadOnlySpan bin) => Get(bin, WB8.Size, static d => new WB8(d)); - private static WA8[] GetWA8DB(ReadOnlySpan bin) => Get(bin, WA8.Size, static d => new WA8(d)); - private static WC9[] GetWC9DB(ReadOnlySpan bin) => Get(bin, WC9.Size, static d => new WC9(d)); + private static WB7[] GetWB7DB(Memory bin) => Get(bin, WB7.Size, static d => new WB7(d)); + private static WC8[] GetWC8DB(Memory bin) => Get(bin, WC8.Size, static d => new WC8(d)); + private static WB8[] GetWB8DB(Memory bin) => Get(bin, WB8.Size, static d => new WB8(d)); + private static WA8[] GetWA8DB(Memory bin) => Get(bin, WA8.Size, static d => new WA8(d)); + private static WC9[] GetWC9DB(Memory bin) => Get(bin, WC9.Size, static d => new WC9(d)); - private static T[] Get(ReadOnlySpan bin, int size, Func ctor) + private static T[] Get(Memory bin, int size, Func, T> ctor) { // bin is a multiple of size // bin.Length % size == 0 @@ -91,7 +91,7 @@ private static T[] Get(ReadOnlySpan bin, int size, Func 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; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs index 360874b06..82a7f730d 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs @@ -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 GetEncounters(PKM pk, LegalInfo info) { diff --git a/PKHeX.Core/MysteryGifts/DataMysteryGift.cs b/PKHeX.Core/MysteryGifts/DataMysteryGift.cs index e1ae18f1c..6ff9c50dc 100644 --- a/PKHeX.Core/MysteryGifts/DataMysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/DataMysteryGift.cs @@ -5,14 +5,14 @@ namespace PKHeX.Core; /// /// Mystery Gift backed by serialized fields from ROM/SAV data, rather than observed specifications. /// -public abstract class DataMysteryGift(byte[] Data) : MysteryGift +public abstract class DataMysteryGift(Memory Raw) : MysteryGift { - public readonly byte[] Data = Data; + public Span Data => Raw.Span; /// /// Returns an array for exporting outside the program (to disk, etc.). /// - public virtual byte[] Write() => Data; + public virtual ReadOnlySpan Write() => Data; public override int GetHashCode() { @@ -27,11 +27,13 @@ public override int GetHashCode() /// 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(0); + public sealed override bool Empty => !Data.ContainsAnyExcept(0); + + public void Clear() => Data.Clear(); } diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 39518c8d1..a5e1af08c 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -27,8 +27,8 @@ public abstract class MysteryGift : IEncounterable, IMoveset, ITrainerID32, IFat /// Raw data of the mystery gift. /// Extension of the file from which the was retrieved. /// An instance of representing the given data, or null if or is invalid. - /// This overload differs from by checking the / combo for validity. If either is invalid, a null reference is returned. - public static DataMysteryGift? GetMysteryGift(byte[] data, ReadOnlySpan ext) => data.Length switch + /// This overload differs from by checking the / combo for validity. If either is invalid, a null reference is returned. + public static DataMysteryGift? GetMysteryGift(Memory data, ReadOnlySpan 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 /// /// Raw data of the mystery gift. /// An instance of representing the given data, or null if is invalid. - public static DataMysteryGift? GetMysteryGift(byte[] data) => data.Length switch + public static DataMysteryGift? GetMysteryGift(Memory 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, }; diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs index 3431aa0b3..9e282e30b 100644 --- a/PKHeX.Core/MysteryGifts/PCD.cs +++ b/PKHeX.Core/MysteryGifts/PCD.cs @@ -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 /// -public sealed class PCD(byte[] Data) - : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, IRestrictVersion, IRandomCorrelation +public sealed class PCD(Memory raw) + : DataMysteryGift(raw), IRibbonSetEvent3, IRibbonSetEvent4, IRestrictVersion, IRandomCorrelation { public PCD() : this(new byte[Size]) { } + private readonly Memory _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 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 GetMetadata() => Data.AsSpan(PGT.Size); - public void SetMetadata(ReadOnlySpan data) => data.CopyTo(Data.AsSpan(PGT.Size)); + public Span GetMetadata() => Data[PGT.Size..]; + public void SetMetadata(ReadOnlySpan 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 CardTitleSpan => Data.AsSpan(0x104, TitleLength); + private Span 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; } diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index 6acdfd07c..f88120333 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -6,10 +6,12 @@ namespace PKHeX.Core; /// /// Generation 5 Mystery Gift Template File /// -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 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; } diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index 585200395..5a8117895 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -8,9 +8,10 @@ namespace PKHeX.Core; /// /// Generation 4 Mystery Gift Template File (Inner Gift Data, no card data) /// -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 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 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); } diff --git a/PKHeX.Core/MysteryGifts/PL6.cs b/PKHeX.Core/MysteryGifts/PL6.cs index 450438c89..58a280436 100644 --- a/PKHeX.Core/MysteryGifts/PL6.cs +++ b/PKHeX.Core/MysteryGifts/PL6.cs @@ -89,8 +89,8 @@ public sealed class LinkEntity6(Memory 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); } } diff --git a/PKHeX.Core/MysteryGifts/WA8.cs b/PKHeX.Core/MysteryGifts/WA8.cs index e2b5b2c9c..60c33af23 100644 --- a/PKHeX.Core/MysteryGifts/WA8.cs +++ b/PKHeX.Core/MysteryGifts/WA8.cs @@ -7,13 +7,14 @@ namespace PKHeX.Core; /// /// Generation 8 Mystery Gift Template File, same as with fields at the end. /// -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 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 RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + private Span 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 GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + private Span GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A); public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + private Span GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A); public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs index 0a6759bcd..bcee4947a 100644 --- a/PKHeX.Core/MysteryGifts/WB7.cs +++ b/PKHeX.Core/MysteryGifts/WB7.cs @@ -1,20 +1,20 @@ using System; -using static System.Buffers.Binary. BinaryPrimitives; +using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// /// Generation 7 Mystery Gift Template File (LGP/E) /// -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 raw) : base(raw) { } public const int Size = 0x310; private const int CardStart = 0x208; - private Span Card => Data.AsSpan(CardStart, 0x108); + private Span 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 GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + private Span GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A); public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + private Span GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A); public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); public void SetOT(int language, ReadOnlySpan 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() diff --git a/PKHeX.Core/MysteryGifts/WB8.cs b/PKHeX.Core/MysteryGifts/WB8.cs index 6ee13ddd5..abeb4d5a8 100644 --- a/PKHeX.Core/MysteryGifts/WB8.cs +++ b/PKHeX.Core/MysteryGifts/WB8.cs @@ -7,13 +7,14 @@ namespace PKHeX.Core; /// /// Generation 8b Mystery Gift Template File /// -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 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 RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + private Span 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 GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + private Span GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A); public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + private Span GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A); public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); diff --git a/PKHeX.Core/MysteryGifts/WC5Full.cs b/PKHeX.Core/MysteryGifts/WC5Full.cs index ef1cad64f..c10c677e3 100644 --- a/PKHeX.Core/MysteryGifts/WC5Full.cs +++ b/PKHeX.Core/MysteryGifts/WC5Full.cs @@ -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 Metadata => Data.AsSpan(PGF.Size); + public readonly Memory Raw; + public Span Data => Raw.Span; + private Span Metadata => Data[PGF.Size..]; - public WC5Full(byte[] data) + public WC5Full(Memory 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(), diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index c131815dc..9829dee32 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -6,10 +6,11 @@ namespace PKHeX.Core; /// /// Generation 6 Mystery Gift Template File /// -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 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; } diff --git a/PKHeX.Core/MysteryGifts/WC6Full.cs b/PKHeX.Core/MysteryGifts/WC6Full.cs index bd7ec13cf..37b34fde6 100644 --- a/PKHeX.Core/MysteryGifts/WC6Full.cs +++ b/PKHeX.Core/MysteryGifts/WC6Full.cs @@ -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 Raw; + public Span 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 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 WC6Full, ReadOnlySpan data) + private static uint GetDate(DateOnly date) => WC6.SetDate((uint)date.Year, (uint)date.Month, (uint)date.Day); + + public static WC6[] GetArray(Memory WC6Full, Memory data) { var countfull = WC6Full.Length / Size; var countgift = data.Length / WC6.Size; @@ -39,20 +43,21 @@ public static WC6[] GetArray(ReadOnlySpan WC6Full, ReadOnlySpan data return result; } - private static WC6 ReadWC6(ReadOnlySpan data, int ofs, DateOnly date) + private static WC6 ReadWC6(Memory 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 data, int ofs) + private static WC6 ReadWC6Only(Memory data, int ofs) { - var slice = data.Slice(ofs, WC6.Size).ToArray(); + var slice = data.Slice(ofs, WC6.Size); return new WC6(slice); } } diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 633c33625..ec08f1133 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -6,10 +6,11 @@ namespace PKHeX.Core; /// /// Generation 7 Mystery Gift Template File /// -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 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; } diff --git a/PKHeX.Core/MysteryGifts/WC7Full.cs b/PKHeX.Core/MysteryGifts/WC7Full.cs index 2498797f3..eecdf2efd 100644 --- a/PKHeX.Core/MysteryGifts/WC7Full.cs +++ b/PKHeX.Core/MysteryGifts/WC7Full.cs @@ -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 Raw; + public Span 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 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 wc7Full, ReadOnlySpan data) + private static uint GetDate(DateOnly date) => WC7.SetDate((uint)date.Year, (uint)date.Month, (uint)date.Day); + + public static WC7[] GetArray(Memory wc7Full, Memory data) { var countfull = wc7Full.Length / Size; var countgift = data.Length / WC7.Size; @@ -39,20 +43,21 @@ public static WC7[] GetArray(ReadOnlySpan wc7Full, ReadOnlySpan data return result; } - private static WC7 ReadWC7(ReadOnlySpan data, int ofs, DateOnly date) + private static WC7 ReadWC7(Memory 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 data, int ofs) + private static WC7 ReadWC7Only(Memory data, int ofs) { - var slice = data.Slice(ofs, WC7.Size).ToArray(); + var slice = data.Slice(ofs, WC7.Size); return new WC7(slice); } } diff --git a/PKHeX.Core/MysteryGifts/WC8.cs b/PKHeX.Core/MysteryGifts/WC8.cs index 9da69ade3..f42d3ad4c 100644 --- a/PKHeX.Core/MysteryGifts/WC8.cs +++ b/PKHeX.Core/MysteryGifts/WC8.cs @@ -7,11 +7,12 @@ namespace PKHeX.Core; /// /// Generation 8 Mystery Gift Template File /// -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 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 RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + private Span 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 GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + private Span GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A); public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + private Span GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A); public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); diff --git a/PKHeX.Core/MysteryGifts/WC9.cs b/PKHeX.Core/MysteryGifts/WC9.cs index 51adc660e..5337968a9 100644 --- a/PKHeX.Core/MysteryGifts/WC9.cs +++ b/PKHeX.Core/MysteryGifts/WC9.cs @@ -7,12 +7,13 @@ namespace PKHeX.Core; /// /// Generation 9 Mystery Gift Template File /// -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 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 RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + private Span 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 GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + private Span GetNicknameSpan(int language) => Data.Slice(GetNicknameOffset(language), 0x1A); public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + private Span GetOTSpan(int language) => Data.Slice(GetOTOffset(language), 0x1A); public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); diff --git a/PKHeX.Core/MysteryGifts/WR7.cs b/PKHeX.Core/MysteryGifts/WR7.cs index ccf82fdb8..41339dc96 100644 --- a/PKHeX.Core/MysteryGifts/WR7.cs +++ b/PKHeX.Core/MysteryGifts/WR7.cs @@ -10,9 +10,10 @@ namespace PKHeX.Core; /// A full is not stored in the structure, as it is immediately converted to upon receiving from server. /// The save file just stores a summary of the received data for the user to look back at. /// -public sealed class WR7(byte[] Data) : DataMysteryGift(Data) +public sealed class WR7 : DataMysteryGift { public WR7() : this(new byte[Size]) { } + public WR7(Memory 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 diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index 6ad94b764..1cdb9b776 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -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); } diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs index 31ab6d174..d71841d94 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs @@ -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.