1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-02-15 09:05:52 +00:00

Add new randomness subsystem

This commit is contained in:
fgenesis 2025-02-01 05:51:54 +01:00
parent c9365a3266
commit 9664352a11
7 changed files with 282 additions and 0 deletions

View file

@ -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()

View file

@ -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();

View file

@ -65,6 +65,8 @@ set(BBGE_SRCS
Quad.h
QuadGrid.cpp
QuadGrid.h
Randomness.cpp
Randomness.h
ReadXML.cpp
ReadXML.h
Rect.h

View file

@ -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)
{

View file

@ -320,6 +320,7 @@ public:
bool loopDone;
Mouse mouse;
unsigned lastEventTimestamp;
AfterEffectManager *afterEffectManager;

182
BBGE/Randomness.cpp Normal file
View 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
View 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