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