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:
parent
4456368632
commit
9006fd7a73
|
@ -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.
|
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.
|
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
|
08-may-2010 - ugetab - Added savestate.object() which is savestate.create() with intuitive numbering under windows
|
||||||
|
|
|
@ -336,7 +336,7 @@ void FCEU_DrawRecordingStatus(uint8* XBuf)
|
||||||
drawstatus(XBuf-ClipSidesOffset,2,28,0);
|
drawstatus(XBuf-ClipSidesOffset,2,28,0);
|
||||||
hasPlayRecIcon = true;
|
hasPlayRecIcon = true;
|
||||||
}
|
}
|
||||||
else if(FCEUMOV_Mode(MOVIEMODE_PLAY))
|
else if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_FINISHED))
|
||||||
{
|
{
|
||||||
drawstatus(XBuf-ClipSidesOffset,1,28,0);
|
drawstatus(XBuf-ClipSidesOffset,1,28,0);
|
||||||
hasPlayRecIcon = true;
|
hasPlayRecIcon = true;
|
||||||
|
|
|
@ -1237,14 +1237,14 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||||
hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS");
|
hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS");
|
||||||
|
|
||||||
//If There is a movie loaded in read only
|
//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);
|
hfceuxcontextsub = GetSubMenu(hfceuxcontext,0);
|
||||||
whichContext = 0; // Game+Movie+readonly
|
whichContext = 0; // Game+Movie+readonly
|
||||||
}
|
}
|
||||||
|
|
||||||
//If there is a movie loaded in read+write
|
//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);
|
hfceuxcontextsub = GetSubMenu(hfceuxcontext,3);
|
||||||
whichContext = 3; // Game+Movie+readwrite
|
whichContext = 3; // Game+Movie+readwrite
|
||||||
|
@ -2484,7 +2484,7 @@ void FCEUD_AviRecordTo(void)
|
||||||
aviDirectory.append("\\"); //if directory override has no \ then add one
|
aviDirectory.append("\\"); //if directory override has no \ then add one
|
||||||
|
|
||||||
//if we are playing a movie, construct the filename from the current movie.
|
//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 = GetMfn(); //get movie filename
|
||||||
tempFilename.erase(0,1); //remove dot
|
tempFilename.erase(0,1); //remove dot
|
||||||
|
|
|
@ -611,7 +611,7 @@ void AutoFire(void)
|
||||||
//doesn't get screwed up when loading.
|
//doesn't get screwed up when loading.
|
||||||
if(FCEUMOV_Mode(MOVIEMODE_RECORD | MOVIEMODE_PLAY))
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1032,7 +1032,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
|
||||||
|
|
||||||
case FCEUI_STOPMOVIE:
|
case FCEUI_STOPMOVIE:
|
||||||
case FCEUI_PLAYFROMBEGINNING:
|
case FCEUI_PLAYFROMBEGINNING:
|
||||||
return FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD);
|
return (FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED));
|
||||||
|
|
||||||
case FCEUI_STOPAVI:
|
case FCEUI_STOPAVI:
|
||||||
return FCEUI_AviIsRecording();
|
return FCEUI_AviIsRecording();
|
||||||
|
@ -1043,7 +1043,7 @@ bool FCEU_IsValidUI(EFCEUI ui)
|
||||||
|
|
||||||
case FCEUI_RESET:
|
case FCEUI_RESET:
|
||||||
if(!GameInfo) return false;
|
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;
|
break;
|
||||||
|
|
||||||
case FCEUI_POWER:
|
case FCEUI_POWER:
|
||||||
|
|
|
@ -2161,7 +2161,7 @@ static int zapper_read(lua_State *L){
|
||||||
int z = 0;
|
int z = 0;
|
||||||
extern void GetMouseData(uint32 (&md)[3]); //adelikat: shouldn't this be ifdef'ed for Win32?
|
extern void GetMouseData(uint32 (&md)[3]); //adelikat: shouldn't this be ifdef'ed for Win32?
|
||||||
int x,y,click;
|
int x,y,click;
|
||||||
if (/*FCEUMOV_IsPlaying()*/ FCEUMOV_Mode(MOVIEMODE_PLAY))
|
if (FCEUMOV_Mode(MOVIEMODE_PLAY))
|
||||||
{
|
{
|
||||||
if (!currFrameCounter)
|
if (!currFrameCounter)
|
||||||
z = 0;
|
z = 0;
|
||||||
|
@ -2580,10 +2580,12 @@ int emu_emulating(lua_State *L) {
|
||||||
|
|
||||||
// string movie.mode()
|
// string movie.mode()
|
||||||
//
|
//
|
||||||
// "record", "playback" or nil
|
// "record", "playback", "finished", or nil
|
||||||
int movie_mode(lua_State *L) {
|
int movie_mode(lua_State *L) {
|
||||||
if (FCEUMOV_IsRecording())
|
if (FCEUMOV_IsRecording())
|
||||||
lua_pushstring(L, "record");
|
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())
|
else if (FCEUMOV_IsPlaying())
|
||||||
lua_pushstring(L, "playback");
|
lua_pushstring(L, "playback");
|
||||||
else
|
else
|
||||||
|
|
|
@ -721,7 +721,7 @@ void FCEUI_StopMovie()
|
||||||
if(suppressMovieStop)
|
if(suppressMovieStop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(movieMode == MOVIEMODE_PLAY)
|
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED)
|
||||||
StopPlayback();
|
StopPlayback();
|
||||||
else if(movieMode == MOVIEMODE_RECORD)
|
else if(movieMode == MOVIEMODE_RECORD)
|
||||||
StopRecording();
|
StopRecording();
|
||||||
|
@ -834,7 +834,7 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus
|
||||||
assert(fname);
|
assert(fname);
|
||||||
|
|
||||||
//mbg 6/10/08 - we used to call StopMovie here, but that cleared curMovieFilename and gave us crashes...
|
//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();
|
StopPlayback();
|
||||||
else if(movieMode == MOVIEMODE_RECORD)
|
else if(movieMode == MOVIEMODE_RECORD)
|
||||||
StopRecording();
|
StopRecording();
|
||||||
|
@ -978,6 +978,14 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author)
|
||||||
|
|
||||||
static int _currCommand = 0;
|
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.
|
//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_AddInputState()
|
void FCEUMOV_AddInputState()
|
||||||
|
@ -1009,9 +1017,9 @@ void FCEUMOV_AddInputState()
|
||||||
else if(movieMode == MOVIEMODE_PLAY)
|
else if(movieMode == MOVIEMODE_PLAY)
|
||||||
{
|
{
|
||||||
//stop when we run out of frames
|
//stop when we run out of frames
|
||||||
if(currFrameCounter == currMovieData.records.size())
|
if(currFrameCounter == (int)currMovieData.records.size())
|
||||||
{
|
{
|
||||||
StopPlayback();
|
FinishPlayback();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1099,6 +1107,8 @@ void FCEU_DrawMovies(uint8 *XBuf)
|
||||||
sprintf(counterbuf,"%d/%d",currFrameCounter,currMovieData.records.size());
|
sprintf(counterbuf,"%d/%d",currFrameCounter,currMovieData.records.size());
|
||||||
else if(movieMode == MOVIEMODE_RECORD)
|
else if(movieMode == MOVIEMODE_RECORD)
|
||||||
sprintf(counterbuf,"%d",currMovieData.records.size());
|
sprintf(counterbuf,"%d",currMovieData.records.size());
|
||||||
|
else if (movieMode == MOVIEMODE_FINISHED)
|
||||||
|
sprintf(counterbuf,"%d/%d (finished)",currFrameCounter,currMovieData.records.size());
|
||||||
else
|
else
|
||||||
sprintf(counterbuf,"%d (no movie)",currFrameCounter);
|
sprintf(counterbuf,"%d (no movie)",currFrameCounter);
|
||||||
|
|
||||||
|
@ -1127,7 +1137,7 @@ void FCEU_DrawLagCounter(uint8 *XBuf)
|
||||||
int FCEUMOV_WriteState(std::ostream* os)
|
int FCEUMOV_WriteState(std::ostream* os)
|
||||||
{
|
{
|
||||||
//we are supposed to dump the movie data into the savestate
|
//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);
|
return currMovieData.dump(os, true);
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
@ -1151,7 +1161,7 @@ bool FCEUMOV_ReadState(std::istream* is, uint32 size)
|
||||||
is->seekg((uint32)curr+size);
|
is->seekg((uint32)curr+size);
|
||||||
extern bool FCEU_state_loading_old_format;
|
extern bool FCEU_state_loading_old_format;
|
||||||
if(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();
|
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)");
|
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
|
// 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
|
//handle moviefile mismatch
|
||||||
if(tempMovieData.guid != currMovieData.guid)
|
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 the frame counter is longer than our current movie, then error
|
||||||
if(currFrameCounter > (int)currMovieData.records.size())
|
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);
|
FinishPlayback();
|
||||||
return false;
|
//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;
|
movieMode = MOVIEMODE_PLAY;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,8 @@ enum EMOVIEMODE
|
||||||
MOVIEMODE_INACTIVE = 1,
|
MOVIEMODE_INACTIVE = 1,
|
||||||
MOVIEMODE_RECORD = 2,
|
MOVIEMODE_RECORD = 2,
|
||||||
MOVIEMODE_PLAY = 4,
|
MOVIEMODE_PLAY = 4,
|
||||||
MOVIEMODE_TASEDIT = 8
|
MOVIEMODE_TASEDIT = 8,
|
||||||
|
MOVIEMODE_FINISHED = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EMOVIECMD
|
enum EMOVIECMD
|
||||||
|
@ -72,8 +73,9 @@ enum EMOVIECMD
|
||||||
EMOVIEMODE FCEUMOV_Mode();
|
EMOVIEMODE FCEUMOV_Mode();
|
||||||
bool FCEUMOV_Mode(EMOVIEMODE modemask);
|
bool FCEUMOV_Mode(EMOVIEMODE modemask);
|
||||||
bool FCEUMOV_Mode(int 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_IsRecording() { return FCEUMOV_Mode(MOVIEMODE_RECORD); }
|
||||||
|
inline bool FCEUMOV_IsFinished() { return FCEUMOV_Mode(MOVIEMODE_FINISHED);}
|
||||||
|
|
||||||
bool FCEUMOV_ShouldPause(void);
|
bool FCEUMOV_ShouldPause(void);
|
||||||
int FCEUMOV_GetFrame(void);
|
int FCEUMOV_GetFrame(void);
|
||||||
|
|
|
@ -284,7 +284,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
|
||||||
read_snd=1;
|
read_snd=1;
|
||||||
break;
|
break;
|
||||||
case 6:
|
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;
|
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,31,FCEU_NEWPPU_STATEINFO);
|
||||||
totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO);
|
totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO);
|
||||||
totalsize+=WriteStateChunk(os,5,FCEUSND_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);
|
totalsize+=WriteStateChunk(os,6,FCEUMOV_STATEINFO);
|
||||||
|
|
||||||
|
@ -776,7 +776,7 @@ bool FCEUSS_Load(const char *fname)
|
||||||
//Update input display if movie is loaded
|
//Update input display if movie is loaded
|
||||||
extern uint32 cur_input_display;
|
extern uint32 cur_input_display;
|
||||||
extern uint8 FCEU_GetJoyJoy(void);
|
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);
|
memcpy(&cur_input_display,currMovieData.records[currFrameCounter-1].joysticks.data,4);
|
||||||
else
|
else
|
||||||
cur_input_display = FCEU_GetJoyJoy();
|
cur_input_display = FCEU_GetJoyJoy();
|
||||||
|
|
Loading…
Reference in New Issue