mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-05-21 05:09:35 -05:00
Existing `get`/`set` logic is flawed in that it doesn't work on Big Endian operating systems, and it allocates heap objects when it doesn't need to. `System.Buffers.Binary.BinaryPrimitives` in the `System.Memory` NuGet package provides both Little Endian and Big Endian methods to read and write data; all the `get`/`set` operations have been reworked to use this new API. This removes the need for PKHeX's manual `BigEndian` class, as all functions are already covered by the BinaryPrimitives API. The `StringConverter` has now been rewritten to accept a Span to read from & write to, no longer requiring a temporary StringBuilder. Other Fixes included: - The Super Training UI for Gen6 has been reworked according to the latest block structure additions. - Cloning a Stadium2 Save File now works correctly (opening from the Folder browser list). - Checksum & Sanity properties removed from parent PKM class, and is now implemented via interface.
111 lines
4.8 KiB
C#
111 lines
4.8 KiB
C#
using System;
|
|
using static System.Buffers.Binary.BinaryPrimitives;
|
|
|
|
namespace PKHeX.Core
|
|
{
|
|
public sealed class SecretBase6PKM : ISanityChecksum
|
|
{
|
|
public const int SIZE = 0x34;
|
|
public readonly byte[] Data;
|
|
|
|
public SecretBase6PKM(byte[] data) => Data = data;
|
|
public SecretBase6PKM() => Data = new byte[SIZE];
|
|
|
|
public uint EncryptionConstant
|
|
{
|
|
get => ReadUInt32LittleEndian(Data.AsSpan(0x00));
|
|
set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value);
|
|
}
|
|
|
|
public ushort Sanity
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x04));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value);
|
|
}
|
|
|
|
public ushort Checksum
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x06));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value);
|
|
}
|
|
|
|
public int Species
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x08));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x08), (ushort)value);
|
|
}
|
|
|
|
public int HeldItem
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x0A));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value);
|
|
}
|
|
|
|
public int Ability { get => Data[0x0C]; set => Data[0x0C] = (byte)value; }
|
|
public int AbilityNumber { get => Data[0x0D]; set => Data[0x0D] = (byte)value; }
|
|
|
|
public uint PID
|
|
{
|
|
get => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
|
set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value);
|
|
}
|
|
|
|
public int Nature { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
|
|
|
public bool FatefulEncounter { get => (Data[0x15] & 1) == 1; set => Data[0x15] = (byte)((Data[0x15] & ~0x01) | (value ? 1 : 0)); }
|
|
public int Gender { get => (Data[0x15] >> 1) & 0x3; set => Data[0x15] = (byte)((Data[0x15] & ~0x06) | (value << 1)); }
|
|
public int Form { get => Data[0x15] >> 3; set => Data[0x15] = (byte)((Data[0x15] & 0x07) | (value << 3)); }
|
|
|
|
public int EV_HP { get => Data[0x16]; set => Data[0x16] = (byte)value; }
|
|
public int EV_ATK { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
|
public int EV_DEF { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
|
public int EV_SPE { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
|
public int EV_SPA { get => Data[0x1A]; set => Data[0x1A] = (byte)value; }
|
|
public int EV_SPD { get => Data[0x1B]; set => Data[0x1B] = (byte)value; }
|
|
|
|
public int Move1
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x1C));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), (ushort)value);
|
|
}
|
|
|
|
public int Move2
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x1E));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), (ushort)value);
|
|
}
|
|
|
|
public int Move3
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x20));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x20), (ushort)value);
|
|
}
|
|
|
|
public int Move4
|
|
{
|
|
get => ReadUInt16LittleEndian(Data.AsSpan(0x22));
|
|
set => WriteUInt16LittleEndian(Data.AsSpan(0x22), (ushort)value);
|
|
}
|
|
|
|
public int Move1_PPUps { get => Data[0x24]; set => Data[0x24] = (byte)value; }
|
|
public int Move2_PPUps { get => Data[0x25]; set => Data[0x25] = (byte)value; }
|
|
public int Move3_PPUps { get => Data[0x26]; set => Data[0x26] = (byte)value; }
|
|
public int Move4_PPUps { get => Data[0x27]; set => Data[0x27] = (byte)value; }
|
|
|
|
// they messed up their bit struct and these ended up as individual fields? (5bits per byte)
|
|
public int IV_HP { get => Data[0x28]; set => Data[0x28] = (byte)value; }
|
|
public int IV_ATK { get => Data[0x29]; set => Data[0x29] = (byte)value; }
|
|
public int IV_DEF { get => Data[0x2A]; set => Data[0x2A] = (byte)value; }
|
|
public int IV_SPE { get => Data[0x2B]; set => Data[0x2B] = (byte)value; }
|
|
public int IV_SPA { get => Data[0x2C]; set => Data[0x2C] = (byte)value; }
|
|
public int IV_SPD { get => Data[0x2D] & 0x1F; set => Data[0x2D] = (byte)((Data[0x2D] & ~31) | value); }
|
|
public bool IsEgg { get => ((Data[0x2D] >> 5) & 1) == 1; set => Data[0x2D] = (byte)((Data[0x2D] & ~32) | (value ? 32 : 0)); }
|
|
public bool IsShiny { get => ((Data[0x2D] >> 5) & 1) == 1; set => Data[0x2D] = (byte)((Data[0x2D] & ~32) | (value ? 32 : 0)); }
|
|
|
|
public int CurrentFriendship { get => Data[0x2E]; set => Data[0x2E] = (byte)value; }
|
|
public int Ball { get => Data[0x2F]; set => Data[0x2F] = (byte)value; }
|
|
public int CurrentLevel { get => Data[0x30]; set => Data[0x30] = (byte)value; }
|
|
// 0x31,0x32,0x33 unused (alignment padding to u32)
|
|
}
|
|
}
|