mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-11-19 09:29:42 +01:00
fd4415317d
This is to make it so RNG is deterministic when played back with the same inputs in a libTAS movie even if screen effects or backgrounds are disabled. That way, Gravitron RNG is on its own system (seeded in hardreset()), separate from the constant fRandom() calls that go to visual systems and don't do anything of actual consequence. The seed is based off of SDL_GetTicks(), so RTA runners don't get the same Gravitron RNG every time. This also paves the way for a future in-built input-based recording system, which now only has to save the seed for a given recording in order for it to play back deterministically.
62 lines
1.1 KiB
C
62 lines
1.1 KiB
C
#include <stdint.h>
|
|
|
|
/* Implements the xoshiro128+ PRNG. */
|
|
|
|
static uint32_t rotl(const uint32_t x, const int k)
|
|
{
|
|
return (x << k) | (x >> (32 - k));
|
|
}
|
|
|
|
static uint32_t s[4];
|
|
|
|
static uint32_t splitmix32(uint32_t* x)
|
|
{
|
|
uint32_t z = (*x += 0x9e3779b9UL);
|
|
z = (z ^ (z >> 15)) * 0xbf58476dUL;
|
|
z = (z ^ (z >> 13)) * 0x94d049bbUL;
|
|
return z ^ (z >> 16);
|
|
}
|
|
|
|
static void seed(
|
|
const uint32_t s0,
|
|
const uint32_t s1,
|
|
const uint32_t s2,
|
|
const uint32_t s3
|
|
) {
|
|
s[0] = s0;
|
|
s[1] = s1;
|
|
s[2] = s2;
|
|
s[3] = s3;
|
|
}
|
|
|
|
uint32_t xoshiro_next(void)
|
|
{
|
|
const uint32_t result = s[0] + s[3];
|
|
|
|
const uint32_t t = s[1] << 9;
|
|
|
|
s[2] ^= s[0];
|
|
s[3] ^= s[1];
|
|
s[1] ^= s[2];
|
|
s[0] ^= s[3];
|
|
|
|
s[2] ^= t;
|
|
|
|
s[3] = rotl(s[3], 11);
|
|
|
|
return result;
|
|
}
|
|
|
|
void xoshiro_seed(uint32_t s)
|
|
{
|
|
const uint32_t s0 = splitmix32(&s);
|
|
const uint32_t s1 = splitmix32(&s);
|
|
const uint32_t s2 = splitmix32(&s);
|
|
const uint32_t s3 = splitmix32(&s);
|
|
seed(s0, s1, s2, s3);
|
|
}
|
|
|
|
float xoshiro_rand(void)
|
|
{
|
|
return ((float) xoshiro_next()) / ((float) UINT32_MAX);
|
|
}
|