Don't seed the Ruby PRNG with the system time in libretro builds

This allows libretro save states to actually behave the same every time
you load them with respect to when randomly generated events occur and
the random movements that NPCs make.
This commit is contained in:
刘皓 2025-07-06 12:27:46 -04:00
parent 42d49f7296
commit fd822ea498
No known key found for this signature in database
GPG key ID: 7901753DB465B711
2 changed files with 50 additions and 0 deletions

View file

@ -151,6 +151,7 @@ $(DOWNLOADS)/ruby/configure.ac:
cd $(DOWNLOADS)/ruby && $(GIT) apply ${PWD}/ruby-stack-pointer.patch
cd $(DOWNLOADS)/ruby && $(GIT) apply ${PWD}/ruby-jump-buffer.patch
cd $(DOWNLOADS)/ruby && $(GIT) apply ${PWD}/ruby-compat.patch
cd $(DOWNLOADS)/ruby && $(GIT) apply ${PWD}/ruby-prng-time.patch
echo '#include "${PWD}/ruby-bindings.h"' >> $(DOWNLOADS)/ruby/gc.c
# WABT (targets the build machine)

View file

@ -0,0 +1,49 @@
# Removes the dependency of the Ruby pseudorandom number generator's seed on the system time for better save state determinism.
--- a/random.c
+++ b/random.c
@@ -680,28 +680,28 @@ static void
fill_random_seed(uint32_t *seed, size_t cnt)
{
static rb_atomic_t n = 0;
-#if defined HAVE_CLOCK_GETTIME
- struct timespec tv;
-#elif defined HAVE_GETTIMEOFDAY
- struct timeval tv;
-#endif
+
+
+
+
+
size_t len = cnt * sizeof(*seed);
memset(seed, 0, len);
fill_random_bytes(seed, len, FALSE);
-#if defined HAVE_CLOCK_GETTIME
- clock_gettime(CLOCK_REALTIME, &tv);
- seed[0] ^= tv.tv_nsec;
-#elif defined HAVE_GETTIMEOFDAY
- gettimeofday(&tv, 0);
- seed[0] ^= tv.tv_usec;
-#endif
- seed[1] ^= (uint32_t)tv.tv_sec;
-#if SIZEOF_TIME_T > SIZEOF_INT
- seed[0] ^= (uint32_t)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
-#endif
+
+
+
+
+
+
+
+
+
+
+
seed[2] ^= getpid() ^ (ATOMIC_FETCH_ADD(n, 1) << 16);
seed[3] ^= (uint32_t)(VALUE)&seed;
#if SIZEOF_VOIDP > SIZEOF_INT