compress savestates, and movie no longer needs to do any compression itsself.

savestate compatibility is now broken.
This commit is contained in:
zeromus 2008-05-24 21:25:20 +00:00
parent bf6d70c56d
commit e524818f1e
3 changed files with 132 additions and 94 deletions

View File

@ -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

View File

@ -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;
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;
}
FILE* tmp = tmpfile();
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)

View File

@ -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);