Rework SCBlock to Memory<byte>

This commit is contained in:
Kurt
2025-01-16 20:55:07 -06:00
parent 2442165907
commit 0549cfda4a
54 changed files with 117 additions and 117 deletions

View File

@@ -188,7 +188,7 @@ private static List<SlotInfoMisc> GetExtraSlots8(ISaveBlock8Main sav)
if (sav is SAV8SWSH {SaveRevision: >= 2} s8)
{
var block = s8.Blocks.GetBlockSafe(SaveBlockAccessor8SWSH.KFusedCalyrex);
var c = new SlotInfoMisc(block.Data, 3, true) {Type = StorageSlotType.FusedCalyrex};
var c = new SlotInfoMisc(block.Raw, 3, true) {Type = StorageSlotType.FusedCalyrex};
list.Insert(3, c);
}
@@ -226,20 +226,19 @@ private static List<SlotInfoMisc> GetExtraSlots9(SAV9SV sav)
};
var block = sav.Blocks.GetBlock(SaveBlockAccessor9SV.KFusedCalyrex);
list.Add(new(block.Data, 0, true) { Type = StorageSlotType.FusedCalyrex });
list.Add(new(block.Raw, 0, true) { Type = StorageSlotType.FusedCalyrex });
if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KFusedKyurem, out var kyurem))
list.Add(new(kyurem.Data, 1, true) { Type = StorageSlotType.FusedKyurem });
list.Add(new(kyurem.Raw, 1, true) { Type = StorageSlotType.FusedKyurem });
if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KFusedNecrozmaS, out var solgaleo))
list.Add(new(solgaleo.Data, 2, true) { Type = StorageSlotType.FusedNecrozmaS });
list.Add(new(solgaleo.Raw, 2, true) { Type = StorageSlotType.FusedNecrozmaS });
if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KFusedNecrozmaM, out var lunala))
list.Add(new(lunala.Data, 3, true) { Type = StorageSlotType.FusedNecrozmaM });
list.Add(new(lunala.Raw, 3, true) { Type = StorageSlotType.FusedNecrozmaM });
if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KSurpriseTrade, out var surprise))
{
var st = surprise.Data.AsMemory();
list.Add(new(st[0x198..], 0) { Type = StorageSlotType.Misc }); // my upload
list.Add(new(st[0x2C..], 1) { Type = StorageSlotType.Misc }); // received from others
list.Add(new(surprise.Raw[0x198..], 0) { Type = StorageSlotType.Misc }); // my upload
list.Add(new(surprise.Raw[0x02C..], 1) { Type = StorageSlotType.Misc }); // received from others
}
return list;
}

View File

@@ -45,14 +45,14 @@ private class Raid9
public Raid9(SAV9SV sav)
{
var paldea = GetBlock(sav.AllBlocks, KTeraRaidPaldea);
Paldea = new RaidSpawnList9(sav, paldea, paldea.Data, RaidSpawnList9.RaidCountLegal_T0, true);
Paldea = new RaidSpawnList9(sav, paldea, paldea.Raw, RaidSpawnList9.RaidCountLegal_T0, true);
if (TryGetBlock(sav.AllBlocks, KTeraRaidDLC, out var raidDLC))
{
var buffer = raidDLC.Data;
var buffer = raidDLC.Raw;
const int size = 0xC80;
var memKita = buffer.AsMemory(0, size);
var memBlue = buffer.AsMemory(size, size);
var memKita = buffer[..size];
var memBlue = buffer.Slice(size, size);
Kitakami = new RaidSpawnList9(sav, raidDLC, memKita, RaidSpawnList9.RaidCountLegal_T1, false);
Blueberry = new RaidSpawnList9(sav, raidDLC, memBlue, RaidSpawnList9.RaidCountLegal_T2, false);
}

View File

@@ -28,7 +28,10 @@ public sealed class SCBlock
/// <summary>
/// Decrypted data for this block.
/// </summary>
public readonly byte[] Data;
public readonly Memory<byte> Raw;
/// <inheritdoc cref="Data"/>
public Span<byte> Data => Raw.Span;
/// <summary>
/// Changes the block's Boolean type. Will throw if the old / new <see cref="Type"/> is not boolean.
@@ -59,7 +62,7 @@ public void ChangeData(ReadOnlySpan<byte> value)
/// </summary>
/// <param name="key">Hash key</param>
/// <param name="type">Value the block has</param>
internal SCBlock(uint key, SCTypeCode type) : this(key, type, [])
internal SCBlock(uint key, SCTypeCode type) : this(key, type, Memory<byte>.Empty)
{
}
@@ -69,11 +72,11 @@ internal SCBlock(uint key, SCTypeCode type) : this(key, type, [])
/// <param name="key">Hash key</param>
/// <param name="type">Type of data that can be read</param>
/// <param name="arr">Backing byte array to interpret as a typed value</param>
internal SCBlock(uint key, SCTypeCode type, byte[] arr)
internal SCBlock(uint key, SCTypeCode type, Memory<byte> arr)
{
Key = key;
Type = type;
Data = arr;
Raw = arr;
}
/// <summary>
@@ -82,11 +85,11 @@ internal SCBlock(uint key, SCTypeCode type, byte[] arr)
/// <param name="key">Hash key</param>
/// <param name="arr">Backing byte array to read primitives from</param>
/// <param name="subType">Primitive value type</param>
internal SCBlock(uint key, byte[] arr, SCTypeCode subType)
internal SCBlock(uint key, Memory<byte> arr, SCTypeCode subType)
{
Key = key;
Type = SCTypeCode.Array;
Data = arr;
Raw = arr;
SubType = subType;
}
@@ -109,7 +112,7 @@ public SCBlock Clone()
{
if (Data.Length == 0)
return new SCBlock(Key, Type);
var clone = Data.AsSpan().ToArray();
var clone = Data.ToArray();
if (SubType == 0)
return new SCBlock(Key, Type, clone);
return new SCBlock(Key, clone, SubType);

View File

@@ -105,7 +105,7 @@ void ReplaceLabels(Dictionary<string, IDataIndirect> list, IEnumerable<SCBlock>
{
foreach (var b in blocks)
{
var match = list.FirstOrDefault(z => z.Value.Equals(b.Data));
var match = list.FirstOrDefault(z => z.Value.Equals(b.Raw));
if (match.Key is not { } x)
continue;
ref var exist = ref CollectionsMarshal.GetValueRefOrNullRef(names, b.Key);

View File

@@ -96,7 +96,7 @@ private string GetBlockHint(SCBlock z, int index)
if (block.Data.Length != 0)
{
static bool SameBackingBuffer(IDataIndirect d, ReadOnlyMemory<byte> data) => d.Equals(data);
var obj = BlockList.FirstOrDefault(z => SameBackingBuffer(z.Value, block.Data));
var obj = BlockList.FirstOrDefault(z => SameBackingBuffer(z.Value, block.Raw));
if (obj is not (null, null))
{
saveBlock = obj.Value;

View File

@@ -5,26 +5,25 @@
namespace PKHeX.Core;
public sealed class Swarm3(byte[] Data)
public sealed class Swarm3(Memory<byte> Raw)
{
public const int SIZE = 0x14;
public readonly byte[] Data = Data;
private Span<byte> Raw => Data.AsSpan();
public Span<byte> Data => Raw.Span;
public ushort Gen3Species { get => ReadUInt16LittleEndian(Raw); set => WriteUInt16LittleEndian(Raw, value); }
public byte MapNum { get => Raw[2]; set => Raw[2] = value; }
public byte MapGroup { get => Raw[3]; set => Raw[3] = value; }
public byte Level { get => Raw[4]; set => Raw[4] = value; }
public byte Unused1 { get => Raw[5]; set => Raw[5] = value; }
public ushort Unused2 { get => ReadUInt16LittleEndian(Raw[0x6..]); set => WriteUInt16LittleEndian(Raw[0x6..], value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Raw[0x8..]); set => WriteUInt16LittleEndian(Raw[0x8..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Raw[0xA..]); set => WriteUInt16LittleEndian(Raw[0xA..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Raw[0xC..]); set => WriteUInt16LittleEndian(Raw[0xC..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Raw[0xE..]); set => WriteUInt16LittleEndian(Raw[0xE..], value); }
public byte Unused3 { get => Raw[0x10]; set => Raw[0x10] = value; }
public byte EncounterProbability { get => Raw[0x11]; set => Raw[0x11] = value; }
public ushort DaysLeft { get => ReadUInt16LittleEndian(Raw[0x12..]); set => WriteUInt16LittleEndian(Raw[0x12..], value); }
public ushort Gen3Species { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public byte MapNum { get => Data[2]; set => Data[2] = value; }
public byte MapGroup { get => Data[3]; set => Data[3] = value; }
public byte Level { get => Data[4]; set => Data[4] = value; }
public byte Unused1 { get => Data[5]; set => Data[5] = value; }
public ushort Unused2 { get => ReadUInt16LittleEndian(Data[0x6..]); set => WriteUInt16LittleEndian(Data[0x6..], value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x8..]); set => WriteUInt16LittleEndian(Data[0x8..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Data[0xA..]); set => WriteUInt16LittleEndian(Data[0xA..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Data[0xC..]); set => WriteUInt16LittleEndian(Data[0xC..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Data[0xE..]); set => WriteUInt16LittleEndian(Data[0xE..], value); }
public byte Unused3 { get => Data[0x10]; set => Data[0x10] = value; }
public byte EncounterProbability { get => Data[0x11]; set => Data[0x11] = value; }
public ushort DaysLeft { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], value); }
public Swarm3(Species species, byte level, byte map, Move m1, Move m2 = 0, Move m3 = 0, Move m4 = 0) : this(new byte[SIZE])
{

View File

@@ -6,13 +6,13 @@ namespace PKHeX.Core;
/// <summary>
/// Honey Tree in Sinnoh (Gen4)
/// </summary>
public sealed class HoneyTreeValue(byte[] Data)
public sealed class HoneyTreeValue(Memory<byte> Raw)
{
public const int Size = 8;
public readonly byte[] Data = Data;
public Span<byte> Data => Raw.Span;
public uint Time { get => ReadUInt32LittleEndian(Data.AsSpan(0)); set => WriteUInt32LittleEndian(Data.AsSpan(0), value); }
public uint Time { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
public int Slot { get => Data[4]; set => Data[4] = (byte)value; }
public int SubTable { get => Data[5]; set => Data[5] = (byte)value; } // offset by 1 with respect to Group
public int Group { get => Data[6]; set { Data[6] = (byte)value; SubTable = Math.Max(0, Group - 1); } }

View File

@@ -8,7 +8,7 @@ namespace PKHeX.Core;
public sealed class PlayTime7b : PlayTimeLastSaved<SaveFile, Epoch1900DateTimeValue>
{
public PlayTime7b(SAV7b sav, Memory<byte> raw) : base(sav, raw) { }
public PlayTime7b(SAV8SWSH sav, SCBlock block) : base(sav, block.Data) { }
public PlayTime7b(SAV8SWSH sav, SCBlock block) : base(sav, block.Raw) { }
protected override Epoch1900DateTimeValue LastSaved => new(Raw.Slice(0x4, 4));
}

View File

@@ -10,5 +10,5 @@ namespace PKHeX.Core;
public sealed class PlayTime8b : PlayTime<SaveFile>
{
public PlayTime8b(SAV8BS sav, Memory<byte> raw) : base(sav, raw) { }
public PlayTime8b(SAV8LA sav, SCBlock block) : base(sav, block.Data) { }
public PlayTime8b(SAV8LA sav, SCBlock block) : base(sav, block.Raw) { }
}

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Exposes information about Box Names and which box is the first box to show when the UI is opened.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class BoxLayout8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Data), IBoxDetailName
public sealed class BoxLayout8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Raw), IBoxDetailName
{
public const int BoxCount = 32;

View File

@@ -9,7 +9,7 @@ namespace PKHeX.Core;
/// Stores the position of the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class Coordinates8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Data)
public sealed class Coordinates8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Raw)
{
// Map
private Span<byte> MapName() => Data.Slice(0x08, 0x48);

View File

@@ -9,7 +9,7 @@ namespace PKHeX.Core;
/// <remarks>
/// Reads four separate pouch blobs: Items, Key Items, Storage, and Recipes.
/// </remarks>
public sealed class MyItem8a(SAV8LA sav, SCBlock block) : MyItem(sav, block.Data)
public sealed class MyItem8a(SAV8LA sav, SCBlock block) : MyItem(sav, block.Raw)
{
public override IReadOnlyList<InventoryPouch> Inventory
{
@@ -49,14 +49,14 @@ public override IReadOnlyList<InventoryPouch> Inventory
private static void LoadFavorites(ReadOnlySpan<InventoryPouch8a> pouches, SCBlockAccessor access)
{
var favorites = access.GetBlock(SaveBlockAccessor8LA.KItemFavorite).Data.AsSpan();
var favorites = access.GetBlock(SaveBlockAccessor8LA.KItemFavorite).Data;
foreach (var arr in pouches)
LoadFavorites(arr.Items, favorites);
}
private static void SaveFavorites(ReadOnlySpan<InventoryPouch8a> pouches, SCBlockAccessor access)
{
var favorites = access.GetBlock(SaveBlockAccessor8LA.KItemFavorite).Data.AsSpan();
var favorites = access.GetBlock(SaveBlockAccessor8LA.KItemFavorite).Data;
favorites.Clear();
foreach (var arr in pouches)
SaveFavorites(arr.Items, favorites);

View File

@@ -8,7 +8,7 @@ namespace PKHeX.Core;
/// Stores data about the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class MyStatus8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Data)
public sealed class MyStatus8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Raw)
{
public uint ID32
{

View File

@@ -1,6 +1,6 @@
namespace PKHeX.Core;
public sealed class Party8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Data)
public sealed class Party8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Raw)
{
public int PartyCount
{

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Stores the selected appearance choices of the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class PlayerFashion8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Data)
public sealed class PlayerFashion8a(SAV8LA sav, SCBlock block) : SaveBlock<SAV8LA>(sav, block.Raw)
{
public ulong Hair { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }
public ulong Contacts { get => ReadUInt64LittleEndian(Data[0x08..]); set => WriteUInt64LittleEndian(Data[0x08..], value); }

View File

@@ -11,7 +11,7 @@ namespace PKHeX.Core;
/// </summary>>
public sealed class PokedexSave8a(SAV8LA SaveFile, SCBlock block)
{
private readonly PokedexSaveData SaveData = new(block.Data);
private readonly PokedexSaveData SaveData = new(block.Raw);
public const int MAX_SPECIES = 981;
public const int MAX_FORM = 120;

View File

@@ -3,7 +3,7 @@
namespace PKHeX.Core;
public sealed class Box8(SaveFile sav, SCBlock block) : SaveBlock<SaveFile>(sav, block.Data)
public sealed class Box8(SaveFile sav, SCBlock block) : SaveBlock<SaveFile>(sav, block.Raw)
{
[Browsable(false)] public new Memory<byte> Raw => base.Raw;
}

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class BoxLayout8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data), IBoxDetailName
public sealed class BoxLayout8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw), IBoxDetailName
{
public const int BoxCount = 32;

View File

@@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Stores the position of the player.
/// </summary>
public sealed class Coordinates8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class Coordinates8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
// Position
public float X { get => ReadSingleLittleEndian(Data[0x10..]); set => WriteSingleLittleEndian(Data[0x10..], value); }

View File

@@ -6,7 +6,7 @@ namespace PKHeX.Core;
/// <summary>
/// Storage for the two in-game daycare structures.
/// </summary>
public sealed class Daycare8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class Daycare8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
// BLOCK STRUCTURE:
// bool8 present

View File

@@ -3,7 +3,7 @@
namespace PKHeX.Core;
public sealed class FashionUnlock8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class FashionUnlock8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
private const int SIZE_ENTRY = 0x80;
private const int REGIONS = 15;

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class FieldMoveModelSave8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class FieldMoveModelSave8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
public int M { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, (ushort)value); }
public float X { get => ReadSingleLittleEndian(Data[0x08..]); set => WriteSingleLittleEndian(Data[0x08..], value); }

View File

@@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Storage for the species that was fused into <see cref="Species.Kyurem"/> and <see cref="Species.Necrozma"/>.
/// </summary>
public sealed class Fused8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class Fused8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
private const int SizeStored = PokeCrypto.SIZE_8PARTY;

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
public sealed class HallOfFameTime8 : SaveBlock<SAV8SWSH>
{
public HallOfFameTime8(SAV8SWSH sav, SCBlock block) : base(sav, block.Data)
public HallOfFameTime8(SAV8SWSH sav, SCBlock block) : base(sav, block.Raw)
{
Debug.Assert(Data.Length == 8);
}

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class Misc8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class Misc8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
public int Badges
{

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class MyItem8(SAV8SWSH SAV, SCBlock block) : MyItem(SAV, block.Data)
public sealed class MyItem8(SAV8SWSH SAV, SCBlock block) : MyItem(SAV, block.Raw)
{
public const int Medicine = 0;
public const int Balls = Medicine + (4 * PouchSize8.Medicine);

View File

@@ -4,7 +4,7 @@
namespace PKHeX.Core;
public sealed class MyStatus8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class MyStatus8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
public const uint MaxWatt = 9999999;

View File

@@ -1,6 +1,6 @@
namespace PKHeX.Core;
public sealed class Party8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class Party8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
public int PartyCount
{

View File

@@ -4,7 +4,7 @@
namespace PKHeX.Core;
public sealed class RaidSpawnList8(SAV8SWSH sav, SCBlock block, int legal) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class RaidSpawnList8(SAV8SWSH sav, SCBlock block, int legal) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
public readonly int CountAll = block.Data.Length / RaidSpawnDetail.SIZE;
public readonly int CountUsed = legal;

View File

@@ -4,7 +4,7 @@
namespace PKHeX.Core;
public sealed class Record8(SAV8SWSH sav, SCBlock block) : RecordBlock<SAV8SWSH>(sav, block.Data)
public sealed class Record8(SAV8SWSH sav, SCBlock block) : RecordBlock<SAV8SWSH>(sav, block.Raw)
{
public const int RecordCount = 50;
public const int WattTotal = 22;

View File

@@ -32,7 +32,7 @@ public void LoadBattleTeams()
for (int i = 0; i < TeamCount * 6; i++)
{
short val = ReadInt16LittleEndian(Indexes.Data.AsSpan(i * 2));
short val = ReadInt16LittleEndian(Indexes.Data[(i*2)..]);
if (val < 0)
{
TeamSlots[i] = NONE_SELECTED;
@@ -60,7 +60,7 @@ public void UnlockAllTeams()
public void SaveBattleTeams()
{
var span = Indexes.Data.AsSpan();
var span = Indexes.Data;
for (int i = 0; i < TeamCount * 6; i++)
{
int index = TeamSlots[i];

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// <summary>
/// Pokémon Team that shows up at the title screen.
/// </summary>
public sealed class TitleScreen8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class TitleScreen8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
/// <summary>
/// Gets an object that exposes the data of the corresponding party <see cref="index"/>.
@@ -15,7 +15,7 @@ public sealed class TitleScreen8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SW
public TitleScreen8Poke ViewPoke(int index)
{
int ofs = GetPokeOffset(index);
var raw = block.Data.AsMemory(ofs, TitleScreen8Poke.SIZE);
var raw = block.Raw.Slice(ofs, TitleScreen8Poke.SIZE);
return new TitleScreen8Poke(raw);
}

View File

@@ -5,7 +5,7 @@
namespace PKHeX.Core;
public sealed class TrainerCard8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Data)
public sealed class TrainerCard8(SAV8SWSH sav, SCBlock block) : SaveBlock<SAV8SWSH>(sav, block.Raw)
{
private Span<byte> OriginalTrainerTrash => Data[..0x1A];
@@ -230,7 +230,7 @@ public ulong Shoe
public TrainerCard8Poke ViewPoke(int index)
{
var ofs = GetPokeOffset(index);
var raw = block.Data.AsMemory(ofs, TrainerCard8Poke.SIZE);
var raw = block.Raw.Slice(ofs, TrainerCard8Poke.SIZE);
return new TrainerCard8Poke(raw);
}

View File

@@ -2,9 +2,9 @@
namespace PKHeX.Core;
public sealed class BlueberryClubRoom9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class BlueberryClubRoom9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public BlueberrySupportBoard9 SupportBoard => new(block.Data.AsMemory(0, 0x38));
public BlueberrySupportBoard9 SupportBoard => new(block.Raw[..0x38]);
public BlueberryClubRoomStyle9 CurrentStyle { get => (BlueberryClubRoomStyle9)Data[0xE6C]; set => Data[0xE6C] = (byte)value; }
}

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class BlueberryQuestRecord9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class BlueberryQuestRecord9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public uint QuestsDoneSolo { get => ReadUInt32LittleEndian(Data[0x188..]); set => WriteUInt32LittleEndian(Data[0x188..], value); }
public uint QuestsDoneGroup { get => ReadUInt32LittleEndian(Data[0x18C..]); set => WriteUInt32LittleEndian(Data[0x18C..], value); }

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class BoxLayout9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data), IBoxDetailName
public sealed class BoxLayout9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw), IBoxDetailName
{
public const int BoxCount = 32;

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class ConfigCamera9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class ConfigCamera9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
// Structure: u32
/* CameraSupport:1 | On = 0, Off = 1

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class ConfigSave9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class ConfigSave9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
// Structure: u32
/* TalkingSpeed:2

View File

@@ -6,7 +6,7 @@
namespace PKHeX.Core;
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class FixedSpawnList9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class FixedSpawnList9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public readonly int CountAll = block.Data.Length / FixedSpawnDetail.SIZE;

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Player item pouches storage
/// </summary>
/// <remarks>size=0xBB80 (<see cref="ItemSaveSize"/> items)</remarks>
public sealed class MyItem9(SAV9SV sav, SCBlock block) : MyItem(sav, block.Data)
public sealed class MyItem9(SAV9SV sav, SCBlock block) : MyItem(sav, block.Raw)
{
public const int ItemSaveSize = 3000;

View File

@@ -3,7 +3,7 @@
namespace PKHeX.Core;
public sealed class MyStatus9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class MyStatus9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public uint ID32
{

View File

@@ -1,6 +1,6 @@
namespace PKHeX.Core;
public sealed class Party9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class Party9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public int PartyCount
{

View File

@@ -2,7 +2,7 @@
namespace PKHeX.Core;
public sealed class PlayTime9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class PlayTime9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public int PlayedHours
{

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Stores the selected facial appearances of the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class PlayerAppearance9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class PlayerAppearance9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public ulong SkinColor { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }
public ulong LipColor { get => ReadUInt64LittleEndian(Data[0x08..]); set => WriteUInt64LittleEndian(Data[0x08..], value); }

View File

@@ -7,7 +7,7 @@ namespace PKHeX.Core;
/// Stores the selected clothing choices of the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class PlayerFashion9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class PlayerFashion9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public ulong Base { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }
public ulong Accessory { get => ReadUInt64LittleEndian(Data[0x08..]); set => WriteUInt64LittleEndian(Data[0x08..], value); }

View File

@@ -60,7 +60,7 @@ public bool Defeated
}
}
public sealed class RaidSevenStarCaptured9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class RaidSevenStarCaptured9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public readonly int CountAll = block.Data.Length / DetailSize;
private const int DetailSize = SevenStarRaidCapturedDetail.SIZE;
@@ -104,7 +104,7 @@ public bool Defeated
// 0x06 - 0x07 padding
}
public sealed class RaidSevenStarDefeated9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Data)
public sealed class RaidSevenStarDefeated9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
// Structure matches the RaidSevenStarCapture9 but there are 4 bytes at the front to indicate if the copy of previous defeated flags happened when updating save
public readonly int CountAll = (block.Data.Length - 0x04) / SevenStarRaidDefeatedDetail.SIZE;

View File

@@ -17,7 +17,7 @@ public sealed class RaidSpawnList9 : SaveBlock<SAV9SV>
private readonly Memory<byte> Memory;
private Span<byte> Span => Memory.Span;
public RaidSpawnList9(SAV9SV sav, SCBlock block, Memory<byte> memory, int countUsed, bool hasSeeds) : base(sav, block.Data)
public RaidSpawnList9(SAV9SV sav, SCBlock block, Memory<byte> memory, int countUsed, bool hasSeeds) : base(sav, block.Raw)
{
Memory = memory;
var length = memory.Length;

View File

@@ -14,7 +14,7 @@ public PokeDexEntry9Kitakami Get(ushort species)
const int size = PokeDexEntry9Kitakami.SIZE;
var internalSpecies = SpeciesConverter.GetInternal9(species);
var span = Block.Data.AsSpan(internalSpecies * size, size);
var span = Block.Data.Slice(internalSpecies * size, size);
return new PokeDexEntry9Kitakami(span);
}
@@ -94,10 +94,7 @@ private ushort GetSpecies(byte group, int index)
return (0, 0);
}
public override void SeenNone()
{
Array.Clear(Block.Data, 0, Block.Data.Length);
}
public override void SeenNone() => Block.Data.Clear();
public override void CaughtNone()
{

View File

@@ -5,7 +5,7 @@ namespace PKHeX.Core;
/// <summary>
/// Pokédex structure used for <see cref="GameVersion.SV"/>.
/// </summary>>
public sealed class Zukan9Paldea(SAV9SV sav, SCBlock block) : ZukanBase<SAV9SV>(sav, block.Data)
public sealed class Zukan9Paldea(SAV9SV sav, SCBlock block) : ZukanBase<SAV9SV>(sav, block.Raw)
{
public PokeDexEntry9Paldea Get(ushort species)
{
@@ -14,7 +14,7 @@ public PokeDexEntry9Paldea Get(ushort species)
const int size = PokeDexEntry9Paldea.SIZE;
var internalSpecies = SpeciesConverter.GetInternal9(species);
var span = block.Data.AsSpan(internalSpecies * size, size);
var span = block.Data.Slice(internalSpecies * size, size);
return new PokeDexEntry9Paldea(span);
}
@@ -119,10 +119,7 @@ private ushort GetSpecies(byte group, int index)
return default;
}
public override void SeenNone()
{
Array.Clear(block.Data, 0, block.Data.Length);
}
public override void SeenNone() => block.Data.Clear();
public override void CaughtNone()
{

View File

@@ -41,7 +41,7 @@ public int GetRevision()
return 2;
}
private byte[] GetDexBlock(Zukan8Type infoDexType) => infoDexType switch
private Span<byte> GetDexBlock(Zukan8Type infoDexType) => infoDexType switch
{
Zukan8Type.Galar => Galar.Data,
Zukan8Type.Armor => Rigel1.Data,
@@ -49,8 +49,8 @@ public int GetRevision()
_ => throw new ArgumentOutOfRangeException(nameof(infoDexType), infoDexType, null),
};
private static bool GetFlag(byte[] data, int baseOffset, int bitIndex) => FlagUtil.GetFlag(data, baseOffset + (bitIndex >> 3), bitIndex);
private static void SetFlag(byte[] data, int baseOffset, int bitIndex, bool value = true) => FlagUtil.SetFlag(data, baseOffset + (bitIndex >> 3), bitIndex, value);
private static bool GetFlag(ReadOnlySpan<byte> data, int baseOffset, int bitIndex) => FlagUtil.GetFlag(data, baseOffset + (bitIndex >> 3), bitIndex);
private static void SetFlag(Span<byte> data, int baseOffset, int bitIndex, bool value = true) => FlagUtil.SetFlag(data, baseOffset + (bitIndex >> 3), bitIndex, value);
private static Dictionary<ushort, Zukan8Index> GetDexLookup(PersonalTable8SWSH pt, int dexRevision, int count)
{
@@ -177,12 +177,12 @@ public override bool GetSeen(ushort species)
public bool GetSeen(Zukan8Index entry)
{
byte[] data = GetDexBlock(entry.DexType);
var data = GetDexBlock(entry.DexType);
int offset = entry.Offset;
for (int i = 0; i < SeenRegionCount; i++)
{
var ofs = offset + (SeenRegionSize * i);
if (ReadUInt64LittleEndian(data.AsSpan(ofs)) != 0)
if (ReadUInt64LittleEndian(data[ofs..]) != 0)
return true;
}
@@ -304,7 +304,7 @@ public uint GetFormDisplayed(Zukan8Index entry)
{
var data = GetDexBlock(entry.DexType);
var index = entry.Offset;
var value = ReadUInt32LittleEndian(data.AsSpan(index + OFS_CAUGHT));
var value = ReadUInt32LittleEndian(data[(index + OFS_CAUGHT)..]);
return (value >> 15) & 0x1FFF; // (0x1FFF is really overkill, GameFreak)
}
@@ -320,7 +320,7 @@ public void SetFormDisplayed(Zukan8Index entry, uint value = 0)
{
var data = GetDexBlock(entry.DexType);
var index = entry.Offset;
var span = data.AsSpan(index + OFS_CAUGHT);
var span = data[(index + OFS_CAUGHT)..];
var current = ReadUInt32LittleEndian(span);
uint update = (current & ~(0x1FFFu << 15)) | ((value & 0x1FFF) << 15);
WriteUInt32LittleEndian(span, update);
@@ -338,7 +338,7 @@ public uint GetGenderDisplayed(Zukan8Index entry)
{
var data = GetDexBlock(entry.DexType);
var index = entry.Offset;
var value = ReadUInt32LittleEndian(data.AsSpan(index + OFS_CAUGHT));
var value = ReadUInt32LittleEndian(data[(index + OFS_CAUGHT)..]);
return (value >> 29) & 3;
}
@@ -354,7 +354,7 @@ public void SetGenderDisplayed(Zukan8Index entry, uint value = 0)
{
var data = GetDexBlock(entry.DexType);
var index = entry.Offset;
var span = data.AsSpan(index + OFS_CAUGHT);
var span = data[(index + OFS_CAUGHT)..];
var current = ReadUInt32LittleEndian(span);
uint update = (current & ~(3u << 29)) | ((value & 3) << 29);
WriteUInt32LittleEndian(span, update);
@@ -432,7 +432,7 @@ private uint GetU32(Zukan8Index entry, int ofs)
var dex = entry.DexType;
var index = entry.Offset;
var data = GetDexBlock(dex);
return ReadUInt32LittleEndian(data.AsSpan(index + ofs));
return ReadUInt32LittleEndian(data[(index + ofs)..]);
}
private void SetU32(ushort species, uint value, int ofs)
@@ -448,7 +448,7 @@ private void SetU32(Zukan8Index entry, uint value, int ofs)
var dex = entry.DexType;
var index = entry.Offset;
var data = GetDexBlock(dex);
WriteUInt32LittleEndian(data.AsSpan(index + ofs), value);
WriteUInt32LittleEndian(data[(index + ofs)..], value);
}
#endregion
@@ -500,9 +500,9 @@ public override void SetDex(PKM pk)
public override void SeenNone()
{
Galar .Data.AsSpan().Clear();
Rigel1.Data.AsSpan().Clear();
Rigel2.Data.AsSpan().Clear();
Galar .Data.Clear();
Rigel1.Data.Clear();
Rigel2.Data.Clear();
}
public override void CaughtNone()
@@ -661,7 +661,7 @@ public override void ClearDexEntryAll(ushort species)
private void ClearDexEntryAll(Zukan8Index entry)
{
var data = GetDexBlock(entry.DexType);
Array.Clear(data, entry.Offset, EntrySize);
data.Slice(entry.Offset, EntrySize).Clear();
}
public void SetAllBattledCount(uint count = 500)

View File

@@ -12,7 +12,7 @@ public sealed class Epoch1900DateTimeValue(Memory<byte> Data) : EpochDateTime(Da
// Data should be 4 or 8 bytes where we only care about the first 4 or 4.5 bytes i.e. 32 or 36 bits
// First 12 bits are year from 1900, next 4 bits are 0 indexed month, next 5 are days, next 5 are hours, next 6 bits are minutes, (optional) last 4 bits are seconds
public Epoch1900DateTimeValue(SCBlock block) : this(block.Data) { }
public Epoch1900DateTimeValue(SCBlock block) : this(block.Raw) { }
private static DateTime Epoch => new(1900, 1, 1);

View File

@@ -14,7 +14,7 @@ public sealed class Epoch1900DateValue(Memory<byte> Data)
// First 12 bits are year from 1900, next 6 bits are 0 indexed month, next 6 are days
private Span<byte> Span => Data.Span;
public Epoch1900DateValue(SCBlock block) : this(block.Data) { }
public Epoch1900DateValue(SCBlock block) : this(block.Raw) { }
private static DateTime Epoch => new(1900, 1, 1);

View File

@@ -12,7 +12,7 @@ public sealed class Epoch1970Value(Memory<byte> Data)
{
private Span<byte> Span => Data.Span;
public Epoch1970Value(SCBlock block) : this(block.Data) { }
public Epoch1970Value(SCBlock block) : this(block.Raw) { }
/// <summary>
/// time_t (seconds since 1970 Epoch)

View File

@@ -3,6 +3,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PKHeX.Core;
using static PKHeX.Core.SCBlockUtil;
@@ -80,7 +81,11 @@ private void UpdateBlockSummaryControls()
{
var block = CurrentBlock;
L_Detail_R.Text = GetBlockSummary(block);
RTB_Hex.Text = string.Join(' ', block.Data.Select(z => $"{z:X2}"));
var sb = new StringBuilder();
foreach (var b in block.Data)
sb.Append($"{b:X2} ");
RTB_Hex.Text = sb.ToString();
var blockName = Metadata.GetBlockName(block, out var obj);
if (blockName != null)