2024-06-10 06:33:46 +00:00
|
|
|
using System;
|
2021-05-14 23:32:26 +00:00
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
namespace PKHeX.Core;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 4-bit decimal encoding used by some Generation 1 save file values.
|
|
|
|
/// </summary>
|
|
|
|
public static class BinaryCodedDecimal
|
2021-05-14 23:32:26 +00:00
|
|
|
{
|
2024-06-10 06:33:46 +00:00
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
private static void PushDigits(ref uint result, uint b)
|
|
|
|
=> result = checked((result * 100) + (10 * (b >> 4)) + (b & 0xf));
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
private static byte GetLowestTuple(uint value)
|
|
|
|
=> (byte)((((value / 10) % 10) << 4) | (value % 10));
|
|
|
|
|
2021-05-14 23:32:26 +00:00
|
|
|
/// <summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
/// Returns a 32-bit signed integer converted from bytes in a Binary Coded Decimal format byte array.
|
2021-05-14 23:32:26 +00:00
|
|
|
/// </summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <param name="input">Input byte array to read from.</param>
|
2024-06-10 06:33:46 +00:00
|
|
|
public static uint ReadUInt32BigEndian(ReadOnlySpan<byte> input)
|
2021-05-14 23:32:26 +00:00
|
|
|
{
|
2024-06-10 06:33:46 +00:00
|
|
|
uint result = 0;
|
2022-06-18 18:04:24 +00:00
|
|
|
foreach (var b in input)
|
|
|
|
PushDigits(ref result, b);
|
|
|
|
return result;
|
|
|
|
}
|
2021-05-14 23:32:26 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Writes the <see cref="value"/> to the <see cref="data"/> buffer.
|
|
|
|
/// </summary>
|
2024-06-10 06:33:46 +00:00
|
|
|
public static void WriteUInt32BigEndian(Span<byte> data, uint value)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
for (int i = data.Length - 1; i >= 0; i--, value /= 100)
|
2024-06-10 06:33:46 +00:00
|
|
|
data[i] = GetLowestTuple(value);
|
2022-06-18 18:04:24 +00:00
|
|
|
}
|
2021-05-14 23:32:26 +00:00
|
|
|
|
2024-06-10 06:33:46 +00:00
|
|
|
/// <inheritdoc cref="ReadUInt32BigEndian"/>
|
|
|
|
public static uint ReadUInt32LittleEndian(ReadOnlySpan<byte> input)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
2024-06-10 06:33:46 +00:00
|
|
|
uint result = 0;
|
2022-06-18 18:04:24 +00:00
|
|
|
for (int i = input.Length - 1; i >= 0; i--)
|
|
|
|
PushDigits(ref result, input[i]);
|
|
|
|
return result;
|
|
|
|
}
|
2021-05-14 23:32:26 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Writes the <see cref="value"/> to the <see cref="data"/> buffer.
|
|
|
|
/// </summary>
|
2024-06-10 06:33:46 +00:00
|
|
|
public static void WriteUInt32LittleEndian(Span<byte> data, uint value)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < data.Length; i++, value /= 100)
|
2024-06-10 06:33:46 +00:00
|
|
|
data[i] = GetLowestTuple(value);
|
2021-05-14 23:32:26 +00:00
|
|
|
}
|
|
|
|
}
|