support loading TAS savestate
This commit is contained in:
parent
e524818f1e
commit
c24c415d2a
123
src/movie.cpp
123
src/movie.cpp
|
@ -89,18 +89,6 @@ int justAutoConverted = 0; //PLEASE REMOVE ME
|
||||||
/* Cache variables used for playback. */
|
/* Cache variables used for playback. */
|
||||||
static uint32 nextts = 0;
|
static uint32 nextts = 0;
|
||||||
static int32 nextd = 0;
|
static int32 nextd = 0;
|
||||||
|
|
||||||
SFORMAT FCEUMOV_STATEINFO[]={
|
|
||||||
{ joop, 4,"JOOP"},
|
|
||||||
{ &framets, 4|FCEUSTATE_RLSB, "FTS "},
|
|
||||||
{ &nextts, 4|FCEUSTATE_RLSB, "NXTS"},
|
|
||||||
{ &nextd, 4|FCEUSTATE_RLSB, "NXTD"},
|
|
||||||
{ &frameptr, 4|FCEUSTATE_RLSB, "FPTR"},
|
|
||||||
{ &framecount, 4|FCEUSTATE_RLSB, "FCNT"},
|
|
||||||
|
|
||||||
{ 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int MovieShow = 0;
|
static int MovieShow = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,12 +110,16 @@ static enum EMOVIEMODE
|
||||||
FILE* fpRecordingMovie = 0;
|
FILE* fpRecordingMovie = 0;
|
||||||
int currFrameCounter;
|
int currFrameCounter;
|
||||||
|
|
||||||
|
SFORMAT FCEUMOV_STATEINFO[]={
|
||||||
|
{ &currFrameCounter, 4|FCEUSTATE_RLSB, "FCNT"},
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
int FCEUMOV_GetFrame(void)
|
int FCEUMOV_GetFrame(void)
|
||||||
{
|
{
|
||||||
return currFrameCounter;
|
return currFrameCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FCEUMOV_ShouldPause(void)
|
bool FCEUMOV_ShouldPause(void)
|
||||||
{
|
{
|
||||||
if(pauseframe && currFrameCounter == pauseframe)
|
if(pauseframe && currFrameCounter == pauseframe)
|
||||||
|
@ -184,6 +176,9 @@ public:
|
||||||
std::vector<char> savestate;
|
std::vector<char> savestate;
|
||||||
std::vector<MovieRecord> records;
|
std::vector<MovieRecord> records;
|
||||||
|
|
||||||
|
//the entire contents of the disk file that was loaded
|
||||||
|
std::vector<char> serializedFile;
|
||||||
|
|
||||||
class TDictionary : public std::map<std::string,std::string>
|
class TDictionary : public std::map<std::string,std::string>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -236,22 +231,33 @@ public:
|
||||||
|
|
||||||
} currMovieData;
|
} currMovieData;
|
||||||
|
|
||||||
|
|
||||||
void DumpCurrentHeader(FILE* fp)
|
void DumpCurrentHeader(FILE* fp)
|
||||||
{
|
{
|
||||||
fprintf(fp,":version %d\n", currMovieData.version);
|
fprintf(fp,"version %d\n", currMovieData.version);
|
||||||
fprintf(fp,":emuVersion %d\n", currMovieData.emuVersion);
|
fprintf(fp,"emuVersion %d\n", currMovieData.emuVersion);
|
||||||
fprintf(fp,":palFlag %d\n", currMovieData.palFlag?1:0);
|
fprintf(fp,"palFlag %d\n", currMovieData.palFlag?1:0);
|
||||||
fprintf(fp,":poweronFlag %d\n", currMovieData.poweronFlag?1:0);
|
fprintf(fp,"poweronFlag %d\n", currMovieData.poweronFlag?1:0);
|
||||||
fprintf(fp,":resetFlag %d\n", currMovieData.resetFlag?1:0);
|
fprintf(fp,"resetFlag %d\n", currMovieData.resetFlag?1:0);
|
||||||
fprintf(fp,":romFilename %s\n", currMovieData.romFilename.c_str());
|
fprintf(fp,"romFilename %s\n", currMovieData.romFilename.c_str());
|
||||||
fprintf(fp,":romChecksum %s\n", BytesToString(currMovieData.romChecksum.data,MD5DATA::size).c_str());
|
fprintf(fp,"romChecksum %s\n", BytesToString(currMovieData.romChecksum.data,MD5DATA::size).c_str());
|
||||||
if(currMovieData.savestate.size() != 0)
|
if(currMovieData.savestate.size() != 0)
|
||||||
fprintf(fp,":savestate %s\n", BytesToString(&currMovieData.savestate[0],currMovieData.savestate.size()).c_str());
|
fprintf(fp,"savestate %s\n", BytesToString(&currMovieData.savestate[0],currMovieData.savestate.size()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//yuck... another custom text parser.
|
//yuck... another custom text parser.
|
||||||
void LoadFM2(MovieData& movieData, FILE *fp)
|
void LoadFM2(MovieData& movieData, FILE *fp)
|
||||||
{
|
{
|
||||||
|
//read the entire file so we can keep it handy.
|
||||||
|
//we could parse from that instead of the disk again...
|
||||||
|
|
||||||
|
fseek(fp,0,SEEK_END);
|
||||||
|
int len = ftell(fp);
|
||||||
|
fseek(fp,0,SEEK_SET);
|
||||||
|
movieData.serializedFile.resize(len);
|
||||||
|
fread(&movieData.serializedFile[0],1,len,fp);
|
||||||
|
fseek(fp,0,SEEK_SET);
|
||||||
|
|
||||||
MovieData::TDictionary dictionary;
|
MovieData::TDictionary dictionary;
|
||||||
|
|
||||||
std::string key,value;
|
std::string key,value;
|
||||||
|
@ -265,25 +271,23 @@ void LoadFM2(MovieData& movieData, FILE *fp)
|
||||||
if(c == -1)
|
if(c == -1)
|
||||||
goto bail;
|
goto bail;
|
||||||
bool iswhitespace = (c==' '||c=='\t');
|
bool iswhitespace = (c==' '||c=='\t');
|
||||||
bool iskeychar = (c==':');
|
bool isrecchar = (c=='|');
|
||||||
bool isnewline = (c==10||c==13);
|
bool isnewline = (c==10||c==13);
|
||||||
switch(state)
|
switch(state)
|
||||||
{
|
{
|
||||||
case NEWLINE:
|
case NEWLINE:
|
||||||
if(isnewline) goto done;
|
if(isnewline) goto done;
|
||||||
if(iskeychar)
|
if(iswhitespace) goto done;
|
||||||
{
|
if(isrecchar)
|
||||||
|
goto dorecord;
|
||||||
|
//must be a key
|
||||||
key = "";
|
key = "";
|
||||||
value = "";
|
value = "";
|
||||||
state = KEY;
|
goto dokey;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
goto dorecord;
|
|
||||||
break;
|
break;
|
||||||
case RECORD: {
|
case RECORD: {
|
||||||
dorecord:
|
dorecord:
|
||||||
MovieRecord record;
|
MovieRecord record;
|
||||||
ungetc(c,fp);
|
|
||||||
//for each joystick
|
//for each joystick
|
||||||
for(int i=0;i<4;i++)
|
for(int i=0;i<4;i++)
|
||||||
{
|
{
|
||||||
|
@ -550,8 +554,6 @@ static void movie_writechar(int c)
|
||||||
fputc(c,fpRecordingMovie);
|
fputc(c,fpRecordingMovie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//the main interaction point between the emulator and the movie system.
|
//the main interaction point between the emulator and the movie system.
|
||||||
//either dumps the current joystick state or loads one state from the movie
|
//either dumps the current joystick state or loads one state from the movie
|
||||||
void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
||||||
|
@ -585,6 +587,8 @@ void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
||||||
}
|
}
|
||||||
else if(movieMode == MOVIEMODE_RECORD)
|
else if(movieMode == MOVIEMODE_RECORD)
|
||||||
{
|
{
|
||||||
|
movie_writechar('|');
|
||||||
|
|
||||||
//for each joystick
|
//for each joystick
|
||||||
for(int i=0;i<4;i++)
|
for(int i=0;i<4;i++)
|
||||||
{
|
{
|
||||||
|
@ -619,9 +623,13 @@ void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
void FCEUMOV_AddCommand(int cmd)
|
void FCEUMOV_AddCommand(int cmd)
|
||||||
{
|
{
|
||||||
if(current <= 0) return; // Return if not recording a movie
|
// do nothing if not recording a movie
|
||||||
|
if(movieMode != MOVIEMODE_RECORD)
|
||||||
|
return;
|
||||||
|
|
||||||
//printf("%d\n",cmd);
|
//printf("%d\n",cmd);
|
||||||
|
|
||||||
//MBG TODO BIG TODO TODO TODO
|
//MBG TODO BIG TODO TODO TODO
|
||||||
|
@ -688,24 +696,53 @@ void FCEU_DrawMovies(uint8 *XBuf)
|
||||||
|
|
||||||
int FCEUMOV_WriteState(FILE* st)
|
int FCEUMOV_WriteState(FILE* st)
|
||||||
{
|
{
|
||||||
uint32 to_write = 0;
|
//we are supposed to dump the movie data into the savestate
|
||||||
if(current < 0)
|
|
||||||
to_write = moviedatasize;
|
|
||||||
else if(current > 0)
|
|
||||||
to_write = frameptr;
|
|
||||||
|
|
||||||
if(!st)
|
if(movieMode == MOVIEMODE_RECORD)
|
||||||
return to_write;
|
{
|
||||||
|
int todo = ftell(fpRecordingMovie);
|
||||||
|
if(st)
|
||||||
|
{
|
||||||
|
fseek(fpRecordingMovie,0,SEEK_SET);
|
||||||
|
std::vector<uint8> tempbuf(todo);
|
||||||
|
fread(&tempbuf[0],1,todo,fpRecordingMovie);
|
||||||
|
fwrite(&tempbuf[0],1,todo,st);
|
||||||
|
}
|
||||||
|
return todo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int todo = currMovieData.serializedFile.size();
|
||||||
|
if(st)
|
||||||
|
{
|
||||||
|
fwrite(&currMovieData.serializedFile[0],1,currMovieData.serializedFile.size(),st);
|
||||||
|
}
|
||||||
|
return todo;
|
||||||
|
}
|
||||||
|
|
||||||
if(to_write)
|
|
||||||
fwrite(moviedata, 1, to_write, st);
|
|
||||||
return to_write;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_successful;
|
static bool load_successful;
|
||||||
|
|
||||||
int FCEUMOV_ReadState(FILE* st, uint32 size)
|
int FCEUMOV_ReadState(FILE* st, uint32 size)
|
||||||
{
|
{
|
||||||
|
load_successful = false;
|
||||||
|
|
||||||
|
//write the state to disk so we can reload
|
||||||
|
std::vector<uint8> buf(size);
|
||||||
|
fread(&buf[0],1,size,st);
|
||||||
|
FILE* tmp = tmpfile();
|
||||||
|
fwrite(&buf[0],1,size,tmp);
|
||||||
|
fseek(tmp,0,SEEK_SET);
|
||||||
|
currMovieData = MovieData();
|
||||||
|
LoadFM2(currMovieData, tmp);
|
||||||
|
fclose(tmp);
|
||||||
|
|
||||||
|
//todo - switch to recording
|
||||||
|
|
||||||
|
movieMode = MOVIEMODE_PLAY;
|
||||||
|
load_successful = true;
|
||||||
|
|
||||||
//// if this savestate was made while replaying,
|
//// if this savestate was made while replaying,
|
||||||
//// we need to "undo" nextd and nextts
|
//// we need to "undo" nextd and nextts
|
||||||
//if(nextd != -1)
|
//if(nextd != -1)
|
||||||
|
|
Loading…
Reference in New Issue