81 lines
2.0 KiB
C#
81 lines
2.0 KiB
C#
using System.Diagnostics;
|
|
|
|
namespace SoulstormReplayReader.Core.Utils;
|
|
|
|
internal sealed class NativeDowRandom
|
|
{
|
|
public uint Seed { get; set; }
|
|
public uint Index { get; set; }
|
|
public uint IterLimit { get; set; }
|
|
|
|
public int Lock { get; set; }
|
|
|
|
public NativeDowRandom(uint iterLimit = 4u)
|
|
{
|
|
IterLimit = iterLimit;
|
|
}
|
|
|
|
public NativeDowRandom SetSeed(uint seed)
|
|
{
|
|
Seed = seed;
|
|
Index = 0;
|
|
|
|
return this;
|
|
}
|
|
|
|
public int GetMax(uint num)
|
|
{
|
|
if (num == 0) return 0;
|
|
var res = (int)(HashRandom() % num);
|
|
Debug.WriteLine($"{num} {res}");
|
|
return res;
|
|
}
|
|
|
|
public int GetMax(int num) => GetMax((uint)num);
|
|
|
|
#region Dow decompiled code
|
|
|
|
private uint HashRandom()
|
|
{
|
|
var result = Index;
|
|
Index++;
|
|
var seed = Seed;
|
|
|
|
if (IterLimit == 0) return result;
|
|
|
|
for (var ind = 0; ind < IterLimit; ind++)
|
|
{
|
|
var s4 = result ^ s_arr1[ind];
|
|
var s5 = result;
|
|
var s6 = (ushort)s4;
|
|
s4 >>= 16;
|
|
var s7 = s_arr2[ind] ^ RotateLeft4((uint)(s6 * s6 + ~(s4 * s4)), '\x10');
|
|
result = (seed ^ (s6 * s4 + s7));
|
|
seed = s5;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static uint RotateLeft4(uint x, char n) => (x << n) | (x >> (32 - n));
|
|
|
|
private static readonly uint[] s_arr1 =
|
|
{
|
|
3131664519, 504877868, 62708796, 255054258, 1990609181,
|
|
3312506973, 3816993251, 2027635554, 1949936084, 2632616645,
|
|
2303949916, 629732701, 1096506909, 560872853, 2244371175,
|
|
1586148200, 1051053196, 3530166132, 4087947819, 1219155940,
|
|
0, 0, 0, 0
|
|
};
|
|
|
|
private static readonly uint[] s_arr2 =
|
|
{
|
|
1259289432, 3899977923, 1767228838, 1437059654, 1301978502,
|
|
4264075669, 2982836325, 1797478225, 2593749601, 2859374024,
|
|
2863238881, 1526273356, 4237173347, 957308556, 1493161986,
|
|
2886360762, 2890429686, 2849966355, 2260618356, 3979088443,
|
|
0, 0, 0, 0
|
|
};
|
|
|
|
#endregion
|
|
} |