Skip to content

Commit f6aa434

Browse files
JoeMattclaude
andcommitted
Use portable xorshift PRNG for deterministic cross-platform RAM init
Replace libc rand()/srand() with a platform-independent xorshift32 PRNG. libc rand() produces different sequences on glibc vs macOS libsystem, causing cross-platform baseline mismatches in regression tests. The xorshift32 implementation guarantees identical RAM initialization on all platforms. Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent a845760 commit f6aa434

6 files changed

Lines changed: 27 additions & 12 deletions

File tree

src/dsp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ void DSPReset(void)
822822

823823
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
824824
for(i=0; i<8192; i+=4)
825-
*((uint32_t *)(&dsp_ram_8[i])) = rand();
825+
*((uint32_t *)(&dsp_ram_8[i])) = JaguarRand();
826826
}
827827

828828
void DSPDone(void)

src/gpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ void GPUReset(void)
666666

667667
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
668668
for(i=0; i<4096; i+=4)
669-
*((uint32_t *)(&gpu_ram_8[i])) = rand();
669+
*((uint32_t *)(&gpu_ram_8[i])) = JaguarRand();
670670
}
671671

672672
uint32_t GPUReadPC(void)

src/jaguar.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include <string.h>
1717
#include <stdlib.h>
1818

19-
#include <time.h>
20-
2119
#include "jaguar.h"
2220

2321
#include "cdrom.h"
@@ -35,6 +33,24 @@
3533

3634
static bool frameDone;
3735

36+
// Platform-independent xorshift32 PRNG for deterministic RAM initialization.
37+
// libc rand() produces different sequences on different platforms (glibc vs
38+
// macOS libsystem), which causes cross-platform baseline mismatches.
39+
static uint32_t jaguar_prng_state = 12345;
40+
41+
void JaguarSeedPRNG(uint32_t seed)
42+
{
43+
jaguar_prng_state = seed ? seed : 1;
44+
}
45+
46+
uint32_t JaguarRand(void)
47+
{
48+
jaguar_prng_state ^= jaguar_prng_state << 13;
49+
jaguar_prng_state ^= jaguar_prng_state >> 17;
50+
jaguar_prng_state ^= jaguar_prng_state << 5;
51+
return jaguar_prng_state;
52+
}
53+
3854
#define ALPINE_FUNCTIONS
3955

4056
// Private function prototypes
@@ -541,15 +557,12 @@ void JaguarSetScreenPitch(uint32_t pitch)
541557
void JaguarInit(void)
542558
{
543559
unsigned i;
544-
// Seed with a fixed value so emulation is deterministic across runs.
545-
// Real hardware has quasi-random RAM contents at power-on, but using
546-
// a constant seed preserves that simulation while keeping output
547-
// reproducible for regression testing and save state consistency.
548-
srand(12345);
560+
// Reset the platform-independent PRNG for deterministic RAM fill
561+
JaguarSeedPRNG(12345);
549562

550563
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
551564
for(i=0; i<0x200000; i+=4)
552-
*((uint32_t *)(&jaguarMainRAM[i])) = rand();
565+
*((uint32_t *)(&jaguarMainRAM[i])) = JaguarRand();
553566

554567
lowerField = false; // Reset the lower field flag
555568
memset(jaguarMainRAM + 0x804, 0xFF, 4);
@@ -634,8 +647,9 @@ void JaguarReset(void)
634647

635648
// Only problem with this approach: It wipes out RAM loaded files...!
636649
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
650+
JaguarSeedPRNG(12345);
637651
for(i=8; i<0x200000; i+=4)
638-
*((uint32_t *)(&jaguarMainRAM[i])) = rand();
652+
*((uint32_t *)(&jaguarMainRAM[i])) = JaguarRand();
639653

640654
// New timer base code stuffola...
641655
InitializeEventList();

src/jaguar.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ void JaguarSetScreenPitch(uint32_t pitch);
1616
void JaguarInit(void);
1717
void JaguarReset(void);
1818
void JaguarDone(void);
19+
void JaguarSeedPRNG(uint32_t seed);
20+
uint32_t JaguarRand(void);
1921

2022
uint8_t JaguarReadByte(uint32_t offset, uint32_t who);
2123
uint16_t JaguarReadWord(uint32_t offset, uint32_t who);

src/tom.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@
256256
#include "tom.h"
257257

258258
#include <string.h> // For memset()
259-
#include <stdlib.h> // For rand()
260259
#include "blitter.h"
261260
#include "event.h"
262261
#include "gpu.h"

test/baselines/yarc.png

-9 Bytes
Loading

0 commit comments

Comments
 (0)