mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-02-15 00:55:54 +00:00
Add new randomness subsystem
This commit is contained in:
parent
c9365a3266
commit
9664352a11
7 changed files with 282 additions and 0 deletions
|
@ -1362,6 +1362,9 @@ void DSQ::init()
|
|||
title(false);
|
||||
else
|
||||
enqueueJumpState("BitBlotLogo");
|
||||
|
||||
// Use the time needed to load everything as an extra source of entropy
|
||||
Randomness::addEntropy(SDL_GetTicks());
|
||||
}
|
||||
|
||||
void DSQ::recreateBlackBars()
|
||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "DSQ.h"
|
||||
#include <SDL.h>
|
||||
#include <SDL_main.h>
|
||||
#include "Randomness.h"
|
||||
|
||||
|
||||
extern "C" int main(int argc,char *argv[])
|
||||
|
@ -45,6 +46,13 @@ extern "C" int main(int argc,char *argv[])
|
|||
extraDataDir = AQUARIA_EXTRA_DATA_DIR;
|
||||
#endif
|
||||
|
||||
// Couple pointers to help enhance entropy, suppported by the system's ASLR if available
|
||||
{
|
||||
void *p = malloc(1);
|
||||
Randomness::init((uintptr_t)argv, (uintptr_t)&dsqParam, (uintptr_t)&(malloc), (uintptr_t)&p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
{
|
||||
DSQ dsql(dsqParam, extraDataDir);
|
||||
dsql.init();
|
||||
|
|
|
@ -65,6 +65,8 @@ set(BBGE_SRCS
|
|||
Quad.h
|
||||
QuadGrid.cpp
|
||||
QuadGrid.h
|
||||
Randomness.cpp
|
||||
Randomness.h
|
||||
ReadXML.cpp
|
||||
ReadXML.h
|
||||
Rect.h
|
||||
|
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "GLLoad.h"
|
||||
#include "RenderBase.h"
|
||||
#include "Window.h"
|
||||
#include "Randomness.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <iostream>
|
||||
|
@ -1152,6 +1153,15 @@ void Core::run(float runTime)
|
|||
dt = (nowTicks-thenTicks)/1000.0;
|
||||
thenTicks = nowTicks;
|
||||
|
||||
uint64_t entropy = nowTicks;
|
||||
entropy <<= 3;
|
||||
entropy ^= frames;
|
||||
entropy <<= 3;
|
||||
entropy += (mouse.buttons.left << 1) | (mouse.buttons.middle << 2) | (mouse.buttons.right << 3);
|
||||
entropy ^= lastEventTimestamp;
|
||||
Randomness::addEntropy(entropy);
|
||||
|
||||
|
||||
if (!avgFPS.empty())
|
||||
{
|
||||
|
||||
|
@ -1459,6 +1469,8 @@ static const TextInputMapping textInputMap[]
|
|||
|
||||
void Core::onEvent(const SDL_Event& event)
|
||||
{
|
||||
lastEventTimestamp = event.common.timestamp;
|
||||
|
||||
const bool focus = window->hasFocus();
|
||||
if(event.type == sdlUserMouseEventID)
|
||||
{
|
||||
|
|
|
@ -320,6 +320,7 @@ public:
|
|||
bool loopDone;
|
||||
|
||||
Mouse mouse;
|
||||
unsigned lastEventTimestamp;
|
||||
|
||||
AfterEffectManager *afterEffectManager;
|
||||
|
||||
|
|
182
BBGE/Randomness.cpp
Normal file
182
BBGE/Randomness.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
// Must be included first to put the implementation here
|
||||
#include "ascon-sponge.h"
|
||||
|
||||
#include "Base.h"
|
||||
#include "Randomness.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "SDLwrap.h"
|
||||
|
||||
|
||||
static SlowRand s_sysrand;
|
||||
static SplitMix64 s_splitmix;
|
||||
static Xoshiro128 s_xosh;
|
||||
static FastRand s_fastr;
|
||||
|
||||
|
||||
static inline uint32_t rotl32(const uint32_t x, uint32_t k)
|
||||
{
|
||||
return (x << k) | (x >> (32u - k));
|
||||
}
|
||||
|
||||
// via https://blog.bithole.dev/blogposts/random-float/
|
||||
static inline float int_to_float01(uint32_t r)
|
||||
{
|
||||
union { uint32_t u32; float f; } u;
|
||||
u.u32 = (r >> 9u) | 0x3f800000;
|
||||
return u.f - 1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Randomness::init(uintptr_t a, uintptr_t b, uintptr_t c, uintptr_t d)
|
||||
{
|
||||
uint64_t v[] =
|
||||
{
|
||||
uint64_t(a),
|
||||
uint64_t(rand()),
|
||||
uint64_t(rand()),
|
||||
uint64_t(rand()),
|
||||
uint64_t(time(NULL)),
|
||||
uint64_t(clock()),
|
||||
uint64_t(&SDL_GetTicks),
|
||||
uint64_t(&time),
|
||||
uint64_t(&s_sysrand),
|
||||
// These functions should be ok to call without calling SDL_Init() first
|
||||
uint64_t(SDL_GetThreadID(NULL)),
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
uint64_t(SDL_GetPerformanceCounter()),
|
||||
uint64_t(SDL_GetPerformanceFrequency()),
|
||||
uint64_t(SDL_GetSystemRAM()),
|
||||
uint64_t(SDL_GetCPUCount())
|
||||
#endif
|
||||
};
|
||||
s_sysrand.absorb(v, Countof(v));
|
||||
s_splitmix.state = s_sysrand.duplex(b);
|
||||
|
||||
s_xosh.u.q[0] = s_sysrand.duplex(c);
|
||||
s_xosh.u.q[1] = s_sysrand.duplex(d);
|
||||
}
|
||||
|
||||
void Randomness::addEntropy(uint64_t x)
|
||||
{
|
||||
s_fastr.state ^= s_sysrand.duplex(x);
|
||||
s_sysrand.absorb(s_splitmix.next()); // pulling from splitmix permutes it
|
||||
s_sysrand.absorb(s_xosh.next());
|
||||
}
|
||||
|
||||
uint64_t Randomness::getBits64()
|
||||
{
|
||||
return s_splitmix.next();
|
||||
}
|
||||
|
||||
uint32_t Randomness::getBits32()
|
||||
{
|
||||
return s_fastr.next();
|
||||
}
|
||||
|
||||
float Randomness::getFloat01()
|
||||
{
|
||||
return s_fastr.f01();
|
||||
}
|
||||
|
||||
|
||||
SplitMix64::SplitMix64()
|
||||
: state(s_sysrand.next())
|
||||
{
|
||||
}
|
||||
|
||||
SplitMix64::SplitMix64(uint64_t seed)
|
||||
: state(seed)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t SplitMix64::next()
|
||||
{
|
||||
uint64_t z = (state += UINT64_C(0x9e3779b97f4a7c15));
|
||||
z = (z ^ (z >> 30u)) * UINT64_C(0xbf58476d1ce4e5b9);
|
||||
z = (z ^ (z >> 27u)) * UINT64_C(0x94d049bb133111eb);
|
||||
return z ^ (z >> 31u);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SlowRand::SlowRand()
|
||||
{
|
||||
ascon_sponge_init(&ascon);
|
||||
}
|
||||
|
||||
|
||||
void SlowRand::absorb(const uint64_t* seed, size_t n)
|
||||
{
|
||||
ascon_sponge_absorb_blocks(&ascon, seed, n);
|
||||
}
|
||||
|
||||
void SlowRand::absorb(uint64_t val)
|
||||
{
|
||||
ascon_sponge_absorb_block(&ascon, val);
|
||||
}
|
||||
|
||||
uint64_t SlowRand::duplex(uint64_t duplex)
|
||||
{
|
||||
return ascon_sponge_duplex_block(&ascon, duplex);
|
||||
}
|
||||
|
||||
uint64_t SlowRand::next()
|
||||
{
|
||||
return ascon_sponge_squeeze_block(&ascon);
|
||||
}
|
||||
|
||||
Xoshiro128::Xoshiro128()
|
||||
{
|
||||
u.q[0] = s_splitmix.next();
|
||||
u.q[1] = s_sysrand.duplex((uintptr_t)this);
|
||||
}
|
||||
|
||||
Xoshiro128::Xoshiro128(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
||||
{
|
||||
u.s[0] = a;
|
||||
u.s[1] = b;
|
||||
u.s[2] = c;
|
||||
u.s[3] = d;
|
||||
}
|
||||
|
||||
uint32_t Xoshiro128::next()
|
||||
{
|
||||
const uint32_t result = u.s[0] + u.s[3];
|
||||
const uint32_t t = u.s[1] << 9;
|
||||
u.s[2] ^= u.s[0];
|
||||
u.s[3] ^= u.s[1];
|
||||
u.s[1] ^= u.s[2];
|
||||
u.s[0] ^= u.s[3];
|
||||
u.s[2] ^= t;
|
||||
u.s[3] = rotl32(u.s[3], 11);
|
||||
return result;
|
||||
}
|
||||
|
||||
float Xoshiro128::f01()
|
||||
{
|
||||
return int_to_float01(next());
|
||||
}
|
||||
|
||||
FastRand::FastRand()
|
||||
: state(s_sysrand.next())
|
||||
{
|
||||
}
|
||||
|
||||
FastRand::FastRand(uint64_t state)
|
||||
: state(state)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t FastRand::next()
|
||||
{
|
||||
// SDL3's rand()
|
||||
state = state * 0xff1cd035u + 0x05;
|
||||
return state >> 32u;
|
||||
}
|
||||
|
||||
float FastRand::f01()
|
||||
{
|
||||
return int_to_float01(next());
|
||||
}
|
74
BBGE/Randomness.h
Normal file
74
BBGE/Randomness.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
#ifndef RANDOMNESS_H
|
||||
#define RANDOMNESS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ASCON_SPONGE_TYPES_ONLY
|
||||
#include "ascon-sponge.h"
|
||||
|
||||
|
||||
namespace Randomness
|
||||
{
|
||||
// Call this once on startup
|
||||
void init(uintptr_t a, uintptr_t b, uintptr_t c, uintptr_t d);
|
||||
|
||||
// Call this once per frame with some number
|
||||
void addEntropy(uint64_t x);
|
||||
|
||||
uint64_t getBits64();
|
||||
uint32_t getBits32();
|
||||
float getFloat01(); // in [0..1)
|
||||
}
|
||||
|
||||
|
||||
class SplitMix64
|
||||
{
|
||||
public:
|
||||
SplitMix64();
|
||||
SplitMix64(uint64_t seed);
|
||||
uint64_t next();
|
||||
uint64_t state;
|
||||
};
|
||||
|
||||
|
||||
class SlowRand
|
||||
{
|
||||
public:
|
||||
SlowRand();
|
||||
void absorb(const uint64_t *seed, size_t n);
|
||||
void absorb(uint64_t val);
|
||||
uint64_t next();
|
||||
uint64_t duplex(uint64_t in); // extract one, put one back in
|
||||
private:
|
||||
ascon_state_t ascon;
|
||||
};
|
||||
|
||||
// Xoshiro128+ actually
|
||||
struct Xoshiro128
|
||||
{
|
||||
public:
|
||||
Xoshiro128();
|
||||
Xoshiro128(uint32_t a, uint32_t b, uint32_t c, uint32_t d);
|
||||
uint32_t next();
|
||||
float f01();
|
||||
|
||||
union
|
||||
{
|
||||
uint32_t s[4];
|
||||
uint64_t q[2];
|
||||
} u;
|
||||
};
|
||||
|
||||
struct FastRand
|
||||
{
|
||||
FastRand();
|
||||
FastRand(uint64_t state);
|
||||
|
||||
uint32_t next();
|
||||
float f01();
|
||||
|
||||
uint64_t state;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue