SaveBlock Constructor Changes (#4191)

* SaveBlock Constructor Changes

- Add primary constructor for SaveBlock with default offset
- Update SaveBlock  subclasses to specify offset in contructor rather than as the constructor body

* Fix MyItem Subclasses Using SaveFile Rather Than Specific Classes
This commit is contained in:
Jonathan Herbert 2024-02-23 15:20:24 -04:00 committed by GitHub
parent 92c964d6fa
commit 4974371100
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 114 additions and 234 deletions

View file

@ -16,5 +16,6 @@ public interface ISaveBlock7b
PokeListHeader Storage { get; }
WB7Records GiftRecords { get; }
CaptureRecords Captured { get; }
GoParkStorage Park { get; }
PlayerGeoLocation7b PlayerGeoLocation { get; }
}

View file

@ -51,6 +51,7 @@ public sealed class SaveBlockAccessor7b : ISaveBlockAccessor<BlockInfo7b>, ISave
Captured = new CaptureRecords(sav, GetBlockOffset(BelugaBlockIndex.CaptureRecord));
FashionPlayer = new Fashion7b(sav, GetBlockOffset(BelugaBlockIndex.FashionPlayer));
FashionStarter = new Fashion7b(sav, GetBlockOffset(BelugaBlockIndex.FashionStarter));
Park = new GoParkStorage(sav, sav.Blocks.GetBlockOffset(BelugaBlockIndex.GoParkEntities));
PlayerGeoLocation = new PlayerGeoLocation7b(sav, GetBlockOffset(BelugaBlockIndex.PlayerGeoLocation));
}
@ -67,6 +68,7 @@ public sealed class SaveBlockAccessor7b : ISaveBlockAccessor<BlockInfo7b>, ISave
public CaptureRecords Captured { get; }
public Fashion7b FashionPlayer { get; }
public Fashion7b FashionStarter { get; }
public GoParkStorage Park { get; }
public PlayerGeoLocation7b PlayerGeoLocation { get; }
public BlockInfo GetBlock(BelugaBlockIndex index) => BlockInfo[(int)index];
public int GetBlockOffset(BelugaBlockIndex index) => GetBlock(index).Offset;

View file

@ -5,20 +5,16 @@ namespace PKHeX.Core;
/// <summary>
/// Base class for a savegame data reader.
/// </summary>
public abstract class SaveBlock<T> : IDataIndirect where T : SaveFile
public abstract class SaveBlock<T>(T sav, byte[] data, int offset = 0) : IDataIndirect where T : SaveFile
{
protected readonly T SAV;
protected readonly T SAV = sav;
[Browsable(false)] public byte[] Data { get; }
[Browsable(false)] public int Offset { get; protected init; }
[Browsable(false)] public byte[] Data { get; } = data;
[Browsable(false)] public int Offset { get; protected init; } = offset;
protected SaveBlock(T sav) : this(sav, sav.Data) { }
protected SaveBlock(T sav, byte[] data)
{
SAV = sav;
Data = data;
}
protected SaveBlock(T sav, int offset) : this(sav, sav.Data, offset) { }
}
public interface IDataIndirect

View file

@ -213,7 +213,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37
public int GTS { get; protected set; } = int.MinValue;
public int ChatterOffset { get; protected set; } = int.MinValue;
public Chatter4 Chatter => new(this);
public Chatter4 Chatter => new(this, ChatterOffset);
// Storage
public override int PartyCount

View file

@ -61,6 +61,7 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray
public PokeListHeader Storage => Blocks.Storage;
public WB7Records GiftRecords => Blocks.GiftRecords;
public CaptureRecords Captured => Blocks.Captured;
public GoParkStorage Park => Blocks.Park;
public PlayerGeoLocation7b PlayerGeoLocation => Blocks.PlayerGeoLocation;
public override IReadOnlyList<InventoryPouch> Inventory { get => Blocks.Items.Inventory; set => Blocks.Items.Inventory = value; }

View file

@ -6,10 +6,8 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 4 Chatter Recording
/// </summary>
public sealed class Chatter4: SaveBlock<SAV4>, IChatter
public sealed class Chatter4(SAV4 SAV, int offset) : SaveBlock<SAV4>(SAV, offset), IChatter
{
public Chatter4(SAV4 SAV) : base(SAV) => Offset = SAV.ChatterOffset;
public bool Initialized
{
get => ReadUInt32LittleEndian(SAV.General[Offset..]) == 1u;

View file

@ -1,13 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class BattleSubway5 : SaveBlock<SAV5>
public sealed class BattleSubway5(SAV5 sav, int offset) : SaveBlock<SAV5>(sav, offset)
{
public BattleSubway5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
public BattleSubway5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
private Span<byte> Raw => Data.AsSpan(Offset);
public int BP { get => ReadUInt16LittleEndian(Raw); set => WriteUInt16LittleEndian(Raw, (ushort)value); }

View file

@ -2,11 +2,8 @@ using System;
namespace PKHeX.Core;
public sealed class BoxLayout5 : SaveBlock<SAV5>
public sealed class BoxLayout5(SAV5 sav, int offset) : SaveBlock<SAV5>(sav, offset)
{
public BoxLayout5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
public BoxLayout5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public int CurrentBox { get => Data[Offset]; set => Data[Offset] = (byte)value; }
public int GetBoxNameOffset(int box) => Offset + (0x28 * box) + 4;
public int GetBoxWallpaperOffset(int box) => Offset + 0x3C4 + box;

View file

@ -6,10 +6,8 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 5 Chatter Recording
/// </summary>
public sealed class Chatter5 : SaveBlock<SAV5>, IChatter
public sealed class Chatter5(SAV5 SAV, int offset) : SaveBlock<SAV5>(SAV, offset), IChatter
{
public Chatter5(SAV5 SAV, int offset) : base(SAV) => Offset = offset;
public bool Initialized
{
get => ReadUInt32LittleEndian(Data.AsSpan(Offset)) == 1u;

View file

@ -3,9 +3,9 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class Daycare5 : SaveBlock<SAV5>
public sealed class Daycare5(SAV5 sav, int offset) : SaveBlock<SAV5>(sav, offset)
{
// struct daycareSlot
// struct daycareSlot
// bool32 occupied
// pk5 (party sized) pk
// u32 expGained
@ -17,8 +17,6 @@ public sealed class Daycare5 : SaveBlock<SAV5>
public const int DaycareSeedSize = 16; // 8 bytes, B2/W2 only
public Daycare5(SAV5 sav, int offset) : base(sav) => Offset = offset;
public ulong? GetSeed()
{
if (SAV is not SAV5B2W2)

View file

@ -3,9 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public abstract class Encount5 : SaveBlock<SAV5>
public abstract class Encount5(SAV5 SAV, int offset) : SaveBlock<SAV5>(SAV, offset)
{
protected Encount5(SAV5 SAV, int offset) : base(SAV) => Offset = offset;
public ushort LastLocation { get => ReadUInt16LittleEndian(Data); set => WriteUInt16LittleEndian(Data, value); }
public ushort CaptureUnknown { get => ReadUInt16LittleEndian(Data.AsSpan()[0x02..]); set => WriteUInt16LittleEndian(Data.AsSpan()[0x02..], value); }

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public abstract class Entralink5 : SaveBlock<SAV5>
public abstract class Entralink5(SAV5 SAV, int offset) : SaveBlock<SAV5>(SAV, offset)
{
protected Entralink5(SAV5 SAV, int offset) : base(SAV) => Offset = offset;
public ushort WhiteForestLevel
{
get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x0C));

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class FestaBlock5 : SaveBlock<SAV5B2W2>
public sealed class FestaBlock5(SAV5B2W2 SAV, int offset) : SaveBlock<SAV5B2W2>(SAV, offset)
{
public FestaBlock5(SAV5B2W2 SAV, int offset) : base(SAV) => Offset = offset;
public const ushort MaxScore = 9999;
public const int FunfestFlag = 2438;

View file

@ -7,10 +7,8 @@ public sealed class MedalList5 : SaveBlock<SAV5B2W2>
private const int MAX_MEDALS = 255;
private readonly Medal5[] Medals;
public MedalList5(SAV5B2W2 SAV, int offset) : base(SAV)
public MedalList5(SAV5B2W2 SAV, int offset) : base(SAV, offset)
{
Offset = offset;
var memory = Data.AsMemory(Offset, MAX_MEDALS * Medal5.SIZE);
Medals = GetMedals(memory);
}

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public abstract class Misc5 : SaveBlock<SAV5>, IGymTeamInfo
public abstract class Misc5(SAV5 sav, int offset) : SaveBlock<SAV5>(sav, offset), IGymTeamInfo
{
protected Misc5(SAV5 sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
get => ReadUInt32LittleEndian(Data.AsSpan(Offset));

View file

@ -1,10 +1,7 @@
namespace PKHeX.Core;
public sealed class Musical5 : SaveBlock<SAV5>
public sealed class Musical5(SAV5 SAV, int offset) : SaveBlock<SAV5>(SAV, offset)
{
public Musical5(SAV5BW SAV, int offset) : base(SAV) => Offset = offset;
public Musical5(SAV5B2W2 SAV, int offset) : base(SAV) => Offset = offset;
private const int PropOffset = 0x258;
public void UnlockAllMusicalProps()

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class MyItem5B2W2 : MyItem
public sealed class MyItem5B2W2(SAV5B2W2 SAV, int offset) : MyItem(SAV, offset)
{
// offsets/pouch sizes are the same for both B/W and B2/W2, but Key Item permissions are different
private const int HeldItem = 0x000; // 0
@ -10,7 +10,6 @@ public sealed class MyItem5B2W2 : MyItem
private const int TMHM = 0x624; // 2
private const int Medicine = 0x7D8; // 3
private const int Berry = 0x898; // 4
public MyItem5B2W2(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
public override IReadOnlyList<InventoryPouch> Inventory
{

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class MyItem5BW : MyItem
public sealed class MyItem5BW(SAV5BW SAV, int offset) : MyItem(SAV, offset)
{
// offsets/pouch sizes are the same for both B/W and B2/W2, but Key Item permissions are different
private const int HeldItem = 0x000; // 0
@ -11,8 +11,6 @@ public sealed class MyItem5BW : MyItem
private const int Medicine = 0x7D8; // 3
private const int Berry = 0x898; // 4
public MyItem5BW(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
public override IReadOnlyList<InventoryPouch> Inventory
{
get

View file

@ -3,7 +3,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class MysteryBlock5 : SaveBlock<SAV5>
public sealed class MysteryBlock5(SAV5 sav, int offset) : SaveBlock<SAV5>(sav, offset)
{
private const int FlagStart = 0;
private const int MaxReceivedFlag = 2048;
@ -15,8 +15,6 @@ public sealed class MysteryBlock5 : SaveBlock<SAV5>
private int SeedOffset => Offset + DataSize;
// Everything is stored encrypted, and only decrypted on demand. Only crypt on object fetch...
public MysteryBlock5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
public MysteryBlock5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public EncryptedMysteryGiftAlbum GiftAlbum
{

View file

@ -1,12 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class PWTBlock5 : SaveBlock<SAV5B2W2>
public sealed class PWTBlock5(SAV5B2W2 sav, int offset) : SaveBlock<SAV5B2W2>(sav, offset)
{
public PWTBlock5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public ushort GetPWTRecord(int id) => GetPWTRecord((PWTRecordID)id);
public ushort GetPWTRecord(PWTRecordID id)

View file

@ -6,11 +6,8 @@ namespace PKHeX.Core;
/// <summary>
/// Combined save block; 0x100 for first, 0x100 for second.
/// </summary>
public sealed class PlayerData5 : SaveBlock<SAV5>
public sealed class PlayerData5(SAV5 sav, int offset) : SaveBlock<SAV5>(sav, offset)
{
public PlayerData5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
public PlayerData5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
private Span<byte> OriginalTrainerTrash => Data.AsSpan(Offset + 4, 0x10);
public string OT

View file

@ -2,7 +2,7 @@ using System;
namespace PKHeX.Core;
public sealed class UnityTower5 : SaveBlock<SAV5>
public sealed class UnityTower5(SAV5 SAV, int offset) : SaveBlock<SAV5>(SAV, offset)
{
private const int CountryCount = 232;
@ -50,9 +50,6 @@ public sealed class UnityTower5 : SaveBlock<SAV5>
Red = 3, // own registered location
}
public UnityTower5(SAV5BW SAV, int offset) : base(SAV) => Offset = offset;
public UnityTower5(SAV5B2W2 SAV, int offset) : base(SAV) => Offset = offset;
private const int UnityTowerOffset = 0x320;
private const int GeonetGlobalFlagOffset = 0x344;
private const int UnityTowerFlagOffset = 0x345;

View file

@ -1,9 +1,9 @@
namespace PKHeX.Core;
namespace PKHeX.Core;
public sealed class BattleBox6 : SaveBlock<SAV6>
{
public BattleBox6(SAV6XY SAV, int offset) : base(SAV) => Offset = offset;
public BattleBox6(SAV6AO SAV, int offset) : base(SAV) => Offset = offset;
public BattleBox6(SAV6XY SAV, int offset) : base(SAV, offset) { }
public BattleBox6(SAV6AO SAV, int offset) : base(SAV, offset) { }
private int LockedFlagOffset => Offset + (6 * PokeCrypto.SIZE_6STORED);

View file

@ -19,8 +19,8 @@ public sealed class BoxLayout6 : SaveBlock<SAV6>, IBoxDetailName, IBoxDetailWall
private const int Unlocked = PCFlags + 1; // 0x43E;
private const int LastViewedBoxOffset = Unlocked + 1; // 0x43F;
public BoxLayout6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public BoxLayout6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public BoxLayout6(SAV6XY sav, int offset) : base(sav, offset) { }
public BoxLayout6(SAV6AO sav, int offset) : base(sav, offset) { }
public int GetBoxWallpaperOffset(int box) => Offset + PCBackgrounds + box;

View file

@ -19,8 +19,8 @@ public sealed class ConfigSave6 : SaveBlock<SAV6>
* unknown:14 19..31
*/
public ConfigSave6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public ConfigSave6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public ConfigSave6(SAV6XY sav, int offset) : base(sav, offset) { }
public ConfigSave6(SAV6AO sav, int offset) : base(sav, offset) { }
public int ConfigValue
{

View file

@ -9,8 +9,8 @@ namespace PKHeX.Core;
/// </summary>
public sealed class Encount6 : SaveBlock<SAV6>
{
public Encount6(SAV6XY SAV, int offset) : base(SAV) => Offset = offset;
public Encount6(SAV6AO SAV, int offset) : base(SAV) => Offset = offset;
public Encount6(SAV6XY SAV, int offset) : base(SAV, offset) { }
public Encount6(SAV6AO SAV, int offset) : base(SAV, offset) { }
public ushort RepelItemUsed { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x00), value); }
public byte RepelSteps { get => Data[Offset + 0x02]; set => Data[Offset + 0x02] = value; }

View file

@ -2,10 +2,8 @@ using System;
namespace PKHeX.Core;
public sealed class Fashion6XY : SaveBlock<SAV6XY>
public sealed class Fashion6XY(SAV6XY sav, int offset) : SaveBlock<SAV6XY>(sav, offset)
{
public Fashion6XY(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public void UnlockAllAccessories()
{
SAV.SetData(AllAccessories, Offset);

View file

@ -1,12 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class GameTime6 : SaveBlock<SAV6>
public sealed class GameTime6(SAV6 sav, int offset) : SaveBlock<SAV6>(sav, offset)
{
public GameTime6(SAV6 sav, int offset) : base(sav) => Offset = offset;
public int ResumeYear { get => ReadInt32LittleEndian(Data.AsSpan(Offset + 0x4)); set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x4), value); }
public int ResumeMonth { get => Data[Offset + 0x8]; set => Data[Offset + 0x8] = (byte)value; }
public int ResumeDay { get => Data[Offset + 0x9]; set => Data[Offset + 0x9] = (byte)value; }

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class ItemInfo6 : SaveBlock<SAV6>
public sealed class ItemInfo6(SAV6 sav, int offset) : SaveBlock<SAV6>(sav, offset)
{
public ItemInfo6(SAV6 sav, int offset) : base(sav) => Offset = offset;
private const int BoundItemCount = 4;
private const int RecentItemCount = 12;

View file

@ -5,8 +5,8 @@ namespace PKHeX.Core;
public sealed class LinkBlock6 : SaveBlock<SAV6>
{
public LinkBlock6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public LinkBlock6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public LinkBlock6(SAV6XY sav, int offset) : base(sav, offset) { }
public LinkBlock6(SAV6AO sav, int offset) : base(sav, offset) { }
public byte[] GetLinkInfoData() => Data.AsSpan(Offset + 0x1FF, PL6.Size).ToArray();
public PL6 GetLinkInfo() => new(GetLinkInfoData());

View file

@ -1,12 +1,12 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class MaisonBlock : SaveBlock<SAV6>
{
public MaisonBlock(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public MaisonBlock(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public MaisonBlock(SAV6XY sav, int offset) : base(sav, offset) { }
public MaisonBlock(SAV6AO sav, int offset) : base(sav, offset) { }
// 5 * [u16*4: normal,super,normalStreak,superStreak]
public const int MaisonStatCount = 20;

View file

@ -1,4 +1,4 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
@ -10,8 +10,8 @@ public interface IMisc6
public sealed class Misc6AO : SaveBlock<SAV6>, IMisc6
{
public Misc6AO(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public Misc6AO(SAV6AODemo sav, int offset) : base(sav) => Offset = offset;
public Misc6AO(SAV6AO sav, int offset) : base(sav, offset) { }
public Misc6AO(SAV6AODemo sav, int offset) : base(sav, offset) { }
public uint Money
{

View file

@ -1,12 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class Misc6XY : SaveBlock<SAV6XY>, IMisc6
public sealed class Misc6XY(SAV6XY sav, int offset) : SaveBlock<SAV6XY>(sav, offset), IMisc6
{
public Misc6XY(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x8));

View file

@ -10,8 +10,8 @@ public sealed class MyItem6AO : MyItem
private const int Medicine = 0x970; // 3, +2 items shift because 2 HMs added
private const int Berry = 0xA70; // 4
public MyItem6AO(SAV6AO SAV, int offset) : base(SAV) => Offset = offset;
public MyItem6AO(SAV6AODemo SAV, int offset) : base(SAV) => Offset = offset;
public MyItem6AO(SAV6AO SAV, int offset) : base(SAV, offset) { }
public MyItem6AO(SAV6AODemo SAV, int offset) : base(SAV, offset) { }
public override IReadOnlyList<InventoryPouch> Inventory
{

View file

@ -2,15 +2,13 @@ using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class MyItem6XY : MyItem
public sealed class MyItem6XY(SAV6XY SAV, int offset) : MyItem(SAV, offset)
{
private const int HeldItem = 0; // 0
private const int KeyItem = 0x640; // 1
private const int TMHM = 0x7C0; // 2
private const int HeldItem = 0; // 0
private const int KeyItem = 0x640; // 1
private const int TMHM = 0x7C0; // 2
private const int Medicine = 0x968; // 3
private const int Berry = 0xA68; // 4
public MyItem6XY(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
private const int Berry = 0xA68; // 4
public override IReadOnlyList<InventoryPouch> Inventory
{

View file

@ -6,10 +6,8 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 6 savedata object that stores the player's trainer data.
/// </summary>
public class MyStatus6 : SaveBlock<SAV6>, IRegionOrigin
public class MyStatus6(SAV6 sav, int offset) : SaveBlock<SAV6>(sav, offset), IRegionOrigin
{
public MyStatus6(SAV6 sav, int offset) : base(sav) => Offset = offset;
public uint ID32
{
get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0));

View file

@ -10,8 +10,8 @@ public sealed class MysteryBlock6 : SaveBlock<SAV6>
// private const int FlagRegionSize = (MaxReceivedFlag / 8); // 0x100
private const int CardStart = FlagStart + (MaxReceivedFlag / 8);
public MysteryBlock6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public MysteryBlock6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public MysteryBlock6(SAV6XY sav, int offset) : base(sav, offset) { }
public MysteryBlock6(SAV6AO sav, int offset) : base(sav, offset) { }
public bool[] GetReceivedFlags() => FlagUtil.GetBitFlagArray(Data.AsSpan(Offset + FlagStart), MaxReceivedFlag);

View file

@ -32,8 +32,8 @@ public sealed class OPower6 : SaveBlock<SAV6>
new(3, Accuracy) {Offset = 62},
];
public OPower6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public OPower6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public OPower6(SAV6XY sav, int offset) : base(sav, offset) { }
public OPower6(SAV6AO sav, int offset) : base(sav, offset) { }
private static OPowerFlagSet Get(OPower6Type type) => Array.Find(Mapping, t => t.Identifier == type) ?? throw new ArgumentOutOfRangeException(nameof(type));
public static int GetOPowerCount(OPower6Type type) => Get(type).BaseCount;

View file

@ -5,8 +5,8 @@ namespace PKHeX.Core;
public sealed class PlayTime6 : SaveBlock<SaveFile>
{
public PlayTime6(SAV6 sav, int offset) : base(sav) => Offset = offset;
public PlayTime6(SAV7 sav, int offset) : base(sav) => Offset = offset;
public PlayTime6(SAV6 sav, int offset) : base(sav, offset) { }
public PlayTime6(SAV7 sav, int offset) : base(sav, offset) { }
public int PlayedHours
{

View file

@ -3,13 +3,11 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class Puff6 : SaveBlock<SAV6>
public sealed class Puff6(SAV6 SAV, int offset) : SaveBlock<SAV6>(SAV, offset)
{
private const byte MaxPuffID = 26; // Supreme Winter Poké Puff
private const int PuffSlots = 100;
public Puff6(SAV6 SAV, int offset) : base(SAV) => Offset = offset;
public Span<byte> GetPuffs() => SAV.Data.AsSpan(Offset, PuffSlots);
public void SetPuffs(ReadOnlySpan<byte> value) => SAV.SetData(value, Offset);

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class SangoInfoBlock : SaveBlock<SAV6AO>
public sealed class SangoInfoBlock(SAV6AO SAV, int offset) : SaveBlock<SAV6AO>(SAV, offset)
{
public SangoInfoBlock(SAV6AO SAV, int offset) : base(SAV) => Offset = offset;
private const uint EON_MAGIC = WC6.EonTicketConst;
public uint EonTicketReceivedMagic // 0x319B8

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class SecretBase6Block : SaveBlock<SAV6AO>
public sealed class SecretBase6Block(SAV6AO sav, int offset) : SaveBlock<SAV6AO>(sav, offset)
{
public SecretBase6Block(SAV6AO sav, int offset) : base(sav) => Offset = offset;
// structure: 0x7AD0 bytes total
// [0000-031F] SecretBaseGoodStock[200] (800 bytes)
// [0320-0321] u16 SecretBaseSelfLocation (-1 if not created)

View file

@ -1,12 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class Situation6 : SaveBlock<SAV6>
public sealed class Situation6(SAV6 SAV, int offset) : SaveBlock<SAV6>(SAV, offset)
{
public Situation6(SAV6 SAV, int offset) : base(SAV) => Offset = offset;
public int M
{
get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x02));

View file

@ -6,10 +6,8 @@ namespace PKHeX.Core;
/// <summary>
/// SUBE block that stores in-game event results.
/// </summary>
public abstract class SubEventLog6 : SaveBlock<SAV6>, IGymTeamInfo
public abstract class SubEventLog6(SAV6 sav, int offset) : SaveBlock<SAV6>(sav, offset), IGymTeamInfo
{
protected SubEventLog6(SAV6 sav, int offset) : base(sav) => Offset = offset;
protected abstract int BadgeVictoryOffset { get; }
/// <summary>

View file

@ -5,8 +5,8 @@ namespace PKHeX.Core;
public sealed class SuperTrainBlock : SaveBlock<SAV6>
{
public SuperTrainBlock(SAV6XY sav, int offset) : base(sav) => Offset = offset;
public SuperTrainBlock(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public SuperTrainBlock(SAV6XY sav, int offset) : base(sav, offset) { }
public SuperTrainBlock(SAV6AO sav, int offset) : base(sav, offset) { }
// Structure:
// 6 bytes stage unlock flags

View file

@ -1,11 +1,9 @@
using System;
using System;
namespace PKHeX.Core;
public sealed class BattleAgency7 : SaveBlock<SAV7USUM>
public sealed class BattleAgency7(SAV7USUM sav, int offset) : SaveBlock<SAV7USUM>(sav, offset)
{
public BattleAgency7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int GetSlotOffset(int slot) => Offset + slot switch
{
0 => 0,

View file

@ -4,11 +4,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class BattleTree7 : SaveBlock<SAV7>
public sealed class BattleTree7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public BattleTree7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public BattleTree7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public const int BattleTypeMax = 4;
public int GetTreeStreak(int battletype, bool super, bool max)

View file

@ -3,7 +3,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class BoxLayout7 : SaveBlock<SAV7>, IBoxDetailName, IBoxDetailWallpaper, ITeamIndexSet
public sealed class BoxLayout7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset), IBoxDetailName, IBoxDetailWallpaper, ITeamIndexSet
{
private const int BoxCount = 32;
@ -19,9 +19,6 @@ public sealed class BoxLayout7 : SaveBlock<SAV7>, IBoxDetailName, IBoxDetailWall
private const int NONE_SELECTED = -1;
public readonly int[] TeamSlots = new int[TeamCount * 6];
public BoxLayout7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public BoxLayout7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int GetBoxWallpaperOffset(int box) => Offset + PCBackgrounds + box;
public int GetBoxWallpaper(int box)

View file

@ -3,7 +3,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class ConfigSave7 : SaveBlock<SAV7>
public sealed class ConfigSave7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
/* ===32 bits===
* talkSpeed:2 0,1
@ -15,9 +15,6 @@ public sealed class ConfigSave7 : SaveBlock<SAV7>
* everything else: unknown
*/
public ConfigSave7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public ConfigSave7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int ConfigValue
{
get => ReadInt32LittleEndian(Data.AsSpan(Offset));

View file

@ -2,13 +2,10 @@ using System;
namespace PKHeX.Core;
public sealed class Daycare7 : SaveBlock<SAV7>
public sealed class Daycare7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public const int DaycareSeedSize = 32; // 128 bits
public Daycare7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public Daycare7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public bool GetIsOccupied(int slot)
{
return Data[Offset + ((PokeCrypto.SIZE_6STORED + 1) * slot)] != 0;

View file

@ -2,11 +2,8 @@ using System;
namespace PKHeX.Core;
public sealed class FashionBlock7 : SaveBlock<SAV7>
public sealed class FashionBlock7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public FashionBlock7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public FashionBlock7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
private const int FashionLength = 0x1A08;
public FashionItem7[] Wardrobe

View file

@ -3,11 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class FieldMenu7 : SaveBlock<SAV7>
public sealed class FieldMenu7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public FieldMenu7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public FieldMenu7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
// US/UM ONLY
public ushort RotomAffection
{

View file

@ -3,11 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class FieldMoveModelSave7 : SaveBlock<SAV7>
public sealed class FieldMoveModelSave7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public FieldMoveModelSave7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public FieldMoveModelSave7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
//public int Unknown { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x00), (ushort)value); } // related to Ride Pokémon
public float X { get => ReadSingleLittleEndian(Data.AsSpan(Offset + 0x08)); set => WriteSingleLittleEndian(Data.AsSpan(Offset + 0x08), value); }
public float Z { get => ReadSingleLittleEndian(Data.AsSpan(Offset + 0x0C)); set => WriteSingleLittleEndian(Data.AsSpan(Offset + 0x0C), value); }

View file

@ -1,11 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class GameTime7 : SaveBlock<SAV7>
public sealed class GameTime7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public GameTime7(SAV7 sav, int offset) : base(sav) => Offset = offset;
public int ResumeYear { get => ReadInt32LittleEndian(Data.AsSpan(Offset + 0x4)); set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x4), value); }
public int ResumeMonth { get => Data[Offset + 0x8]; set => Data[Offset + 0x8] = (byte)value; }
public int ResumeDay { get => Data[Offset + 0x9]; set => Data[Offset + 0x9] = (byte)value; }

View file

@ -1,13 +1,10 @@
using System;
using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class HallOfFame7 : SaveBlock<SAV7>
public sealed class HallOfFame7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public HallOfFame7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public HallOfFame7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
// this HoF region is immediately after the Event Flags
private const int MaxCount = 12;
public int First1 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x00), (ushort)value); }

View file

@ -3,11 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class JoinFesta7 : SaveBlock<SAV7>
public sealed class JoinFesta7(SAV7 sav, int offset) : SaveBlock<SAV7>(sav, offset)
{
public JoinFesta7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
public JoinFesta7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int FestaCoins
{
get => ReadInt32LittleEndian(Data.AsSpan(Offset + 0x508));

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class CaptureRecords : SaveBlock<SAV7b>
public sealed class CaptureRecords(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public CaptureRecords(SAV7b sav, int offset) : base(sav) => Offset = offset;
private const int ENTRY_COUNT = 153;
private const int MAX_COUNT_ENTRY_CAPTURE = 9_999;
private const int MAX_COUNT_ENTRY_TRANSFER = 999_999_999;

View file

@ -3,7 +3,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class ConfigSave7b : SaveBlock<SAV7b>
public sealed class ConfigSave7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
/* ===First 8 bits===
* talkSpeed:2
@ -14,8 +14,6 @@ public sealed class ConfigSave7b : SaveBlock<SAV7b>
* everything else: unknown
*/
public ConfigSave7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public int ConfigValue
{
get => ReadInt32LittleEndian(Data.AsSpan(Offset));

View file

@ -6,10 +6,8 @@ namespace PKHeX.Core;
/// <summary>
/// Stores the position of the player.
/// </summary>
public sealed class Coordinates7b : SaveBlock<SAV7b>
public sealed class Coordinates7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public Coordinates7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
// Position
public float X { get => ReadSingleLittleEndian(Data.AsSpan(Offset + 0x10)); set => WriteSingleLittleEndian(Data.AsSpan(Offset + 0x10), value); }
public float Z { get => ReadSingleLittleEndian(Data.AsSpan(Offset + 0x14)); set => WriteSingleLittleEndian(Data.AsSpan(Offset + 0x14), value); }

View file

@ -3,21 +3,17 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class EventWork7b : SaveBlock<SAV7b>, IEventVar<int>
public sealed class EventWork7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset), IEventVar<int>
{
public EventWork7b(SAV7b sav, int offset) : base(sav)
{
Offset = offset;
// Zone @ 0x21A0 - 0x21AF (128 flags)
// System @ 0x21B0 - 0x21EF (512 flags) -- is this really 256 instead, with another 256 region after for the small vanish?
// Vanish @ 0x21F0 - 0x22AF (1536 flags)
// Event @ 0x22B0 - 0x23A7 (rest of the flags) (512) -- I think trainer flags are afterward.... For now, this is a catch-all
// Zone @ 0x21A0 - 0x21AF (128 flags)
// System @ 0x21B0 - 0x21EF (512 flags) -- is this really 256 instead, with another 256 region after for the small vanish?
// Vanish @ 0x21F0 - 0x22AF (1536 flags)
// Event @ 0x22B0 - 0x23A7 (rest of the flags) (512) -- I think trainer flags are afterward.... For now, this is a catch-all
// time flags (39 used flags of 42) = 6 bytes 0x22F0-0x22F5
// trainer flags (???) = 0x22F6 - end?
// time flags (39 used flags of 42) = 6 bytes 0x22F0-0x22F5
// trainer flags (???) = 0x22F6 - end?
// Title flags @ 0x2498 - 0x24AB (160 flags): unlocked Master Trainer Titles (last 4 unused)
}
// Title flags @ 0x2498 - 0x24AB (160 flags): unlocked Master Trainer Titles (last 4 unused)
// Overall Layout
private const int WorkCount = 1000;

View file

@ -2,10 +2,8 @@ using System;
namespace PKHeX.Core;
public sealed class Fashion7b : SaveBlock<SAV7b>
public sealed class Fashion7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public Fashion7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public void UnlockAllAccessoriesPlayer()
{
SAV.SetData(AllAccessoriesPlayer, Offset);

View file

@ -4,13 +4,8 @@ using System.Diagnostics;
namespace PKHeX.Core;
public sealed class GoParkStorage : SaveBlock<SAV7b>, IEnumerable<GP1>
public sealed class GoParkStorage(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset), IEnumerable<GP1>
{
public GoParkStorage(SAV7b sav) : base(sav)
{
Offset = sav.Blocks.GetBlockOffset(BelugaBlockIndex.GoParkEntities);
}
public const int SlotsPerArea = 50;
public const int Areas = 20;
public const int Count = SlotsPerArea * Areas; // 1000

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class Misc7b : SaveBlock<SAV7b>
public sealed class Misc7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public Misc7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 4));

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class MyItem7b : MyItem
public sealed class MyItem7b(SAV7b sav, int offset) : MyItem(sav, offset)
{
private const int Medicine = 0x0000; // 0
private const int TM = 0x00F0; // 1
@ -12,8 +12,6 @@ public sealed class MyItem7b : MyItem
private const int Battle = 0x08E0; // 5
private const int Key = 0x0B38; // 6
public MyItem7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public override IReadOnlyList<InventoryPouch> Inventory
{
get

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class MyStatus7b : SaveBlock<SAV7b>
public sealed class MyStatus7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public MyStatus7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
// Player Information
// idb uint8 offset: 0x58

View file

@ -3,10 +3,8 @@ using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
public sealed class PlayTime7b : SaveBlock<SAV7b>
public sealed class PlayTime7b(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public PlayTime7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public int PlayedHours
{
get => ReadUInt16LittleEndian(Data.AsSpan(Offset));

View file

@ -25,9 +25,8 @@ public sealed class PokeListHeader : SaveBlock<SAV7b>
private const int MAX_SLOTS = 1000;
private const int SLOT_EMPTY = 1001;
public PokeListHeader(SAV7b sav, int offset) : base(sav)
public PokeListHeader(SAV7b sav, int offset) : base(sav, offset)
{
Offset = offset;
var info = PokeListInfo = LoadPointerData();
if (!sav.State.Exportable)
{

View file

@ -2,10 +2,8 @@ using System;
namespace PKHeX.Core;
public sealed class WB7Records : SaveBlock<SAV7b>
public sealed class WB7Records(SAV7b sav, int offset) : SaveBlock<SAV7b>(sav, offset)
{
public WB7Records(SAV7b sav, int offset) : base(sav) => Offset = offset;
private const int RecordMax = 10; // 0xE90 > (0x140 * 0xA = 0xC80), not sure what final 0x210 bytes are used for
private const int FlagCountMax = 0x1C00; // (7168) end of the block?

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class MyItem7SM : MyItem
public sealed class MyItem7SM(SAV7SM SAV, int offset) : MyItem(SAV, offset)
{
private const int HeldItem = 0; // 430 (Case 0)
private const int KeyItem = HeldItem + (4 * 430); // 184 (Case 4)
@ -11,8 +11,6 @@ public sealed class MyItem7SM : MyItem
private const int Berry = Medicine + (4 * 64); // 72 (Case 3)
private const int ZCrystals = Berry + (4 * 72); // 30 (Case 5)
public MyItem7SM(SAV7SM SAV, int offset) : base(SAV) => Offset = offset;
public override IReadOnlyList<InventoryPouch> Inventory
{
get

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class MyItem7USUM : MyItem
public sealed class MyItem7USUM(SAV7USUM SAV, int offset) : MyItem(SAV, offset)
{
private const int HeldItem = 0; // 427 (Case 0)
private const int KeyItem = HeldItem + (4 * 427); // 198 (Case 4)
@ -12,8 +12,6 @@ public sealed class MyItem7USUM : MyItem
private const int ZCrystals = Berry + (4 * 67); // 35 (Case 5)
private const int BattleItems = ZCrystals + (4 * 35); // 11 (Case 6)
public MyItem7USUM(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
public override IReadOnlyList<InventoryPouch> Inventory
{
get

View file

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

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(SaveFile SAV, SCBlock block) : MyItem(SAV, block.Data)
public sealed class MyItem9(SAV9SV sav, SCBlock block) : MyItem(sav, block.Data)
{
public const int ItemSaveSize = 3000;

View file

@ -7,4 +7,5 @@ public abstract class MyItem : SaveBlock<SaveFile>
public abstract IReadOnlyList<InventoryPouch> Inventory { get; set; }
protected MyItem(SaveFile SAV) : base(SAV) { }
protected MyItem(SaveFile SAV, byte[] data) : base(SAV, data) { }
protected MyItem(SaveFile SAV, int offset) : base(SAV, offset) { }
}

View file

@ -18,7 +18,7 @@ public partial class SAV_Trainer7GG : Form
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
SAV = (SAV7b)(Origin = sav).Clone();
Park = new GoParkStorage(SAV);
Park = SAV.Park;
UpdateGoSummary(0);
if (Main.Unicode)