Fixed up more loadstate logic. We had a slight logic error this whole time that wasn't a problem until now. Checking to see if a state is a future event, we assumed frame counter of the state matched the length of the movie. Now that movie finished is a mode, that is no longer true. Fixed that, and fixed the input display updating at the end of a load state to always look at the state input rather than the statemovie last record. This fixes proper behavior of saving and loading states during movie finished mode as per the "Laws of TAS": http://tasvideos.org/Adelikat/LawsOfTAS.html

This commit is contained in:
adelikat 2010-05-15 21:22:16 +00:00
parent 473b954991
commit 7c06c4d2ab
2 changed files with 10 additions and 10 deletions

View File

@ -1084,7 +1084,7 @@ void FCEUMOV_AddInputState()
else if(movieMode == MOVIEMODE_PLAY)
{
//stop when we run out of frames
if(currFrameCounter == (int)currMovieData.records.size())
if(currFrameCounter >= (int)currMovieData.records.size())
{
FinishPlayback();
}
@ -1307,11 +1307,13 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
if (sameTimeline)
{
//if the frame counter is longer than our current movie, then error
if(currFrameCounter > (int)currMovieData.records.size()) //adelikat: TODO: finished mode needs something different here
//if we made it this far, then the savestate has identical movie data but we want to know now if the stateMOVIE size is greater than current movie size and make this error
//then we want to know if currFramecoutner > currmoviedata.records.size so we can know it is time for movie finished handling
//currFrameCounter is currently savestate frame counter (not savestate movie size
if(tempMovieData.records.size() > currMovieData.records.size())
{
//TODO: turn frame counter to red to get attention
FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", currFrameCounter, currMovieData.records.size()-1);
FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", tempMovieData.records.size(), currMovieData.records.size()-1);
return false;
}
movieMode = MOVIEMODE_PLAY;
@ -1323,7 +1325,7 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
return false;
}
}
else
else //Read + write
{
//truncate before we copy, just to save some time
tempMovieData.truncateAt(currFrameCounter);

View File

@ -776,11 +776,9 @@ bool FCEUSS_Load(const char *fname)
//Update input display if movie is loaded
extern uint32 cur_input_display;
extern uint8 FCEU_GetJoyJoy(void);
if (FCEUMOV_Mode(MOVIEMODE_RECORD|MOVIEMODE_PLAY|MOVIEMODE_FINISHED)) //adelikat: just doing GetJoyJoy regardless should work, but I just felt conceptually movies should be relying on movie data. There might be some fringe cases where this is necessary.
memcpy(&cur_input_display,currMovieData.records[currFrameCounter-1].joysticks.data,4);
else
cur_input_display = FCEU_GetJoyJoy();
cur_input_display = FCEU_GetJoyJoy(); //Input display should show the last buttons pressed (stored in the savestate)
return true;
}
else