speed up state rewinding
This commit is contained in:
parent
1559e84d0d
commit
359aafba57
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue