Movies now have a "finished" option. If a playback stops the movie isn't cleared from memory, and can be replayed or a state loaded. Similar functionality as DeSmuME and GENS rerecording.

This commit is contained in:
adelikat 2010-05-12 15:31:24 +00:00
parent 4456368632
commit 9006fd7a73
8 changed files with 41 additions and 24 deletions

View File

@ -1,4 +1,5 @@
11-may-2010 - 10-may-2010 - adelikat - Loadstate updates input display
12-may-2010 - adelikat - Movies now have a "finished" option. If a playback stops the movie isn't cleared from memory, and can be replayed or a state loaded. Similar functionality as DeSmuME and GENS rerecording
11-may-2010 - adelikat - Loadstate updates input display
11-may-2010 - ugetab - Win32 - Added Ram Search hotkeys for the first 6 search types in the list.
10-may-2010 - ugetab - Added gui.getpixel() which gets any gui.pixel() set pixel colors, and possibly other functions. Added emu.getscreenpixel() which gets the RGB and Palette of any pixel on the screen.
08-may-2010 - ugetab - Added savestate.object() which is savestate.create() with intuitive numbering under windows

View File

@ -336,7 +336,7 @@ void FCEU_DrawRecordingStatus(uint8* XBuf)
drawstatus(XBuf-ClipSidesOffset,2,28,0);
hasPlayRecIcon = true;
}
else if(FCEUMOV_Mode(MOVIEMODE_PLAY))
else if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED))
{
drawstatus(XBuf-ClipSidesOffset,1,28,0);
hasPlayRecIcon = true;

View File

@ -1237,14 +1237,14 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS");
//If There is a movie loaded in read only
if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD) && movie_readonly)
if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && movie_readonly)
{
hfceuxcontextsub = GetSubMenu(hfceuxcontext,0);
whichContext = 0; // Game+Movie+readonly
}
//If there is a movie loaded in read+write
else if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD) && !movie_readonly)
else if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && !movie_readonly)
{
hfceuxcontextsub = GetSubMenu(hfceuxcontext,3);
whichContext = 3; // Game+Movie+readwrite
@ -2484,7 +2484,7 @@ void FCEUD_AviRecordTo(void)
aviDirectory.append("\\"); //if directory override has no \ then add one
//if we are playing a movie, construct the filename from the current movie.
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD))
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD)) //adelikat: TOOD: Think about this. I think MOVIEMODE_FINISHED shouldn't not be included here. Am I wrong?
{
tempFilename = GetMfn(); //get movie filename
tempFilename.erase(0,1); //remove dot

View File

@ -611,7 +611,7 @@ void AutoFire(void)
//doesn't get screwed up when loading.
if(FCEUMOV_Mode(MOVIEMODE_RECORD | MOVIEMODE_PLAY))
{
rapidAlternator= AutoFirePattern[(AutoFireOffset + FCEUMOV_GetFrame())%AutoFirePatternLength];
rapidAlternator= AutoFirePattern[(AutoFireOffset + FCEUMOV_GetFrame())%AutoFirePatternLength]; //adelikat: TODO: Think through this, MOVIEMODE_FINISHED should not use movie data for auto-fire?
}
else
{
@ -1032,7 +1032,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
case FCEUI_STOPMOVIE:
case FCEUI_PLAYFROMBEGINNING:
return FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD);
return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED));
case FCEUI_STOPAVI:
return FCEUI_AviIsRecording();
@ -1043,7 +1043,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
case FCEUI_RESET:
if(!GameInfo) return false;
if(FCEUMOV_Mode(MOVIEMODE_TASEDIT|MOVIEMODE_PLAY)) return false;
if(FCEUMOV_Mode(MOVIEMODE_FINISHED|MOVIEMODE_TASEDIT|MOVIEMODE_PLAY)) return false;
break;
case FCEUI_POWER:

View File

@ -2161,7 +2161,7 @@ static int zapper_read(lua_State *L){
int z = 0;
extern void GetMouseData(uint32 (&md)[3]); //adelikat: shouldn't this be ifdef'ed for Win32?
int x,y,click;
if (/*FCEUMOV_IsPlaying()*/ FCEUMOV_Mode(MOVIEMODE_PLAY))
if (FCEUMOV_Mode(MOVIEMODE_PLAY))
{
if (!currFrameCounter)
z = 0;
@ -2580,10 +2580,12 @@ int emu_emulating(lua_State *L) {
// string movie.mode()
//
// "record", "playback" or nil
// "record", "playback", "finished", or nil
int movie_mode(lua_State *L) {
if (FCEUMOV_IsRecording())
lua_pushstring(L, "record");
else if (FCEUMOV_IsFinished())
lua_pushstring(L, "finished"); //Note: this comes before plaback since playback checks for finished as well
else if (FCEUMOV_IsPlaying())
lua_pushstring(L, "playback");
else

View File

@ -721,7 +721,7 @@ void FCEUI_StopMovie()
if(suppressMovieStop)
return;
if(movieMode == MOVIEMODE_PLAY)
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED)
StopPlayback();
else if(movieMode == MOVIEMODE_RECORD)
StopRecording();
@ -834,7 +834,7 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus
assert(fname);
//mbg 6/10/08 - we used to call StopMovie here, but that cleared curMovieFilename and gave us crashes...
if(movieMode == MOVIEMODE_PLAY)
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED)
StopPlayback();
else if(movieMode == MOVIEMODE_RECORD)
StopRecording();
@ -978,6 +978,14 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author)
static int _currCommand = 0;
// Stop movie playback without closing the movie.
static void FinishPlayback()
{
FCEU_DispMessage("Movie finished playing.");
movieMode = MOVIEMODE_FINISHED;
}
//the main interaction point between the emulator and the movie system.
//either dumps the current joystick state or loads one state from the movie
void FCEUMOV_AddInputState()
@ -1009,9 +1017,9 @@ void FCEUMOV_AddInputState()
else if(movieMode == MOVIEMODE_PLAY)
{
//stop when we run out of frames
if(currFrameCounter == currMovieData.records.size())
if(currFrameCounter == (int)currMovieData.records.size())
{
StopPlayback();
FinishPlayback();
}
else
{
@ -1099,6 +1107,8 @@ void FCEU_DrawMovies(uint8 *XBuf)
sprintf(counterbuf,"%d/%d",currFrameCounter,currMovieData.records.size());
else if(movieMode == MOVIEMODE_RECORD)
sprintf(counterbuf,"%d",currMovieData.records.size());
else if (movieMode == MOVIEMODE_FINISHED)
sprintf(counterbuf,"%d/%d (finished)",currFrameCounter,currMovieData.records.size());
else
sprintf(counterbuf,"%d (no movie)",currFrameCounter);
@ -1127,7 +1137,7 @@ void FCEU_DrawLagCounter(uint8 *XBuf)
int FCEUMOV_WriteState(std::ostream* os)
{
//we are supposed to dump the movie data into the savestate
if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY)
if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED)
return currMovieData.dump(os, true);
else return 0;
}
@ -1151,7 +1161,7 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
is->seekg((uint32)curr+size);
extern bool FCEU_state_loading_old_format;
if(FCEU_state_loading_old_format) {
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD) {
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_FINISHED) {
FCEUI_StopMovie();
FCEU_PrintError("You have tried to use an old savestate while playing a movie. This is unsupported (since the old savestate has old-format movie data in it which can't be converted on the fly)");
}
@ -1178,7 +1188,7 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
// then, we must discard this movie and just load the savestate
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD)
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_FINISHED)
{
//handle moviefile mismatch
if(tempMovieData.guid != currMovieData.guid)
@ -1203,8 +1213,10 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
//if the frame counter is longer than our current movie, then error
if(currFrameCounter > (int)currMovieData.records.size())
{
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);
return false;
FinishPlayback();
//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);
//return false;
}
movieMode = MOVIEMODE_PLAY;
}

View File

@ -58,7 +58,8 @@ enum EMOVIEMODE
MOVIEMODE_INACTIVE = 1,
MOVIEMODE_RECORD = 2,
MOVIEMODE_PLAY = 4,
MOVIEMODE_TASEDIT = 8
MOVIEMODE_TASEDIT = 8,
MOVIEMODE_FINISHED = 16
};
enum EMOVIECMD
@ -72,8 +73,9 @@ enum EMOVIECMD
EMOVIEMODE FCEUMOV_Mode();
bool FCEUMOV_Mode(EMOVIEMODE modemask);
bool FCEUMOV_Mode(int modemask);
inline bool FCEUMOV_IsPlaying() { return FCEUMOV_Mode(MOVIEMODE_PLAY); }
inline bool FCEUMOV_IsPlaying() { return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED)); }
inline bool FCEUMOV_IsRecording() { return FCEUMOV_Mode(MOVIEMODE_RECORD); }
inline bool FCEUMOV_IsFinished() { return FCEUMOV_Mode(MOVIEMODE_FINISHED);}
bool FCEUMOV_ShouldPause(void);
int FCEUMOV_GetFrame(void);

View File

@ -284,7 +284,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
read_snd=1;
break;
case 6:
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD))
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED))
{
if(!ReadStateChunk(is,FCEUMOV_STATEINFO,size)) ret=false;
}
@ -372,7 +372,7 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
totalsize+=WriteStateChunk(os,31,FCEU_NEWPPU_STATEINFO);
totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO);
totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO);
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD))
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED))
{
totalsize+=WriteStateChunk(os,6,FCEUMOV_STATEINFO);
@ -776,7 +776,7 @@ 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) || FCEUMOV_Mode(MOVIEMODE_PLAY)) //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.
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();