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.
65 lines
4.1 KiB
C#
65 lines
4.1 KiB
C#
using System;
|
||
using System.ComponentModel;
|
||
using static System.Buffers.Binary.BinaryPrimitives;
|
||
|
||
namespace PKHeX.Core
|
||
{
|
||
/// <summary>
|
||
/// Details about the Console and specific timestamps.
|
||
/// </summary>
|
||
/// <remarks>size: 0x138</remarks>
|
||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||
public sealed class SystemData8b : SaveBlock
|
||
{
|
||
// Structure:
|
||
// (u32 count, u64 FILETIME) Start Time
|
||
// (u32 count, u64 FILETIME) Latest Save Time
|
||
// (u32 count, u64 FILETIME) Penalty Timeout Time
|
||
// (u32 count, u64 FILETIME) Last Daily Event Time
|
||
// byte[208] ClockSnapshot (char[0x24])
|
||
// u32 "fd_bgmEvnet"
|
||
// s64[6] reserved
|
||
private const int SIZE_GMTIME = 12;
|
||
private const int SIZE_SNAPSHOT = 0xD0;
|
||
|
||
private const int OFS_SNAPSHOT = 4 + (3 * SIZE_GMTIME) + SIZE_GMTIME; // 0x34
|
||
private const int OFS_FDBGM = OFS_SNAPSHOT + SIZE_SNAPSHOT;
|
||
private const int OFS_RESERVED = OFS_FDBGM + 4;
|
||
private const int SIZE_TOTAL = OFS_RESERVED + (6 * 8); // 0x138
|
||
|
||
public SystemData8b(SAV8BS sav, int offset) : base(sav) => Offset = offset;
|
||
|
||
public uint CountStart { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0 + (0 * SIZE_GMTIME))); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0 + (0 * SIZE_GMTIME)), value); }
|
||
public long TicksStart { get => ReadInt64LittleEndian(Data.AsSpan(Offset + 4 + (0 * SIZE_GMTIME))); set => WriteInt64LittleEndian(Data.AsSpan(Offset + 4 + (0 * SIZE_GMTIME)), value); }
|
||
public uint CountLatest { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0 + (1 * SIZE_GMTIME))); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0 + (1 * SIZE_GMTIME)), value); }
|
||
public long TicksLatest { get => ReadInt64LittleEndian(Data.AsSpan(Offset + 4 + (1 * SIZE_GMTIME))); set => WriteInt64LittleEndian(Data.AsSpan(Offset + 4 + (1 * SIZE_GMTIME)), value); }
|
||
public uint CountPenalty { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0 + (2 * SIZE_GMTIME))); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0 + (2 * SIZE_GMTIME)), value); }
|
||
public long TicksPenalty { get => ReadInt64LittleEndian(Data.AsSpan(Offset + 4 + (2 * SIZE_GMTIME))); set => WriteInt64LittleEndian(Data.AsSpan(Offset + 4 + (2 * SIZE_GMTIME)), value); }
|
||
public uint CountDaily { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0 + (3 * SIZE_GMTIME))); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0 + (3 * SIZE_GMTIME)), value); }
|
||
public long TicksDaily { get => ReadInt64LittleEndian(Data.AsSpan(Offset + 4 + (3 * SIZE_GMTIME))); set => WriteInt64LittleEndian(Data.AsSpan(Offset + 4 + (3 * SIZE_GMTIME)), value); }
|
||
|
||
// byte[] nxSnapshot
|
||
// u32 fd_bgmEvnet
|
||
|
||
// THESE ARE IN UTC
|
||
public DateTime TimestampStart { get => DateTime.FromFileTimeUtc(TicksStart); set => TicksStart = value.ToFileTimeUtc(); }
|
||
public DateTime TimestampLatest { get => DateTime.FromFileTimeUtc(TicksLatest); set => TicksLatest = value.ToFileTimeUtc(); }
|
||
public DateTime TimestampPenalty { get => DateTime.FromFileTimeUtc(TicksPenalty); set => TicksPenalty = value.ToFileTimeUtc(); }
|
||
public DateTime TimestampDaily { get => DateTime.FromFileTimeUtc(TicksDaily); set => TicksDaily = value.ToFileTimeUtc(); }
|
||
|
||
public DateTime LocalTimestampStart { get => TimestampStart .ToLocalTime(); set => TimestampStart = value.ToUniversalTime(); }
|
||
public DateTime LocalTimestampLatest { get => TimestampLatest .ToLocalTime(); set => TimestampLatest = value.ToUniversalTime(); }
|
||
public DateTime LocalTimestampPenalty { get => TimestampPenalty.ToLocalTime(); set => TimestampPenalty = value.ToUniversalTime(); }
|
||
public DateTime LocalTimestampDaily { get => TimestampDaily .ToLocalTime(); set => TimestampDaily = value.ToUniversalTime(); }
|
||
|
||
public string LastSavedTime
|
||
{
|
||
get
|
||
{
|
||
var stamp = LocalTimestampLatest;
|
||
return $"{stamp.Year:0000}-{stamp.Month:00}-{stamp.Day:00} {stamp.Hour:00}ː{stamp.Minute:00}ː{stamp.Second:00}"; // not :
|
||
}
|
||
}
|
||
}
|
||
}
|