diff --git a/src/movie.cpp b/src/movie.cpp index 215b43b2..87b09cb3 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -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 diff --git a/src/state.cpp b/src/state.cpp index fbf62955..cd19b3a3 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -27,6 +27,8 @@ #include //#include //mbg merge 7/17/06 removed +#include + #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 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 cbuf(comprlen); + //std::vector 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 cbuf(comprlen); + std::vector 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) diff --git a/src/state.h b/src/state.h index eada00a8..d5f0de58 100644 --- a/src/state.h +++ b/src/state.h @@ -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);