use pseudo-deterministic PRNG for random ram initialization (reseed PRNG from system clock every time poweron happens -- except when dealing with movies)
This commit is contained in:
parent
e8d85a9eb2
commit
3a1d872a6d
|
@ -796,12 +796,63 @@ void ResetNES(void) {
|
|||
}
|
||||
|
||||
|
||||
int RAMInitSeed = 0;
|
||||
int RAMInitOption = 0;
|
||||
// Note: this option does not currently apply to WRAM.
|
||||
// Would it be appropriate to call FCEU_MemoryRand inside FCEU_gmalloc to initialize them?
|
||||
|
||||
u64 splitmix64(u32 input) {
|
||||
u64 z = (input + 0x9e3779b97f4a7c15);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||
return z ^ (z >> 31);
|
||||
}
|
||||
|
||||
static inline u64 xoroshiro128plus_rotl(const u64 x, int k) {
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
u64 xoroshiro128plus_s[2];
|
||||
void xoroshiro128plus_seed(u32 input)
|
||||
{
|
||||
//http://xoroshiro.di.unimi.it/splitmix64.c
|
||||
u64 x = input;
|
||||
|
||||
u64 z = (x += 0x9e3779b97f4a7c15);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||
xoroshiro128plus_s[0] = z ^ (z >> 31);
|
||||
|
||||
z = (x += 0x9e3779b97f4a7c15);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||
xoroshiro128plus_s[1] = z ^ (z >> 31);
|
||||
}
|
||||
|
||||
//http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c
|
||||
u64 xoroshiro128plus_next() {
|
||||
const u64 s0 = xoroshiro128plus_s[0];
|
||||
u64 s1 = xoroshiro128plus_s[1];
|
||||
const u64 result = s0 + s1;
|
||||
|
||||
s1 ^= s0;
|
||||
xoroshiro128plus_s[0] = xoroshiro128plus_rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
|
||||
xoroshiro128plus_s[1] = xoroshiro128plus_rotl(s1, 36); // c
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FCEU_MemoryRand(uint8 *ptr, uint32 size) {
|
||||
int x = 0;
|
||||
|
||||
//reseed random, unless we're in a movie
|
||||
extern int disableBatteryLoading;
|
||||
if(FCEUMOV_Mode(MOVIEMODE_INACTIVE) && !disableBatteryLoading)
|
||||
RAMInitSeed = rand()&0x7FFF;
|
||||
|
||||
//always reseed the PRNG with the current seed, for deterministic results (for that seed)
|
||||
xoroshiro128plus_seed(RAMInitSeed);
|
||||
|
||||
while (size) {
|
||||
uint8 v = 0;
|
||||
switch (RAMInitOption)
|
||||
|
@ -810,7 +861,7 @@ void FCEU_MemoryRand(uint8 *ptr, uint32 size) {
|
|||
case 0: v = (x & 4) ? 0xFF : 0x00; break;
|
||||
case 1: v = 0xFF; break;
|
||||
case 2: v = 0x00; break;
|
||||
case 3: v = uint8(rand()); break;
|
||||
case 3: v = (u8)(xoroshiro128plus_next()); break;
|
||||
|
||||
// the default is this 8 byte pattern: 00 00 00 00 FF FF FF FF
|
||||
// it has been used in FCEUX since time immemorial
|
||||
|
|
|
@ -35,6 +35,7 @@ extern bool mustEngageTaseditor;
|
|||
#endif
|
||||
|
||||
extern int RAMInitOption;
|
||||
extern int RAMInitSeed;
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
@ -395,6 +396,7 @@ MovieData::MovieData()
|
|||
, palFlag(false)
|
||||
, PPUflag(false)
|
||||
, RAMInitOption(0)
|
||||
, RAMInitSeed(0)
|
||||
, rerecordCount(0)
|
||||
, binaryFlag(false)
|
||||
, loadFrameCount(-1)
|
||||
|
@ -417,6 +419,8 @@ void MovieData::installValue(std::string& key, std::string& val)
|
|||
installBool(val,PPUflag);
|
||||
else if(key == "RAMInitOption")
|
||||
installInt(val,RAMInitOption);
|
||||
else if(key == "RAMInitSeed")
|
||||
installInt(val,RAMInitSeed);
|
||||
else if(key == "version")
|
||||
installInt(val,version);
|
||||
else if(key == "emuVersion")
|
||||
|
@ -481,6 +485,7 @@ int MovieData::dump(EMUFILE *os, bool binary)
|
|||
os->fprintf("FDS %d\n" , fds?1:0 );
|
||||
os->fprintf("NewPPU %d\n" , PPUflag?1:0 );
|
||||
os->fprintf("RAMInitOption %d\n", RAMInitOption);
|
||||
os->fprintf("RAMInitSeed %d\n", RAMInitSeed);
|
||||
|
||||
for(uint32 i=0;i<comments.size();i++)
|
||||
os->fprintf("comment %s\n" , wcstombs(comments[i]).c_str() );
|
||||
|
@ -817,6 +822,7 @@ void FCEUMOV_CreateCleanMovie()
|
|||
currMovieData.fds = isFDS;
|
||||
currMovieData.PPUflag = (newppu != 0);
|
||||
currMovieData.RAMInitOption = RAMInitOption;
|
||||
currMovieData.RAMInitSeed = RAMInitSeed;
|
||||
}
|
||||
void FCEUMOV_ClearCommands()
|
||||
{
|
||||
|
@ -881,6 +887,9 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
|||
LoadSubtitles(currMovieData);
|
||||
delete fp;
|
||||
|
||||
RAMInitOption = currMovieData.RAMInitOption;
|
||||
RAMInitSeed = currMovieData.RAMInitSeed;
|
||||
|
||||
freshMovie = true; //Movie has been loaded, so it must be unaltered
|
||||
if (bindSavestate) AutoSS = false; //If bind savestate to movie is true, then their isn't a valid auto-save to load, so flag it
|
||||
//fully reload the game to reinitialize everything before playing any movie
|
||||
|
@ -903,7 +912,7 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
|
|||
else
|
||||
FCEUI_SetVidSystem(0);
|
||||
|
||||
RAMInitOption = currMovieData.RAMInitOption;
|
||||
|
||||
|
||||
//force the input configuration stored in the movie to apply
|
||||
FCEUD_SetInput(currMovieData.fourscore, currMovieData.microphone, (ESI)currMovieData.ports[0], (ESI)currMovieData.ports[1], (ESIFC)currMovieData.ports[2]);
|
||||
|
@ -1573,6 +1582,7 @@ bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount)
|
|||
info.pal = md.palFlag;
|
||||
info.ppuflag = md.PPUflag;
|
||||
info.RAMInitOption = md.RAMInitOption;
|
||||
info.RAMInitSeed = md.RAMInitSeed;
|
||||
info.nosynchack = true;
|
||||
info.num_frames = md.records.size();
|
||||
info.md5_of_rom_used = md.romChecksum;
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef struct
|
|||
uint32 emu_version_used; // 9813 = 0.98.13
|
||||
MD5DATA md5_of_rom_used;
|
||||
std::string name_of_rom_used;
|
||||
int RAMInitOption;
|
||||
int RAMInitOption, RAMInitSeed;
|
||||
|
||||
std::vector<std::wstring> comments;
|
||||
std::vector<std::string> subtitles;
|
||||
|
@ -199,7 +199,7 @@ public:
|
|||
|
||||
int getNumRecords() { return records.size(); }
|
||||
|
||||
int RAMInitOption;
|
||||
int RAMInitOption, RAMInitSeed;
|
||||
|
||||
class TDictionary : public std::map<std::string,std::string>
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue