-
Notifications
You must be signed in to change notification settings - Fork 0
/
PokemonData.cs
95 lines (80 loc) · 2.45 KB
/
PokemonData.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System.Buffers.Binary;
namespace PCDWC4Converter;
public static class PokemonData
{
private static readonly byte[] _blockPositions =
{
0, 1, 2, 3,
0, 1, 3, 2,
0, 2, 1, 3,
0, 3, 1, 2,
0, 2, 3, 1,
0, 3, 2, 1,
1, 0, 2, 3,
1, 0, 3, 2,
2, 0, 1, 3,
3, 0, 1, 2,
2, 0, 3, 1,
3, 0, 2, 1,
1, 2, 0, 3,
1, 3, 0, 2,
2, 1, 0, 3,
3, 1, 0, 2,
2, 3, 0, 1,
3, 2, 0, 1,
1, 2, 3, 0,
1, 3, 2, 0,
2, 1, 3, 0,
3, 1, 2, 0,
2, 3, 1, 0,
3, 2, 1, 0
};
private static readonly byte[] _blockPositionInvert =
{
0, 1, 2, 4, 3, 5, 6, 7, 12, 18, 13, 19, 8, 10, 14, 20, 16, 22, 9, 11, 15, 21, 17, 23
};
private static void XorCrypt(Span<byte> data)
{
var pid = BinaryPrimitives.ReadUInt32LittleEndian(data[..4]);
var initialSeed = BinaryPrimitives.ReadUInt16LittleEndian(data[6..8]);
var rng = new LCRng(initialSeed);
for (var i = 8; i < 236; i += 2)
{
if (i == 136)
{
rng = new LCRng(pid);
}
var dataBlock = data[i..];
var value = BinaryPrimitives.ReadUInt16LittleEndian(dataBlock);
BinaryPrimitives.WriteUInt16LittleEndian(dataBlock, (ushort)(value ^ rng.NextH()));
}
}
private static void Shuffle(Span<byte> data, uint shiftValue)
{
// Offset by first block
data = data.Slice(8, 32 * 4);
Span<byte> originalData = stackalloc byte[32 * 4];
data.CopyTo(originalData);
for (var i = 0; i < 4; i++)
{
// Unshuffle the data
originalData.Slice(32 * _blockPositions[i + shiftValue * 4], 32).CopyTo(data);
// Increment to next block
data = data[32..];
}
}
public static void DecryptData(Span<byte> pkmData)
{
var pid = BinaryPrimitives.ReadUInt32LittleEndian(pkmData[..4]);
var shiftValue = ((pid & 0x3E000) >> 0xD) % 24;
XorCrypt(pkmData);
Shuffle(pkmData, shiftValue);
}
public static void EncryptData(Span<byte> pkmData)
{
var pid = BinaryPrimitives.ReadUInt32LittleEndian(pkmData[..4]);
var shiftValue = ((pid & 0x3E000) >> 0xD) % 24;
Shuffle(pkmData, _blockPositionInvert[shiftValue]);
XorCrypt(pkmData);
}
}