Small save/load state speedup, noticeable only in TAS Editor or lua bots

This commit is contained in:
ansstuff 2012-02-25 23:55:35 +00:00
parent d659fab541
commit e1950ba025
2 changed files with 37 additions and 28 deletions

View File

@ -247,6 +247,11 @@ public:
virtual void fflush() {} virtual void fflush() {}
void set_len(s32 length)
{
len = length;
if(pos>length) pos=length;
}
void trim() void trim()
{ {
vec->resize(len); vec->resize(len);

View File

@ -82,6 +82,11 @@ bool internalSaveLoad = false;
bool backupSavestates = true; bool backupSavestates = true;
bool compressSavestates = true; //By default FCEUX compresses savestates when a movie is inactive. bool compressSavestates = true; //By default FCEUX compresses savestates when a movie is inactive.
// a temp memory stream. We'll be dumping some data here and then compress
EMUFILE_MEMORY memory_savestate;
// temporary buffer for compressed data of a savestate
std::vector<uint8> compressed_buf;
#define SFMDATA_SIZE (64) #define SFMDATA_SIZE (64)
static SFORMAT SFMDATA[SFMDATA_SIZE]; static SFORMAT SFMDATA[SFMDATA_SIZE];
static int SFEXINDEX; static int SFEXINDEX;
@ -355,11 +360,10 @@ extern int geniestage;
bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel) bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
{ {
//a temp memory stream. we'll dump some data here and then compress // reset memory_savestate
//TODO - support dumping directly without compressing to save a buffer copy memory_savestate.set_len(0);
EMUFILE_MEMORY ms; EMUFILE* os = &memory_savestate;
EMUFILE* os = &ms;
uint32 totalsize = 0; uint32 totalsize = 0;
@ -404,7 +408,7 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
if(SPreSave) SPostSave(); if(SPreSave) SPostSave();
//save the length of the file //save the length of the file
int len = ms.size(); int len = memory_savestate.size();
//sanity check: len and totalsize should be the same //sanity check: len and totalsize should be the same
if(len != totalsize) if(len != totalsize)
@ -414,15 +418,16 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
} }
int error = Z_OK; int error = Z_OK;
uint8* cbuf = (uint8*)ms.buf(); uint8* cbuf = (uint8*)memory_savestate.buf();
uLongf comprlen = -1; uLongf comprlen = -1;
if(compressionLevel != Z_NO_COMPRESSION && compressSavestates) if(compressionLevel != Z_NO_COMPRESSION && compressSavestates)
{ {
//worst case compression. // worst case compression: zlib says "0.1% larger than sourceLen plus 12 bytes"
//zlib says "0.1% larger than sourceLen plus 12 bytes"
comprlen = (len>>9)+12 + len; comprlen = (len>>9)+12 + len;
cbuf = new uint8[comprlen]; if (compressed_buf.size() < comprlen) compressed_buf.resize(comprlen);
error = compress2(cbuf,&comprlen,(uint8*)ms.buf(),len,compressionLevel); cbuf = &compressed_buf[0];
// do compression
error = compress2(cbuf, &comprlen, (uint8*)memory_savestate.buf(), len, compressionLevel);
} }
//dump the header //dump the header
@ -435,7 +440,6 @@ bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
outstream->fwrite((char*)header,16); outstream->fwrite((char*)header,16);
outstream->fwrite((char*)cbuf,comprlen==-1?totalsize:comprlen); outstream->fwrite((char*)cbuf,comprlen==-1?totalsize:comprlen);
if(cbuf != (uint8*)ms.buf()) delete[] cbuf;
return error == Z_OK; return error == Z_OK;
} }
@ -644,30 +648,31 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
int stateversion = FCEU_de32lsb(header + 8); int stateversion = FCEU_de32lsb(header + 8);
int comprlen = FCEU_de32lsb(header + 12); int comprlen = FCEU_de32lsb(header + 12);
std::vector<uint8> buf(totalsize); // memory_savestate is global variable which already has its vector of bytes
if ((int)(memory_savestate.get_vec())->size() < totalsize)
(memory_savestate.get_vec())->resize(totalsize);
memory_savestate.set_len(totalsize);
memory_savestate.fseek(0, SEEK_SET);
//not compressed:
if(comprlen != -1) if(comprlen != -1)
{ {
//load the compressed chunk and decompress // the savestate is compressed: read from is to compressed_buf, then decompress from compressed_buf to memory_savestate.vec
std::vector<char> cbuf(comprlen); if ((int)compressed_buf.size() < comprlen) compressed_buf.resize(comprlen);
is->fread((char*)&cbuf[0],comprlen); is->fread(&compressed_buf[0], comprlen);
uLongf uncomprlen = totalsize; uLongf uncomprlen = totalsize;
int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); int error = uncompress(memory_savestate.buf(), &uncomprlen, &compressed_buf[0], comprlen);
if(error != Z_OK || uncomprlen != totalsize) if(error != Z_OK || uncomprlen != totalsize)
return false; return false; // we dont need to restore the backup here because we havent messed with the emulator state yet
//we dont need to restore the backup here because we havent messed with the emulator state yet } else
}
else
{ {
is->fread((char*)&buf[0],totalsize); // the savestate is not compressed: just read from is to memory_savestate.vec
is->fread(memory_savestate.buf(), totalsize);
} }
FCEUMOV_PreLoad(); FCEUMOV_PreLoad();
EMUFILE_MEMORY mstemp(&buf); bool x = (ReadStateChunks(&memory_savestate, totalsize) != 0);
bool x = ReadStateChunks(&mstemp,totalsize)!=0;
//mbg 5/24/08 - we don't support old states, so this shouldnt matter. //mbg 5/24/08 - we don't support old states, so this shouldnt matter.
//if(read_sfcpuc && stateversion<9500) //if(read_sfcpuc && stateversion<9500)
@ -677,14 +682,13 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
{ {
GameStateRestore(stateversion); GameStateRestore(stateversion);
} }
if(x) if (x)
{ {
FCEUPPU_LoadState(stateversion); FCEUPPU_LoadState(stateversion);
FCEUSND_LoadState(stateversion); FCEUSND_LoadState(stateversion);
x=FCEUMOV_PostLoad(); x=FCEUMOV_PostLoad();
} } else if (backup)
{
if(!x && backup) {
msBackupSavestate.fseek(0,SEEK_SET); msBackupSavestate.fseek(0,SEEK_SET);
FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP); FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP);
} }