speed up state rewinding

This commit is contained in:
zeromus 2009-07-21 08:09:52 +00:00
parent 1559e84d0d
commit 359aafba57
2 changed files with 89 additions and 55 deletions

View File

@ -155,31 +155,6 @@ public:
myBuf = true;
}
private:
void dosync(int c)
{
size_t wp = tellWrite();
size_t rp = tellRead();
//if we are supposed to insert a character..
if(c != -1)
{
buf[wp] = c;
wp++;
}
//the length is determined by the highest character that was ever inserted
length = std::max(length,wp);
//the write window advances to begin at the current write insertion point
ww = wp;
//set the new write and read windows
setp(buf+ww, buf + capacity);
setg(buf, buf+rp, buf + length);
}
void expand(size_t upto)
{
if(!myBuf && !usevec)
@ -211,6 +186,31 @@ private:
}
}
private:
void dosync(int c)
{
size_t wp = tellWrite();
size_t rp = tellRead();
//if we are supposed to insert a character..
if(c != -1)
{
buf[wp] = c;
wp++;
}
//the length is determined by the highest character that was ever inserted
length = std::max(length,wp);
//the write window advances to begin at the current write insertion point
ww = wp;
//set the new write and read windows
setp(buf+ww, buf + capacity);
setg(buf, buf+rp, buf + length);
}
protected:
int overflow(int c)
@ -297,6 +297,8 @@ public:
void trim() { streambuf.trim(); }
void giveBuf() { streambuf.giveBuf(); }
memory_streambuf<char>& getStreambuf() { return streambuf; }
};

View File

@ -22,6 +22,7 @@
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#include <stack>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
@ -738,23 +739,40 @@ static void writechunks(std::ostream* os);
static bool savestate_save(std::ostream* outstream, int compressionLevel)
{
//generate the savestate in memory first
#ifndef HAVE_LIBZ
compressionLevel = Z_NO_COMPRESSION;
#endif
memorystream ms;
std::ostream* os;
if(compressionLevel != Z_NO_COMPRESSION)
{
//generate the savestate in memory first
std::ostream* os = (std::ostream*)&ms;
writechunks(os);
ms.flush();
}
else
{
os = outstream;
os->seekp(32); //skip the header
writechunks(os);
}
os->flush();
//save the length of the file
u32 len = ms.size();
u32 len = os->tellp();
u32 comprlen = 0xFFFFFFFF;
u8* cbuf = (u8*)ms.buf();
u8* cbuf;
#ifdef HAVE_LIBZ
//compress the data
int error = Z_OK;
if(compressionLevel != Z_NO_COMPRESSION)
{
cbuf = (u8*)ms.buf();
uLongf comprlen2;
//worst case compression.
//zlib says "0.1% larger than sourceLen plus 12 bytes"
@ -765,22 +783,23 @@ static bool savestate_save(std::ostream* outstream, int compressionLevel)
error = compress2(cbuf,&comprlen2,(u8*)ms.buf(),len,compressionLevel);
comprlen = (u32)comprlen2;
}
#endif
//dump the header
outstream->seekp(0);
outstream->write(magic,16);
write32le(SAVESTATE_VERSION,outstream);
write32le(DESMUME_VERSION_NUMERIC,outstream); //desmume version
write32le(len,outstream); //uncompressed length
write32le(comprlen,outstream); //compressed length (-1 if it is not compressed)
outstream->flush();
if(compressionLevel != Z_NO_COMPRESSION)
{
outstream->write((char*)cbuf,comprlen==(u32)-1?len:comprlen);
if(cbuf != (uint8*)ms.buf()) delete[] cbuf;
#ifdef HAVE_LIBZ
delete[] cbuf;
}
return error == Z_OK;
#else
return true;
#endif
}
bool savestate_save (const char *file_name)
@ -965,7 +984,8 @@ bool savestate_load(const char *file_name)
return savestate_load(&f);
}
static std::vector<std::vector <char>> rewindbuffer;
static std::stack<memorystream*> rewindFreeList;
static std::vector<memorystream*> rewindbuffer;
int rewindstates = 16;
int rewindinterval = 4;
@ -975,23 +995,30 @@ void rewindsave () {
if(currFrameCounter % rewindinterval)
return;
printf("rewindsave"); printf("%d%s", currFrameCounter, "\n");
//printf("rewindsave"); printf("%d%s", currFrameCounter, "\n");
memorystream ms;
if(!savestate_save(&ms, 0))
memorystream *ms;
if(!rewindFreeList.empty()) {
ms = rewindFreeList.top();
rewindFreeList.pop();
} else {
ms = new memorystream();
}
ms->getStreambuf().expand(1024*1024*12);
if(!savestate_save(ms, Z_NO_COMPRESSION))
return;
ms.flush();
ms->sync();
std::vector<char> v(ms.buf(), ms.buf() + ms.size());
rewindbuffer.push_back(ms);
//clip the header
v.erase(v.begin(),v.begin()+32);
rewindbuffer.push_back(v);
if(rewindbuffer.size() > rewindstates) rewindbuffer.erase(rewindbuffer.begin());
if(rewindbuffer.size() > rewindstates) {
delete *rewindbuffer.begin();
rewindbuffer.erase(rewindbuffer.begin());
}
}
void dorewind()
@ -1000,7 +1027,7 @@ void dorewind()
if(currFrameCounter % rewindinterval)
return;
printf("rewind\n");
//printf("rewind\n");
nds.debugConsole = FALSE;
@ -1013,11 +1040,16 @@ void dorewind()
printf("%d", size);
memorystream mstemp(&rewindbuffer.at(size-1));
memorystream* loadms = rewindbuffer[size-1];
loadms->seekg(32, std::ios::beg);
ReadStateChunks(&mstemp,(s32)mstemp.size());
ReadStateChunks(loadms,loadms->size()-32);
loadstate();
if(rewindbuffer.size()>1)
{
rewindFreeList.push(loadms);
rewindbuffer.pop_back();
}
}