mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-05-20 04:38:25 -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.
82 lines
2.1 KiB
C#
82 lines
2.1 KiB
C#
using System.Runtime.CompilerServices;
|
|
|
|
namespace PKHeX.Core
|
|
{
|
|
/// <summary>
|
|
/// Self-mutating value that returns a crypto value to be xor-ed with another (unaligned) byte stream.
|
|
/// <para>
|
|
/// This implementation allows for yielding crypto bytes on demand.
|
|
/// </para>
|
|
/// </summary>
|
|
public ref struct SCXorShift32
|
|
{
|
|
private int Counter;
|
|
private uint Seed;
|
|
|
|
public SCXorShift32(uint seed)
|
|
{
|
|
#if NET5
|
|
var pop_count = System.Numerics.BitOperations.PopCount(seed);
|
|
#else
|
|
var pop_count = PopCount(seed);
|
|
#endif
|
|
for (var i = 0; i < pop_count; i++)
|
|
seed = XorshiftAdvance(seed);
|
|
|
|
Counter = 0;
|
|
Seed = seed;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a <see cref="byte"/> from the current state.
|
|
/// </summary>
|
|
public uint Next()
|
|
{
|
|
var c = Counter;
|
|
var result = (Seed >> (c << 3)) & 0xFF;
|
|
if (c == 3)
|
|
{
|
|
Seed = XorshiftAdvance(Seed);
|
|
Counter = 0;
|
|
}
|
|
else
|
|
{
|
|
++Counter;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a <see cref="uint"/> from the current state.
|
|
/// </summary>
|
|
public uint Next32()
|
|
{
|
|
return Next() | (Next() << 8) | (Next() << 16) | (Next() << 24);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static uint XorshiftAdvance(uint key)
|
|
{
|
|
key ^= key << 2;
|
|
key ^= key >> 15;
|
|
key ^= key << 13;
|
|
return key;
|
|
}
|
|
|
|
#if !NET5
|
|
/// <summary>
|
|
/// Count of bits set in value
|
|
/// </summary>
|
|
private static uint PopCount(uint x)
|
|
{
|
|
x -= ((x >> 1) & 0x55555555u);
|
|
x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
|
|
x = (x + (x >> 4)) & 0x0F0F0F0Fu;
|
|
x += (x >> 8);
|
|
x += (x >> 16);
|
|
return x & 0x0000003Fu;
|
|
}
|
|
#endif
|
|
}
|
|
}
|