compress savestates, and movie no longer needs to do any compression itsself.
savestate compatibility is now broken.
This commit is contained in:
parent
bf6d70c56d
commit
e524818f1e
|
@ -22,7 +22,6 @@
|
|||
#include "movie.h"
|
||||
#include "utils/memory.h"
|
||||
#include "utils/xstring.h"
|
||||
#include "zlib.h"
|
||||
|
||||
|
||||
#define MOVIE_MAGIC 0x1a4d4346 // FCM\x1a
|
||||
|
@ -438,22 +437,15 @@ void FCEUI_LoadMovie(char *fname, int _read_only, int _pauseframe)
|
|||
//WE NEED TO LOAD A SAVESTATE
|
||||
if(!currMovieData.poweronFlag)
|
||||
{
|
||||
//uncompress the savestate
|
||||
int bufsize = ntohl(*(int*)&currMovieData.savestate[0]);
|
||||
uint8* buf = new uint8[bufsize];
|
||||
uLongf uncomprlen = bufsize;
|
||||
uncompress(buf,&uncomprlen,(uint8*)&currMovieData.savestate[4],currMovieData.savestate.size()-4);
|
||||
|
||||
//dump it to disk
|
||||
//dump the savestate to disk
|
||||
FILE* fp = tmpfile();
|
||||
fwrite(buf,1,bufsize,fp);
|
||||
fwrite(&currMovieData.savestate[0],1,currMovieData.savestate.size(),fp);
|
||||
fseek(fp,0,SEEK_SET);
|
||||
|
||||
//and load the state
|
||||
bool success = FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP);
|
||||
|
||||
fclose(fp);
|
||||
delete[] buf;
|
||||
|
||||
if(!success) return;
|
||||
}
|
||||
|
@ -525,27 +517,14 @@ void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
|
|||
//dump a savestate to a tempfile..
|
||||
FILE* tmp = tmpfile();
|
||||
FCEUSS_SaveFP(tmp);
|
||||
|
||||
//reloading the savestate into the data structure
|
||||
fseek(tmp,0,SEEK_END);
|
||||
int len = (int)ftell(tmp);
|
||||
fseek(tmp,0,SEEK_SET);
|
||||
//reloading the savestate from the tempfile..
|
||||
uint8* buf = new uint8[len];
|
||||
fread(buf,1,len,tmp);
|
||||
currMovieData.savestate.resize(len);
|
||||
fread(&currMovieData.savestate[0],1,len,tmp);
|
||||
fclose(tmp);
|
||||
|
||||
//compress it
|
||||
uint8* cbuf = new uint8[len*2]; //worst case compression, lets say twice the input buffer size
|
||||
uLongf destlen;
|
||||
int error = compress2(cbuf,&destlen,buf,len,Z_BEST_COMPRESSION);
|
||||
|
||||
//poke it in the data structure
|
||||
currMovieData.savestate.resize(destlen+4);
|
||||
memcpy(&currMovieData.savestate[4],cbuf,destlen);
|
||||
*(int*)&currMovieData.savestate[0] = htonl(len);
|
||||
|
||||
//cleanup
|
||||
delete[] buf;
|
||||
delete[] cbuf;
|
||||
}
|
||||
|
||||
//we are going to go ahead and dump the header. from now on we will only be appending frames
|
||||
|
|
187
src/state.cpp
187
src/state.cpp
|
@ -27,6 +27,8 @@
|
|||
#include <string.h>
|
||||
//#include <unistd.h> //mbg merge 7/17/06 removed
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
|
@ -41,6 +43,7 @@
|
|||
#include "netplay.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "zlib.h"
|
||||
|
||||
static void (*SPreSave)(void);
|
||||
static void (*SPostSave)(void);
|
||||
|
@ -305,56 +308,73 @@ static int ReadStateChunks(FILE *st, int32 totalsize)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int CurrentState=1;
|
||||
extern int geniestage;
|
||||
|
||||
int FCEUSS_SaveFP(FILE *st)
|
||||
bool FCEUSS_SaveFP(FILE *st)
|
||||
{
|
||||
static uint32 totalsize;
|
||||
static uint8 header[16]="FCS";
|
||||
uint32 writeoffset;
|
||||
FILE* tmp = tmpfile();
|
||||
|
||||
writeoffset = ftell(st);
|
||||
memset(header+4,0,13);
|
||||
header[3]=0xFF;
|
||||
FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC);
|
||||
fwrite(header,1,16,st);
|
||||
FCEUPPU_SaveState();
|
||||
FCEUSND_SaveState();
|
||||
totalsize=WriteStateChunk(st,1,SFCPU);
|
||||
totalsize+=WriteStateChunk(st,2,SFCPUC);
|
||||
totalsize+=WriteStateChunk(st,3,FCEUPPU_STATEINFO);
|
||||
totalsize+=WriteStateChunk(st,4,FCEUCTRL_STATEINFO);
|
||||
totalsize+=WriteStateChunk(st,5,FCEUSND_STATEINFO);
|
||||
if(FCEUI_IsMovieActive())
|
||||
{
|
||||
totalsize+=WriteStateChunk(st,6,FCEUMOV_STATEINFO);
|
||||
uint32 size = FCEUMOV_WriteState(0);
|
||||
fputc(7,st);
|
||||
write32le(size, st);
|
||||
FCEUMOV_WriteState(st);
|
||||
totalsize += 5 + size;
|
||||
}
|
||||
// save back buffer
|
||||
{
|
||||
extern uint8 *XBackBuf;
|
||||
uint32 size = 256 * 256 + 8;
|
||||
fputc(8,st);
|
||||
write32le(size, st);
|
||||
fwrite(XBackBuf,1,size,st);
|
||||
totalsize += 5 + size;
|
||||
}
|
||||
uint32 totalsize = 0;
|
||||
|
||||
FCEUPPU_SaveState();
|
||||
FCEUSND_SaveState();
|
||||
totalsize=WriteStateChunk(tmp,1,SFCPU);
|
||||
totalsize+=WriteStateChunk(tmp,2,SFCPUC);
|
||||
totalsize+=WriteStateChunk(tmp,3,FCEUPPU_STATEINFO);
|
||||
totalsize+=WriteStateChunk(tmp,4,FCEUCTRL_STATEINFO);
|
||||
totalsize+=WriteStateChunk(tmp,5,FCEUSND_STATEINFO);
|
||||
if(FCEUI_IsMovieActive())
|
||||
{
|
||||
totalsize+=WriteStateChunk(tmp,6,FCEUMOV_STATEINFO);
|
||||
uint32 size = FCEUMOV_WriteState(0);
|
||||
fputc(7,tmp);
|
||||
write32le(size, tmp);
|
||||
FCEUMOV_WriteState(tmp);
|
||||
totalsize += 5 + size;
|
||||
}
|
||||
// save back buffer
|
||||
{
|
||||
extern uint8 *XBackBuf;
|
||||
uint32 size = 256 * 256 + 8;
|
||||
fputc(8,tmp);
|
||||
write32le(size, tmp);
|
||||
fwrite(XBackBuf,1,size,tmp);
|
||||
totalsize += 5 + size;
|
||||
}
|
||||
|
||||
if(SPreSave) SPreSave();
|
||||
totalsize+=WriteStateChunk(st,0x10,SFMDATA);
|
||||
totalsize+=WriteStateChunk(tmp,0x10,SFMDATA);
|
||||
if(SPreSave) SPostSave();
|
||||
|
||||
fseek(st,writeoffset+4,SEEK_SET);
|
||||
write32le(totalsize,st);
|
||||
return(1);
|
||||
//save the length of the file
|
||||
int len = (int)ftell(tmp);
|
||||
|
||||
//reload the savestate from the tempfile
|
||||
fseek(tmp,0,SEEK_SET);
|
||||
std::vector<uint8> buf(len);
|
||||
fread(&buf[0],1,len,tmp);
|
||||
fclose(tmp);
|
||||
|
||||
//compress it
|
||||
uint8* cbuf = new uint8[len*2]; //worst case compression, lets say twice the input buffer size
|
||||
uLongf comprlen;
|
||||
int error = compress2(cbuf,&comprlen,&buf[0],len,Z_BEST_COMPRESSION);
|
||||
|
||||
//dump the header
|
||||
uint8 header[16]="FCSX";
|
||||
FCEU_en32lsb(header+4, totalsize);
|
||||
FCEU_en32lsb(header+8, FCEU_VERSION_NUMERIC);
|
||||
FCEU_en32lsb(header+12, comprlen);
|
||||
|
||||
//dump it to the destination file
|
||||
fwrite(header,1,16,st);
|
||||
fwrite(cbuf,1,comprlen,st);
|
||||
|
||||
return error == Z_OK;
|
||||
}
|
||||
|
||||
|
||||
void FCEUSS_Save(char *fname)
|
||||
{
|
||||
FILE *st=NULL;
|
||||
|
@ -392,14 +412,38 @@ void FCEUSS_Save(char *fname)
|
|||
}
|
||||
}
|
||||
|
||||
int FCEUSS_LoadFP(FILE *st, ENUM_SSLOADPARAMS params)
|
||||
bool FCEUSS_LoadFP(FILE *st, ENUM_SSLOADPARAMS params)
|
||||
{
|
||||
if(params==SSLOADPARAM_DUMMY && suppress_scan_chunks)
|
||||
return 1;
|
||||
|
||||
int x;
|
||||
////--------------
|
||||
////read and decompress the savestate
|
||||
//uint32 comprlen, datalen;
|
||||
//if(!read32le(&datalen,st))
|
||||
// return false;
|
||||
//if(!read32le(&comprlen,st))
|
||||
// return false;
|
||||
//
|
||||
//std::vector<uint8> cbuf(comprlen);
|
||||
//std::vector<uint8> buf(datalen);
|
||||
//if(fread(&cbuf[0],1,comprlen,st) != comprlen)
|
||||
// return false;
|
||||
|
||||
//uLongf uncomprlen = datalen;
|
||||
//int error = uncompress(&buf[0],&uncomprlen,&cbuf[0],comprlen);
|
||||
//if(error != Z_OK || uncomprlen != datalen)
|
||||
// return false;
|
||||
|
||||
////dump savestate to a tempfile
|
||||
//FILE* tmp = tmpfile();
|
||||
//fwrite(&buf[0],0,datalen,tmp);
|
||||
//fseek(tmp,0,SEEK_SET);
|
||||
////-----------------
|
||||
|
||||
|
||||
bool x;
|
||||
uint8 header[16];
|
||||
int stateversion;
|
||||
char* fn=0;
|
||||
|
||||
//Make temporary savestate in case something screws up during the load
|
||||
|
@ -425,36 +469,50 @@ int FCEUSS_LoadFP(FILE *st, ENUM_SSLOADPARAMS params)
|
|||
}
|
||||
|
||||
if(params!=SSLOADPARAM_DUMMY)
|
||||
{
|
||||
FCEUMOV_PreLoad();
|
||||
}
|
||||
|
||||
//read and analyze the header
|
||||
fread(&header,1,16,st);
|
||||
if(memcmp(header,"FCS",3))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
if(header[3] == 0xFF)
|
||||
{
|
||||
stateversion = FCEU_de32lsb(header + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
stateversion=header[3] * 100;
|
||||
}
|
||||
if(memcmp(header,"FCSX",4))
|
||||
return false;
|
||||
int totalsize = FCEU_de32lsb(header + 4);
|
||||
int stateversion = FCEU_de32lsb(header + 8);
|
||||
int comprlen = FCEU_de32lsb(header + 12);
|
||||
|
||||
//load the compressed chunk and decompress
|
||||
std::vector<uint8> cbuf(comprlen);
|
||||
std::vector<uint8> buf(totalsize);
|
||||
if(fread(&cbuf[0],1,comprlen,st) != comprlen)
|
||||
return false;
|
||||
|
||||
uLongf uncomprlen = totalsize;
|
||||
int error = uncompress(&buf[0],&uncomprlen,&cbuf[0],comprlen);
|
||||
if(error != Z_OK || uncomprlen != totalsize)
|
||||
return false;
|
||||
|
||||
//dump it back to a tempfile
|
||||
FILE* tmp = tmpfile();
|
||||
fwrite(&buf[0],1,totalsize,tmp);
|
||||
fseek(tmp,0,SEEK_SET);
|
||||
|
||||
if(params == SSLOADPARAM_DUMMY)
|
||||
{
|
||||
scan_chunks=1;
|
||||
}
|
||||
x=ReadStateChunks(st,*(uint32*)(header+4));
|
||||
|
||||
x = ReadStateChunks(tmp,totalsize)!=0;
|
||||
|
||||
if(params == SSLOADPARAM_DUMMY)
|
||||
{
|
||||
scan_chunks=0;
|
||||
return 1;
|
||||
}
|
||||
if(read_sfcpuc && stateversion<9500)
|
||||
{
|
||||
X.IRQlow=0;
|
||||
fclose(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
//mbg 5/24/08 - we don't support old states, so this shouldnt matter.
|
||||
//if(read_sfcpuc && stateversion<9500)
|
||||
// X.IRQlow=0;
|
||||
|
||||
if(GameStateRestore)
|
||||
{
|
||||
GameStateRestore(stateversion);
|
||||
|
@ -463,7 +521,7 @@ int FCEUSS_LoadFP(FILE *st, ENUM_SSLOADPARAMS params)
|
|||
{
|
||||
FCEUPPU_LoadState(stateversion);
|
||||
FCEUSND_LoadState(stateversion);
|
||||
x=FCEUMOV_PostLoad();
|
||||
x=FCEUMOV_PostLoad()!=0;
|
||||
}
|
||||
|
||||
if(fn)
|
||||
|
@ -483,7 +541,8 @@ int FCEUSS_LoadFP(FILE *st, ENUM_SSLOADPARAMS params)
|
|||
free(fn);
|
||||
}
|
||||
|
||||
return(x);
|
||||
fclose(tmp);
|
||||
return x;
|
||||
}
|
||||
|
||||
int FCEUSS_Load(char *fname)
|
||||
|
|
|
@ -29,8 +29,8 @@ enum ENUM_SSLOADPARAMS
|
|||
|
||||
void FCEUSS_Save(char *);
|
||||
int FCEUSS_Load(char *);
|
||||
int FCEUSS_SaveFP(FILE *);
|
||||
int FCEUSS_LoadFP(FILE *, ENUM_SSLOADPARAMS);
|
||||
bool FCEUSS_SaveFP(FILE *);
|
||||
bool FCEUSS_LoadFP(FILE *, ENUM_SSLOADPARAMS);
|
||||
|
||||
extern int CurrentState;
|
||||
void FCEUSS_CheckStates(void);
|
||||
|
|
Loading…
Reference in New Issue