From fd822ea498c74147df8bc6ff4ac5f6dfc24220b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=9A=93?= Date: Sun, 6 Jul 2025 12:27:46 -0400 Subject: [PATCH] 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. --- libretro/Makefile | 1 + libretro/ruby-prng-time.patch | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 libretro/ruby-prng-time.patch diff --git a/libretro/Makefile b/libretro/Makefile index bcdf3781..407aed5f 100644 --- a/libretro/Makefile +++ b/libretro/Makefile @@ -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) diff --git a/libretro/ruby-prng-time.patch b/libretro/ruby-prng-time.patch new file mode 100644 index 00000000..27a0de14 --- /dev/null +++ b/libretro/ruby-prng-time.patch @@ -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