From 2d81852e819bfbd7e530cb1fe005adb272769d4c Mon Sep 17 00:00:00 2001 From: aquanull Date: Wed, 4 Apr 2018 18:28:42 +0800 Subject: [PATCH 01/18] Fixes for some file handles and memory leaks. --- src/drivers/win/replay.cpp | 12 +++++++++--- src/emufile.cpp | 1 + src/file.cpp | 7 ++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/drivers/win/replay.cpp b/src/drivers/win/replay.cpp index ca998dcf..fb5cd8d1 100644 --- a/src/drivers/win/replay.cpp +++ b/src/drivers/win/replay.cpp @@ -126,7 +126,10 @@ void UpdateReplayCommentsSubs(const char * fname) { MOVIE_INFO info; FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0); - fp->stream = fp->stream->memwrap(); + EMUFILE *tmp = fp->stream->memwrap(); + if (tmp != fp->stream) + delete fp->stream; + fp->stream = tmp; bool scanok = FCEUI_MovieGetInfo(fp, info, true); delete fp; @@ -151,8 +154,11 @@ void UpdateReplayDialog(HWND hwndDlg) { MOVIE_INFO info; - FCEUFILE* fp = FCEU_fopen(fn,0,"rb",0); - fp->stream = fp->stream->memwrap(); + FCEUFILE *fp = FCEU_fopen(fn,0,"rb",0); + EMUFILE *tmp = fp->stream->memwrap(); + if (tmp != fp->stream) + delete fp->stream; + fp->stream = tmp; bool isarchive = FCEU_isFileInArchive(fn); bool ismovie = FCEUI_MovieGetInfo(fp, info, false); delete fp; diff --git a/src/emufile.cpp b/src/emufile.cpp index 5102f2ce..162e8df0 100644 --- a/src/emufile.cpp +++ b/src/emufile.cpp @@ -86,6 +86,7 @@ void EMUFILE_FILE::truncate(s32 length) #else ftruncate(fileno(fp),length); #endif + // this is probably wrong if mode is "wb" fclose(fp); fp = NULL; open(fname.c_str(),mode); diff --git a/src/file.cpp b/src/file.cpp index a13c04a9..3ef0bf6a 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -284,11 +284,16 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext { //if the archive contained no files, try to open it the old fashioned way EMUFILE_FILE* fp = FCEUD_UTF8_fstream(fileToOpen,mode); - if(!fp || (fp->get_fp() == NULL)) + if(!fp) + return 0; + if (fp->get_fp() == NULL) { + //fp is new'ed so it has to be deleted + delete fp; return 0; } + //try to read a zip file { fceufp = TryUnzip(fileToOpen); From 7f8e2dd7e86c53a4b0c7471868ba46f8450ce1e6 Mon Sep 17 00:00:00 2001 From: aquanull Date: Thu, 5 Apr 2018 18:46:19 +0800 Subject: [PATCH 02/18] Fixes the focus bug of the main window minimized with clicks on Windows Taskbar. --- src/drivers/win/window.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 5fc4583b..b9dd376b 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -1443,7 +1443,9 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) goto proco; case WM_SIZE: - if (!fullscreen && !changerecursive && !windowedfailed) + if (wParam == SIZE_MINIMIZED) + nofocus = 1; + else if (!fullscreen && !changerecursive && !windowedfailed) { switch(wParam) { @@ -2420,6 +2422,7 @@ adelikat: Outsourced this to a remappable hotkey DoFCEUExit(); break; case WM_SETFOCUS: + nofocus = 0; if (wasPausedByCheats) { EmulationPaused = 0; From 9560521507f98cfe111c80872641c5de5969646b Mon Sep 17 00:00:00 2001 From: aquanull Date: Fri, 13 Apr 2018 11:59:23 +0800 Subject: [PATCH 03/18] RAM Watch now respects Directories Configuration for Memory Watch. --- src/drivers/win/ramwatch.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/drivers/win/ramwatch.cpp b/src/drivers/win/ramwatch.cpp index 55bae1d4..0caa1d0a 100644 --- a/src/drivers/win/ramwatch.cpp +++ b/src/drivers/win/ramwatch.cpp @@ -470,7 +470,7 @@ void OpenRWRecentFile(int memwRFileNumber) return; } -int Change_File_L(char *Dest, char *Dir, char *Titre, char *Filter, char *Ext, HWND hwnd) +int Change_File_L(char *Dest, const char *Dir, const char *Titre, const char *Filter, const char *Ext, HWND hwnd) { OPENFILENAME ofn; @@ -501,7 +501,7 @@ int Change_File_L(char *Dest, char *Dir, char *Titre, char *Filter, char *Ext, H return 0; } -int Change_File_S(char *Dest, char *Dir, char *Titre, char *Filter, char *Ext, HWND hwnd) +int Change_File_S(char *Dest, const char *Dir, const char *Titre, const char *Filter, const char *Ext, HWND hwnd) { OPENFILENAME ofn; @@ -536,11 +536,12 @@ int Change_File_S(char *Dest, char *Dir, char *Titre, char *Filter, char *Ext, H bool Save_Watches() { + string initdir = FCEU_GetPath(FCEUMKF_MEMW); const char* slash = max(strrchr(gamefilename, '|'), max(strrchr(gamefilename, '\\'), strrchr(gamefilename, '/'))); strcpy(Str_Tmp,slash ? slash+1 : gamefilename); char* dot = strrchr(Str_Tmp, '.'); if(dot) *dot = 0; - if(Change_File_S(Str_Tmp, applicationPath, "Save Watches", "Watchlist (*.wch)\0*.wch\0All Files (*.*)\0*.*\0\0", "wch", RamWatchHWnd)) + if(Change_File_S(Str_Tmp, initdir.c_str(), "Save Watches", "Watchlist (*.wch)\0*.wch\0All Files (*.*)\0*.*\0\0", "wch", RamWatchHWnd)) { FILE *WatchFile = fopen(Str_Tmp,"w+b"); fputc('\n',WatchFile); @@ -655,12 +656,13 @@ bool Load_Watches(bool clear, const char* filename) bool Load_Watches(bool clear) { + string initdir = FCEU_GetPath(FCEUMKF_MEMW); const char* slash = max(strrchr(gamefilename, '|'), max(strrchr(gamefilename, '\\'), strrchr(gamefilename, '/'))); strcpy(Str_Tmp,slash ? slash+1 : gamefilename); char* dot = strrchr(Str_Tmp, '.'); if(dot) *dot = 0; strcat(Str_Tmp,".wch"); - if(Change_File_L(Str_Tmp, applicationPath, "Load Watches", "Watchlist (*.wch)\0*.wch\0All Files (*.*)\0*.*\0\0", "wch", RamWatchHWnd)) + if(Change_File_L(Str_Tmp, initdir.c_str(), "Load Watches", "Watchlist (*.wch)\0*.wch\0All Files (*.*)\0*.*\0\0", "wch", RamWatchHWnd)) { return Load_Watches(clear, Str_Tmp); } From c161dd892bacd82e90b6443e2a8ad1e2f26cb167 Mon Sep 17 00:00:00 2001 From: aquanull Date: Wed, 4 Apr 2018 18:33:42 +0800 Subject: [PATCH 04/18] Fixes the bug loading the wrong movie extras via Movie->Recent. --- src/drivers/win/window.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index b9dd376b..266487de 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -1689,9 +1689,12 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) // A menu item for the recent movie files menu was clicked. if(wParam >= MOVIE_FIRST_RECENT_FILE && wParam < MOVIE_FIRST_RECENT_FILE + MAX_NUMBER_OF_MOVIE_RECENT_FILES) { + // aquanull: FCEUI_LoadMovie() calls AddRecentMovieFile(), which may change the orders of recent movies. + // For FCEUX_LoadMovieExtras() to receive the correct filename, fname has to be unaffected. char*& fname = recent_movie[wParam - MOVIE_FIRST_RECENT_FILE]; if(fname) { + string movie_fname = fname; if (!FCEUI_LoadMovie(fname, 1, false)) { int result = MessageBox(hWnd,"Remove from list?", "Could Not Open Recent File", MB_YESNO); @@ -1701,7 +1704,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) UpdateMovieRMenu(recentmoviemenu, recent_movie, MENU_MOVIE_RECENT, MOVIE_FIRST_RECENT_FILE); } } else { - FCEUX_LoadMovieExtras(fname); + FCEUX_LoadMovieExtras(movie_fname.c_str()); } } } From b08267b84a431f78c03fcd092b717f11b960b007 Mon Sep 17 00:00:00 2001 From: aquanull Date: Wed, 4 Apr 2018 18:49:33 +0800 Subject: [PATCH 05/18] Allows loading post-movie-end savestates if consistency of the timeline can be verified. --- src/movie.cpp | 52 ++++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/src/movie.cpp b/src/movie.cpp index 93512262..6bb763b0 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -1421,7 +1421,6 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) } closeRecordingMovie(); - if (movie_readonly) { // currFrameCounter at this point represents the savestate framecount @@ -1436,40 +1435,29 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) } else FCEU_PrintError("Error: Savestate not in the same timeline as movie!\nFrame %d branches from current timeline", frame_of_mismatch); return false; - } else if (movieMode == MOVIEMODE_FINISHED - && currFrameCounter > (int)currMovieData.records.size() - && currMovieData.records.size() == tempMovieData.records.size()) + } else if ((int)tempMovieData.records.size() < currFrameCounter) { - // special case (in MOVIEMODE_FINISHED mode) - // allow loading post-movie savestates that were made after finishing current movie - - } else if (currFrameCounter > (int)currMovieData.records.size()) - { - // this is future event state, don't allow it - //TODO: turn frame counter to red to get attention - if (!backupSavestates) //If backups are disabled we can just resume normally since we can't restore so stop movie and inform user + // this is post-movie savestate and must be checked further + if (tempMovieData.records.size() < currMovieData.records.size()) { - FCEU_PrintError("Error: Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, currMovieData.records.size()-1); - FCEUI_StopMovie(); - } else - 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; - } else if (currFrameCounter > (int)tempMovieData.records.size()) - { - // this is post-movie savestate, don't allow it - //TODO: turn frame counter to red to get attention - if (!backupSavestates) //If backups are disabled we can just resume normally since we can't restore so stop movie and inform user - { - FCEU_PrintError("Error: Savestate is from a frame (%d) after the final frame in the savestated movie (%d). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, tempMovieData.records.size()-1); - FCEUI_StopMovie(); - } else - FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the savestated movie (%d). This is not permitted.", currFrameCounter, tempMovieData.records.size()-1); - return false; - } else - { - // Finally, this is a savestate file for this movie - movieMode = MOVIEMODE_PLAY; + // this savestate doesn't contain enough input to be checked + //TODO: turn frame counter to red to get attention + if (!backupSavestates) //If backups are disabled we can just resume normally since we can't restore so stop movie and inform user + { + FCEU_PrintError("Error: Savestate taken from a frame (%d) after the final frame in the savestated movie (%d) cannot be verified against current movie (%d). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1); + FCEUI_StopMovie(); + } else + FCEU_PrintError("Savestate taken from a frame (%d) after the final frame in the savestated movie (%d) cannot be verified against current movie (%d). This is not permitted.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1); + return false; + } } + + // Finally, this is a savestate file for this movie + // We'll allow loading post-movie savestates that were made after finishing current movie + if (currFrameCounter < (int)currMovieData.records.size()) + movieMode = MOVIEMODE_PLAY; + else + FinishPlayback(); } else { //Read+Write mode From 693607f66b09f3d3bea9e41aea1399da15a2db13 Mon Sep 17 00:00:00 2001 From: aquanull Date: Wed, 4 Apr 2018 19:32:29 +0800 Subject: [PATCH 06/18] Fixes the bug that extra frames could be saved in the movie file, when rerecording from middle of the movie. Also flushes the movie file more often. --- src/movie.cpp | 167 +++++++++++++++++++++++++++++++++----------------- src/movie.h | 2 +- 2 files changed, 113 insertions(+), 56 deletions(-) diff --git a/src/movie.cpp b/src/movie.cpp index 6bb763b0..c14158fb 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -478,7 +478,7 @@ void MovieData::installValue(std::string& key, std::string& val) } } -int MovieData::dump(EMUFILE *os, bool binary) +int MovieData::dump(EMUFILE *os, bool binary, bool seekToCurrFramePos) { int start = os->ftell(); os->fprintf("version %d\n", version); @@ -516,19 +516,30 @@ int MovieData::dump(EMUFILE *os, bool binary) if (this->loadFrameCount >= 0) os->fprintf("length %d\n" , this->loadFrameCount); + int currFramePos = -1; if(binary) { //put one | to start the binary dump os->fputc('|'); - for(int i=0;i<(int)records.size();i++) + for (int i = 0; i < (int)records.size(); i++) + { + if (seekToCurrFramePos && currFrameCounter == i) + currFramePos = os->ftell(); records[i].dumpBinary(this, os, i); + } } else { - for(int i=0;i<(int)records.size();i++) + for (int i = 0; i < (int)records.size(); i++) + { + if (seekToCurrFramePos && currFrameCounter == i) + currFramePos = os->ftell(); records[i].dump(this, os, i); + } } int end = os->ftell(); + if (currFramePos >= 0) + os->fseek(currFramePos, SEEK_SET); return end-start; } @@ -735,53 +746,83 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) return true; } -/// Stop movie playback. -static void StopPlayback() +static EMUFILE *openRecordingMovie(const char* fname) { - FCEU_DispMessageOnMovie("Movie playback stopped."); - movieMode = MOVIEMODE_INACTIVE; -} + if (osRecordingMovie) + delete osRecordingMovie; -// Stop movie playback without closing the movie. -static void FinishPlayback() -{ - extern int closeFinishedMovie; - if (closeFinishedMovie) - StopPlayback(); - else - { - FCEU_DispMessage("Movie finished playing.",0); - movieMode = MOVIEMODE_FINISHED; + osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb"); + if (!osRecordingMovie || osRecordingMovie->fail()) { + FCEU_PrintError("Error opening movie output file: %s", fname); + return NULL; } + strcpy(curMovieFilename, fname); + + return osRecordingMovie; } static void closeRecordingMovie() { - if(osRecordingMovie) + if (osRecordingMovie) { delete osRecordingMovie; osRecordingMovie = 0; } } +// Callers shall set the approriate movieMode before calling this +static void RedumpWholeMovieFile(bool justToggledRecording = false) +{ + bool recording = (movieMode == MOVIEMODE_RECORD); + assert((NULL != osRecordingMovie) == (recording != justToggledRecording) && "osRecordingMovie should be consistent with movie mode!"); + + if (NULL == openRecordingMovie(curMovieFilename)) + return; + + currMovieData.dump(osRecordingMovie, false/*currMovieData.binaryFlag*/, recording); + if (recording) + osRecordingMovie->fflush(); + else + closeRecordingMovie(); +} + +/// Stop movie playback. +static void StopPlayback() +{ + assert(movieMode != MOVIEMODE_RECORD && NULL == osRecordingMovie); + + movieMode = MOVIEMODE_INACTIVE; + FCEU_DispMessageOnMovie("Movie playback stopped."); +} + +// Stop movie playback without closing the movie. +static void FinishPlayback() +{ + assert(movieMode != MOVIEMODE_RECORD); + + extern int closeFinishedMovie; + if (closeFinishedMovie) + StopPlayback(); + else + { + movieMode = MOVIEMODE_FINISHED; + FCEU_DispMessage("Movie finished playing.",0); + } +} + /// Stop movie recording static void StopRecording() { - FCEU_DispMessage("Movie recording stopped.",0); - movieMode = MOVIEMODE_INACTIVE; + assert(movieMode == MOVIEMODE_RECORD); - closeRecordingMovie(); + movieMode = MOVIEMODE_INACTIVE; + RedumpWholeMovieFile(true); + FCEU_DispMessage("Movie recording stopped.",0); } -void FCEUI_StopMovie() +static void OnMovieClosed() { - if(suppressMovieStop) - return; - - if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) - StopPlayback(); - else if(movieMode == MOVIEMODE_RECORD) - StopRecording(); + assert(movieMode == MOVIEMODE_INACTIVE); curMovieFilename[0] = 0; //No longer a current movie filename freshMovie = false; //No longer a fresh movie loaded @@ -794,6 +835,19 @@ void FCEUI_StopMovie() bool bogorf; +void FCEUI_StopMovie() +{ + if (suppressMovieStop) + return; + + if (movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) + StopPlayback(); + else if (movieMode == MOVIEMODE_RECORD) + StopRecording(); + + OnMovieClosed(); +} + void poweron(bool shouldDisableBatteryLoading) { //// make a for-movie-recording power-on clear the game's save data, too @@ -1021,21 +1075,6 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe) return true; } -static void openRecordingMovie(const char* fname) -{ - osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb"); - if(!osRecordingMovie || osRecordingMovie->fail()) { - FCEU_PrintError("Error opening movie output file: %s",fname); - return; - } - strcpy(curMovieFilename, fname); - -#ifdef WIN32 - //Add to the recent movie menu - AddRecentMovieFile(fname); -#endif -} - //begin recording a new movie //TODO - BUG - the record-from-another-savestate doesnt work. @@ -1048,11 +1087,14 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author) FCEUI_StopMovie(); - openRecordingMovie(fname); - - if(!osRecordingMovie || osRecordingMovie->fail()) + if (NULL == openRecordingMovie(fname)) return; +#ifdef WIN32 + //Add to the recent movie menu + AddRecentMovieFile(fname); +#endif + currFrameCounter = 0; LagCounterReset(); FCEUMOV_CreateCleanMovie(); @@ -1224,6 +1266,9 @@ void FCEUMOV_AddCommand(int cmd) void FCEU_DrawMovies(uint8 *XBuf) { + // not the best place, but just working + assert((NULL != osRecordingMovie) == (movieMode == MOVIEMODE_RECORD)); + if(frame_display) { char counterbuf[32] = {0}; @@ -1420,9 +1465,15 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) #endif } - closeRecordingMovie(); if (movie_readonly) { + if (movieMode == MOVIEMODE_RECORD) + { + movieMode = MOVIEMODE_PLAY; + RedumpWholeMovieFile(true); + closeRecordingMovie(); + } + // currFrameCounter at this point represents the savestate framecount int frame_of_mismatch = CheckTimelines(tempMovieData, currMovieData); if (frame_of_mismatch >= 0) @@ -1461,13 +1512,16 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) } else { //Read+Write mode + closeRecordingMovie(); + if (currFrameCounter > (int)tempMovieData.records.size()) { //This is a post movie savestate, handle it differently //Replace movie contents but then switch to movie finished mode currMovieData = tempMovieData; - openRecordingMovie(curMovieFilename); - currMovieData.dump(osRecordingMovie, false/*currMovieData.binaryFlag*/); + movieMode = MOVIEMODE_PLAY; + FCEUMOV_IncrementRerecordCount(); + RedumpWholeMovieFile(); FinishPlayback(); } else { @@ -1477,11 +1531,9 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) tempMovieData.truncateAt(currFrameCounter); currMovieData = tempMovieData; - FCEUMOV_IncrementRerecordCount(); - openRecordingMovie(curMovieFilename); - currMovieData.dump(osRecordingMovie, false/*currMovieData.binaryFlag*/); movieMode = MOVIEMODE_RECORD; - + FCEUMOV_IncrementRerecordCount(); + RedumpWholeMovieFile(true); } } } @@ -1616,6 +1668,11 @@ void FCEUI_MoviePlayFromBeginning(void) #endif } else if (movieMode != MOVIEMODE_INACTIVE) { + if (movieMode == MOVIEMODE_RECORD) + { + movieMode = MOVIEMODE_PLAY; + RedumpWholeMovieFile(true); + } if (currMovieData.savestate.empty()) { movie_readonly = true; diff --git a/src/movie.h b/src/movie.h index a19d25ba..c1c41a17 100644 --- a/src/movie.h +++ b/src/movie.h @@ -234,7 +234,7 @@ public: void truncateAt(int frame); void installValue(std::string& key, std::string& val); - int dump(EMUFILE* os, bool binary); + int dump(EMUFILE* os, bool binary, bool seekToCurrFramePos = false); void clearRecordRange(int start, int len); void eraseRecords(int at, int frames = 1); From 23c7ce73426128749df604246691a9f0845e6171 Mon Sep 17 00:00:00 2001 From: aquanull Date: Wed, 4 Apr 2018 21:13:42 +0800 Subject: [PATCH 07/18] Adds new command to toggle movie Recording/Playing directly. Adds new command to truncate movie in Read+Write mode. Adds new command to insert/delete 1 frame in Read+Write mode. --- src/driver.h | 3 +- src/drivers/win/res.rc | 111 ++++++++++++++++++++---- src/drivers/win/resource.h | 8 ++ src/drivers/win/window.cpp | 83 +++++++++++++++--- src/fceu.cpp | 4 + src/input.cpp | 4 + src/input.h | 5 ++ src/movie.cpp | 172 +++++++++++++++++++++++++++++++++++-- src/movie.h | 4 + 9 files changed, 359 insertions(+), 35 deletions(-) diff --git a/src/driver.h b/src/driver.h index 7d228e0b..f221b9bb 100644 --- a/src/driver.h +++ b/src/driver.h @@ -337,7 +337,8 @@ enum EFCEUI FCEUI_STOPMOVIE, FCEUI_RECORDMOVIE, FCEUI_PLAYMOVIE, FCEUI_OPENGAME, FCEUI_CLOSEGAME, FCEUI_TASEDITOR, - FCEUI_RESET, FCEUI_POWER, FCEUI_PLAYFROMBEGINNING, FCEUI_EJECT_DISK, FCEUI_SWITCH_DISK, FCEUI_INSERT_COIN + FCEUI_RESET, FCEUI_POWER, FCEUI_PLAYFROMBEGINNING, FCEUI_EJECT_DISK, FCEUI_SWITCH_DISK, FCEUI_INSERT_COIN, + FCEUI_TOGGLERECORDINGMOVIE, FCEUI_TRUNCATEMOVIE, FCEUI_INSERT1FRAME, FCEUI_DELETE1FRAME }; //checks whether an EFCEUI is valid right now diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index b536c7cf..95b39718 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -7,7 +7,8 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "afxres.h" +#include "afxres.h" + ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -1854,6 +1855,14 @@ BEGIN MENUITEM "&Play Movie...", MENU_REPLAY_MOVIE MENUITEM "&Stop Movie", MENU_STOP_MOVIE MENUITEM "Play from &Beginning", ID_FILE_PLAYMOVIEFROMBEGINNING + MENUITEM "&Toggle Recording/Playing", ID_FILE_TOGGLE_RECORDING_MOVIE + POPUP "&Modify" + BEGIN + MENUITEM "&Insert 1 Frame", ID_FILE_INSERT_1_FRAME + MENUITEM "&Delete 1 Frame", ID_FILE_DELETE_1_FRAME + MENUITEM SEPARATOR + MENUITEM "&Truncate at Current Frame", ID_FILE_TRUNCATE_MOVIE + END MENUITEM SEPARATOR MENUITEM "&Read-only", ID_FILE_MOVIE_TOGGLEREAD END @@ -2225,17 +2234,12 @@ END FCEUCONTEXTMENUS MENU BEGIN - POPUP "Game+Movie+readonly" + POPUP "NoGame" BEGIN - MENUITEM "Toggle to read+write", FCEUX_CONTEXT_READONLYTOGGLE - MENUITEM "Play Movie from Beginning", FCEU_CONTEXT_PLAYMOVIEFROMBEGINNING - MENUITEM "Stop Movie Replay", FCEU_CONTEXT_STOPMOVIE - MENUITEM "View comments and subtitles", FCEUX_CONTEXT_VIEWCOMMENTSSUBTITLES + MENUITEM "Open ROM", FCEU_CONTEXT_OPENROM + MENUITEM "Last ROM used", FCEUX_CONTEXT_RECENTROM1 MENUITEM SEPARATOR - MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE - MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO - MENUITEM SEPARATOR - MENUITEM "Help....", FCEU_CONTEXT_MOVIEHELP + MENUITEM "Help...", FCEU_CONTEXT_FCEUHELP MENUITEM SEPARATOR MENUITEM "Use Config > Gui to get zapper right click", FCEUX_CONTEXT_GUICONFIG END @@ -2254,16 +2258,81 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Use Config > Gui to get zapper right click", FCEUX_CONTEXT_GUICONFIG END - POPUP "NoGame" + POPUP "Game+Movie+Playing+readonly" BEGIN - MENUITEM "Open ROM", FCEU_CONTEXT_OPENROM - MENUITEM "Last ROM used", FCEUX_CONTEXT_RECENTROM1 + MENUITEM "Toggle to read+write", FCEUX_CONTEXT_READONLYTOGGLE + MENUITEM "Play Movie from Beginning", FCEU_CONTEXT_PLAYMOVIEFROMBEGINNING + MENUITEM "Stop Movie Replay", FCEU_CONTEXT_STOPMOVIE + MENUITEM "View comments and subtitles", FCEUX_CONTEXT_VIEWCOMMENTSSUBTITLES MENUITEM SEPARATOR - MENUITEM "Help...", FCEU_CONTEXT_FCEUHELP + MENUITEM "Toggle to Recording", FCEUX_CONTEXT_TOGGLE_RECORDING + POPUP "Modify Movie" + BEGIN + MENUITEM "Insert 1 Frame", FCEUX_CONTEXT_INSERT_1_FRAME + MENUITEM "Delete 1 Frame", FCEUX_CONTEXT_DELETE_1_FRAME + MENUITEM SEPARATOR + MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE + END + MENUITEM SEPARATOR + MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE + MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO + MENUITEM SEPARATOR + MENUITEM "Help....", FCEU_CONTEXT_MOVIEHELP MENUITEM SEPARATOR MENUITEM "Use Config > Gui to get zapper right click", FCEUX_CONTEXT_GUICONFIG END - POPUP "Game+Movie+readwrite" + POPUP "Game+Movie+Playing+readwrite" + BEGIN + MENUITEM "Toggle to Read-only", FCEUX_CONTEXT_READONLYTOGGLE + MENUITEM "Play Movie From Beginning", FCEU_CONTEXT_PLAYMOVIEFROMBEGINNING + MENUITEM "Stop Movie Replay", FCEU_CONTEXT_STOPMOVIE + MENUITEM "View comments and subtitles", FCEUX_CONTEXT_VIEWCOMMENTSSUBTITLES + MENUITEM "Make backup", FCEUX_CONTEXT_MAKEBACKUP + MENUITEM "Save Movie As...", FCEUX_CONTEXT_SAVEMOVIEAS + MENUITEM SEPARATOR + MENUITEM "Toggle to Recording", FCEUX_CONTEXT_TOGGLE_RECORDING + POPUP "Modify Movie" + BEGIN + MENUITEM "Insert 1 Frame", FCEUX_CONTEXT_INSERT_1_FRAME + MENUITEM "Delete 1 Frame", FCEUX_CONTEXT_DELETE_1_FRAME + MENUITEM SEPARATOR + MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE + END + MENUITEM SEPARATOR + MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE + MENUITEM "Undo loadstate", FCEUX_CONTEXT_UNDOLOADSTATE + MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO + MENUITEM SEPARATOR + MENUITEM "&Mode: Full state-movie loads", ID_CONTEXT_FULLSAVESTATES + MENUITEM SEPARATOR + MENUITEM "Help...", FCEU_CONTEXT_MOVIEHELP + MENUITEM SEPARATOR + MENUITEM "Use Config > Gui to get zapper right click", FCEUX_CONTEXT_GUICONFIG + END + POPUP "Game+Movie+Recording+readonly" + BEGIN + MENUITEM "Toggle to read+write", FCEUX_CONTEXT_READONLYTOGGLE + MENUITEM "Play Movie from Beginning", FCEU_CONTEXT_PLAYMOVIEFROMBEGINNING + MENUITEM "Stop Movie Recording", FCEU_CONTEXT_STOPMOVIE + MENUITEM "View comments and subtitles", FCEUX_CONTEXT_VIEWCOMMENTSSUBTITLES + MENUITEM SEPARATOR + MENUITEM "Toggle to Playing", FCEUX_CONTEXT_TOGGLE_RECORDING + POPUP "Modify Movie" + BEGIN + MENUITEM "Insert 1 Frame", FCEUX_CONTEXT_INSERT_1_FRAME + MENUITEM "Delete 1 Frame", FCEUX_CONTEXT_DELETE_1_FRAME + MENUITEM SEPARATOR + MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE + END + MENUITEM SEPARATOR + MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE + MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO + MENUITEM SEPARATOR + MENUITEM "Help....", FCEU_CONTEXT_MOVIEHELP + MENUITEM SEPARATOR + MENUITEM "Use Config > Gui to get zapper right click", FCEUX_CONTEXT_GUICONFIG + END + POPUP "Game+Movie+Recording+readwrite" BEGIN MENUITEM "Toggle to Read-only", FCEUX_CONTEXT_READONLYTOGGLE MENUITEM "Play Movie From Beginning", FCEU_CONTEXT_PLAYMOVIEFROMBEGINNING @@ -2272,6 +2341,15 @@ BEGIN MENUITEM "Make backup", FCEUX_CONTEXT_MAKEBACKUP MENUITEM "Save Movie As...", FCEUX_CONTEXT_SAVEMOVIEAS MENUITEM SEPARATOR + MENUITEM "Toggle to Playing", FCEUX_CONTEXT_TOGGLE_RECORDING + POPUP "Modify Movie" + BEGIN + MENUITEM "Insert 1 Frame", FCEUX_CONTEXT_INSERT_1_FRAME + MENUITEM "Delete 1 Frame", FCEUX_CONTEXT_DELETE_1_FRAME + MENUITEM SEPARATOR + MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE + END + MENUITEM SEPARATOR MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE MENUITEM "Undo loadstate", FCEUX_CONTEXT_UNDOLOADSTATE MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO @@ -2599,7 +2677,8 @@ IDB_BRANCH_SPRITESHEET BITMAP "res\\branch_spritesheet.bmp" // // Generated from the TEXTINCLUDE 3 resource. // - + + ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 0ad99e52..9a3f71ef 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -923,6 +923,12 @@ #define ID_FILE_CLOSE40218 40218 #define MENU_MV_FILE_GOTO_ADDRESS 40219 #define MENU_BASIC_BOT2 40220 +#define ID_FILE_TRUNCATE_MOVIE 40221 +#define FCEUX_CONTEXT_TRUNCATE_MOVIE 40222 +#define ID_FILE_INSERT_1_FRAME 40223 +#define FCEUX_CONTEXT_INSERT_1_FRAME 40224 +#define ID_FILE_DELETE_1_FRAME 40225 +#define FCEUX_CONTEXT_DELETE_1_FRAME 40226 #define ID_FILE_OPENLUAWINDOW 40229 #define ID_FILE_CLOSELUAWINDOWS 40230 #define ID_CONFIG_DISPLAY 40231 @@ -1053,6 +1059,8 @@ #define FCEUX_CONTEXT_LOADLASTMOVIE 40356 #define ID_GAME_SAVEMOVIEAS 40357 #define FCEUX_CONTEXT_SAVEMOVIEAS 40358 +#define ID_FILE_TOGGLE_RECORDING_MOVIE 40359 +#define FCEUX_CONTEXT_TOGGLE_RECORDING 40360 #define ID_OPTIONS_BINDTOMAINWINDOW 40361 #define ID_CONFIG_PPU 40362 #define ID_PPU_NEWPPU 40363 diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 266487de..df1adc80 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -494,6 +494,23 @@ void UpdateContextMenuItems(HMENU context, int whichContext) CheckMenuItem(context,ID_CONTEXT_FULLSAVESTATES,MF_BYCOMMAND | (fullSaveStateLoads ? MF_CHECKED : MF_UNCHECKED)); + if (FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD)) + EnableMenuItem(context, FCEUX_CONTEXT_TOGGLE_RECORDING, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(context, FCEUX_CONTEXT_TOGGLE_RECORDING, MF_BYCOMMAND | MF_GRAYED); + + if (FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD)) + { + EnableMenuItem(context, FCEUX_CONTEXT_INSERT_1_FRAME, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(context, FCEUX_CONTEXT_DELETE_1_FRAME, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem(context, FCEUX_CONTEXT_TRUNCATE_MOVIE, MF_BYCOMMAND | MF_ENABLED); + } else + { + EnableMenuItem(context, FCEUX_CONTEXT_INSERT_1_FRAME, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(context, FCEUX_CONTEXT_DELETE_1_FRAME, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(context, FCEUX_CONTEXT_TRUNCATE_MOVIE, MF_BYCOMMAND | MF_GRAYED); + } + //Undo Loadstate if (CheckBackupSaveStateExist() && (undoLS || redoLS)) EnableMenuItem(context,FCEUX_CONTEXT_UNDOLOADSTATE,MF_BYCOMMAND | MF_ENABLED); @@ -547,9 +564,8 @@ void UpdateContextMenuItems(HMENU context, int whichContext) InsertMenu(context,0xFFFF, MF_BYCOMMAND, FCEUX_CONTEXT_UNHIDEMENU, "Unhide Menu"); } - if ( ( (whichContext == 0) || (whichContext == 3) ) && (currMovieData.subtitles.size()) ){ + if (whichContext > 1 && currMovieData.subtitles.size() != 0){ // At position 3 is "View comments and subtitles". Insert this there: - InsertMenu(context,0x3, MF_BYPOSITION, FCEUX_CONTEXT_TOGGLESUBTITLES, movieSubtitles ? "Subtitle Display: On" : "Subtitle Display: Off"); // At position 4(+1) is after View comments and subtitles. Insert this there: InsertMenu(context,0x5, MF_BYPOSITION, FCEUX_CONTEXT_DUMPSUBTITLES, "Dump Subtitles to SRT file"); @@ -1374,18 +1390,25 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { if (rightClickEnabled) { - //If There is a movie loaded in read only - if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && movie_readonly) - whichContext = 0; // Game+Movie+readonly - //If there is a movie loaded in read+write - else if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && !movie_readonly) - whichContext = 3; // Game+Movie+readwrite + //If There is a movie loaded + if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_FINISHED)) + { + if (FCEUMOV_Mode(MOVIEMODE_RECORD)) + if (movie_readonly) + whichContext = 4; // Game+Movie+Recording+readonly + else + whichContext = 5; // Game+Movie+Recording+readwrite + else //if (FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_FINISHED)) + if (movie_readonly) + whichContext = 2; // Game+Movie+Playing+readonly + else + whichContext = 3; // Game+Movie+Playing+readwrite //If there is a ROM loaded but no movie - else if (GameInfo) + } else if (GameInfo) whichContext = 1; // Game+NoMovie //Else no ROM else - whichContext = 2; // NoGame + whichContext = 0; // NoGame hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS"); hfceuxcontextsub = GetSubMenu(hfceuxcontext, whichContext); @@ -1765,6 +1788,22 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) case ID_FILE_MOVIE_TOGGLEREAD: FCEUI_MovieToggleReadOnly(); break; + case FCEUX_CONTEXT_TOGGLE_RECORDING: + case ID_FILE_TOGGLE_RECORDING_MOVIE: + FCEUI_MovieToggleRecording(); + break; + case FCEUX_CONTEXT_INSERT_1_FRAME: + case ID_FILE_INSERT_1_FRAME: + FCEUI_MovieInsertFrame(); + break; + case FCEUX_CONTEXT_DELETE_1_FRAME: + case ID_FILE_DELETE_1_FRAME: + FCEUI_MovieDeleteFrame(); + break; + case FCEUX_CONTEXT_TRUNCATE_MOVIE: + case ID_FILE_TRUNCATE_MOVIE: + FCEUI_MovieTruncate(); + break; //Record Avi/Wav submenu case MENU_RECORD_AVI: @@ -2455,6 +2494,10 @@ adelikat: Outsourced this to a remappable hotkey EnableMenuItem(fceumenu,MENU_MOVIE_RECENT,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_PLAYMOVIE)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_STOP_MOVIE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_STOPMOVIE)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,ID_FILE_PLAYMOVIEFROMBEGINNING,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_PLAYFROMBEGINNING)?MF_ENABLED:MF_GRAYED)); + EnableMenuItem(fceumenu, ID_FILE_TOGGLE_RECORDING_MOVIE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_TOGGLERECORDINGMOVIE)?MF_ENABLED:MF_GRAYED)); + EnableMenuItem(fceumenu, ID_FILE_INSERT_1_FRAME, MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_INSERT1FRAME) ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(fceumenu, ID_FILE_DELETE_1_FRAME, MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_DELETE1FRAME) ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(fceumenu, ID_FILE_TRUNCATE_MOVIE, MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_TRUNCATEMOVIE) ? MF_ENABLED : MF_GRAYED)); EnableMenuItem(fceumenu,MENU_SAVESTATE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_QUICKSAVE)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_LOADSTATE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_QUICKLOAD)?MF_ENABLED:MF_GRAYED)); EnableMenuItem(fceumenu,MENU_SAVE_STATE,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_SAVESTATE)?MF_ENABLED:MF_GRAYED)); @@ -2876,6 +2919,26 @@ void UpdateMenuHotkeys() combined = "Play from &Beginning\t" + combo; ChangeMenuItemText(ID_FILE_PLAYMOVIEFROMBEGINNING, combined); + //Toggle Movie Recording/Playing + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_TOGGLE_RECORDING]); + combined = "&Toggle Recording/Playing\t" + combo; + ChangeMenuItemText(ID_FILE_TOGGLE_RECORDING_MOVIE, combined); + + //Insert 1 Frame + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_INSERT_1_FRAME]); + combined = "&Insert 1 Frame\t" + combo; + ChangeMenuItemText(ID_FILE_INSERT_1_FRAME, combined); + + //Delete 1 Frame + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_DELETE_1_FRAME]); + combined = "&Delete 1 Frame\t" + combo; + ChangeMenuItemText(ID_FILE_DELETE_1_FRAME, combined); + + //Truncate Movie at Current Frame + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_TRUNCATE]); + combined = "&Truncate at &Current Frame\t" + combo; + ChangeMenuItemText(ID_FILE_TRUNCATE_MOVIE, combined); + //Read only combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_READONLY_TOGGLE]); combined = "&Read only\t" + combo; diff --git a/src/fceu.cpp b/src/fceu.cpp index 2ba2a748..062286a5 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -1199,11 +1199,15 @@ bool FCEU_IsValidUI(EFCEUI ui) { break; case FCEUI_STOPMOVIE: + case FCEUI_TOGGLERECORDINGMOVIE: return(FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_FINISHED)); case FCEUI_PLAYFROMBEGINNING: return(FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_TASEDITOR | MOVIEMODE_FINISHED)); + case FCEUI_TRUNCATEMOVIE: + return(FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD)); + case FCEUI_STOPAVI: return FCEUI_AviIsRecording(); diff --git a/src/input.cpp b/src/input.cpp index adb5b624..21e3e4b6 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -813,6 +813,10 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", 0 }, { EMUCMD_MOVIE_REPLAY_FROM, EMUCMDTYPE_MOVIE, FCEUD_MovieReplayFrom, 0, 0, "Play Movie From...", 0 }, { EMUCMD_MOVIE_PLAY_FROM_BEGINNING, EMUCMDTYPE_MOVIE, FCEUI_MoviePlayFromBeginning, 0, 0, "Play Movie From Beginning", EMUCMDFLAG_TASEDITOR }, + { EMUCMD_MOVIE_TOGGLE_RECORDING, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleRecording, 0, 0, "Toggle Movie Recording/Playing", 0 }, + { EMUCMD_MOVIE_INSERT_1_FRAME, EMUCMDTYPE_MOVIE, FCEUI_MovieInsertFrame, 0, 0, "Insert 1 Frame To Movie", 0 }, + { EMUCMD_MOVIE_DELETE_1_FRAME, EMUCMDTYPE_MOVIE, FCEUI_MovieDeleteFrame, 0, 0, "Delete 1 Frame From Movie", 0 }, + { EMUCMD_MOVIE_TRUNCATE, EMUCMDTYPE_MOVIE, FCEUI_MovieTruncate, 0, 0, "Truncate Movie At Current Frame", 0 }, { EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 }, { EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Toggle Frame Display", EMUCMDFLAG_TASEDITOR }, diff --git a/src/input.h b/src/input.h index a4ba1624..f4e20674 100644 --- a/src/input.h +++ b/src/input.h @@ -248,6 +248,11 @@ enum EMUCMD EMUCMD_FPS_DISPLAY_TOGGLE, EMUCMD_TOOL_DEBUGSTEPINTO, + EMUCMD_MOVIE_TOGGLE_RECORDING, + EMUCMD_MOVIE_TRUNCATE, + EMUCMD_MOVIE_INSERT_1_FRAME, + EMUCMD_MOVIE_DELETE_1_FRAME, + EMUCMD_MAX }; diff --git a/src/movie.cpp b/src/movie.cpp index c14158fb..e06fcf9f 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -746,6 +746,22 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) return true; } +static const char *GetMovieModeStr() +{ + if (movieMode == MOVIEMODE_INACTIVE) + return " (no movie)"; + else if (movieMode == MOVIEMODE_PLAY) + return " (playing)"; + else if (movieMode == MOVIEMODE_RECORD) + return " (recording)"; + else if (movieMode == MOVIEMODE_FINISHED) + return " (finished)"; + else if (movieMode == MOVIEMODE_TASEDITOR) + return " (taseditor)"; + else + return "."; +} + static EMUFILE *openRecordingMovie(const char* fname) { if (osRecordingMovie) @@ -1641,22 +1657,162 @@ void FCEUI_SetMovieToggleReadOnly(bool which) FCEU_DispMessage("Movie is Read+Write.",0); } } + +//auqnull: What's the point to toggle Read-Only without a movie loaded? void FCEUI_MovieToggleReadOnly() { char message[260]; - if(movie_readonly) - strcpy(message, "Movie is now Read+Write"); - else + movie_readonly = !movie_readonly; + if (movie_readonly) strcpy(message, "Movie is now Read-Only"); + else + strcpy(message, "Movie is now Read+Write"); + + strcat(message, GetMovieModeStr()); + FCEU_DispMessage(message, 0); +} + +void FCEUI_MovieToggleRecording() +{ + char message[260] = ""; if (movieMode == MOVIEMODE_INACTIVE) - strcat(message, " (no movie)"); - else if (movieMode == MOVIEMODE_FINISHED) - strcat(message, " (finished)"); + strcpy(message, "Cannot toggle Recording"); + else if (currFrameCounter > (int)currMovieData.records.size()) + strcpy(message, "Cannot toggle Recording in a future state"); + else if (movieMode == MOVIEMODE_PLAY || (movieMode == MOVIEMODE_FINISHED && currFrameCounter == (int)currMovieData.records.size())) + { + strcpy(message, "Movie is now Read+Write"); + movie_readonly = false; + FCEUMOV_IncrementRerecordCount(); + movieMode = MOVIEMODE_RECORD; + RedumpWholeMovieFile(true); + } else if (movieMode == MOVIEMODE_RECORD) + { + strcpy(message, "Movie is now Read-Only"); + movie_readonly = true; + movieMode = MOVIEMODE_PLAY; + RedumpWholeMovieFile(true); + if (currFrameCounter >= (int)currMovieData.records.size()) + { + extern int closeFinishedMovie; + if (closeFinishedMovie) + { + movieMode = MOVIEMODE_INACTIVE; + OnMovieClosed(); + } else + movieMode = MOVIEMODE_FINISHED; + } + } else + strcpy(message, "Nothing to do in this mode"); - FCEU_DispMessage(message,0); - movie_readonly = !movie_readonly; + strcat(message, GetMovieModeStr()); + + FCEU_DispMessage(message, 0); +} + +void FCEUI_MovieInsertFrame() +{ + char message[260] = ""; + + if (movieMode == MOVIEMODE_INACTIVE) + strcpy(message, "No movie to insert a frame."); + else if (movie_readonly) + strcpy(message, "Cannot modify movie in Read-Only mode."); + else if (currFrameCounter > (int)currMovieData.records.size()) + strcpy(message, "Cannot insert a frame here."); + else if (movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) + { + strcpy(message, "1 frame inserted"); + strcat(message, GetMovieModeStr()); + std::vector::iterator iter = currMovieData.records.begin(); + currMovieData.records.insert(iter + currFrameCounter, MovieRecord()); + FCEUMOV_IncrementRerecordCount(); + RedumpWholeMovieFile(); + } else + { + strcpy(message, "Nothing to do in this mode"); + strcat(message, GetMovieModeStr()); + } + + FCEU_DispMessage(message, 0); +} + +void FCEUI_MovieDeleteFrame() +{ + char message[260] = ""; + + if (movieMode == MOVIEMODE_INACTIVE) + strcpy(message, "No movie to delete a frame."); + else if (movie_readonly) + strcpy(message, "Cannot modify movie in Read-Only mode."); + else if (currFrameCounter >= (int)currMovieData.records.size()) + strcpy(message, "Nothing to delete past movie end."); + else if (movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY) + { + strcpy(message, "1 frame deleted"); + std::vector::iterator iter = currMovieData.records.begin(); + currMovieData.records.erase(iter + currFrameCounter); + FCEUMOV_IncrementRerecordCount(); + RedumpWholeMovieFile(); + + if (movieMode != MOVIEMODE_RECORD && currFrameCounter >= (int)currMovieData.records.size()) + { + extern int closeFinishedMovie; + if (closeFinishedMovie) + { + movieMode = MOVIEMODE_INACTIVE; + OnMovieClosed(); + } else + movieMode = MOVIEMODE_FINISHED; + } + strcat(message, GetMovieModeStr()); + } else + { + strcpy(message, "Nothing to do in this mode"); + strcat(message, GetMovieModeStr()); + } + + FCEU_DispMessage(message, 0); +} + +void FCEUI_MovieTruncate() +{ + char message[260] = ""; + + if (movieMode == MOVIEMODE_INACTIVE) + strcpy(message, "No movie to truncate."); + else if (movie_readonly) + strcpy(message, "Cannot modify movie in Read-Only mode."); + else if (currFrameCounter >= (int)currMovieData.records.size()) + strcpy(message, "Nothing to truncate past movie end."); + else if (movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY) + { + strcpy(message, "Movie truncated"); + currMovieData.truncateAt(currFrameCounter); + FCEUMOV_IncrementRerecordCount(); + RedumpWholeMovieFile(); + + if (movieMode != MOVIEMODE_RECORD) + { + extern int closeFinishedMovie; + if (closeFinishedMovie) + { + movieMode = MOVIEMODE_INACTIVE; + OnMovieClosed(); + } + else + movieMode = MOVIEMODE_FINISHED; + } + strcat(message, GetMovieModeStr()); + } else + { + strcpy(message, "Nothing to do in this mode"); + strcat(message, GetMovieModeStr()); + } + + FCEU_DispMessage(message, 0); } void FCEUI_MoviePlayFromBeginning(void) diff --git a/src/movie.h b/src/movie.h index c1c41a17..f6229f6b 100644 --- a/src/movie.h +++ b/src/movie.h @@ -277,6 +277,10 @@ void FCEUI_StopMovie(void); bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount = false); //char* FCEUI_MovieGetCurrentName(int addSlotNumber); void FCEUI_MovieToggleReadOnly(void); +void FCEUI_MovieToggleRecording(); +void FCEUI_MovieInsertFrame(); +void FCEUI_MovieDeleteFrame(); +void FCEUI_MovieTruncate(); bool FCEUI_GetMovieToggleReadOnly(); void FCEUI_SetMovieToggleReadOnly(bool which); int FCEUI_GetMovieLength(); From e7adca91324a0212535255d99dab85d520a3c833 Mon Sep 17 00:00:00 2001 From: aquanull Date: Thu, 5 Apr 2018 00:53:56 +0800 Subject: [PATCH 08/18] Allows changing Read-Only state by toggling Recording/Playing even if movie finished. --- src/movie.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/movie.cpp b/src/movie.cpp index e06fcf9f..b4ad8ceb 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -1680,8 +1680,13 @@ void FCEUI_MovieToggleRecording() if (movieMode == MOVIEMODE_INACTIVE) strcpy(message, "Cannot toggle Recording"); else if (currFrameCounter > (int)currMovieData.records.size()) - strcpy(message, "Cannot toggle Recording in a future state"); - else if (movieMode == MOVIEMODE_PLAY || (movieMode == MOVIEMODE_FINISHED && currFrameCounter == (int)currMovieData.records.size())) + { + movie_readonly = !movie_readonly; + if (movie_readonly) + strcpy(message, "Movie is now Read-Only (finished)"); + else + strcpy(message, "Movie is now Read+Write (finished)"); + } else if (movieMode == MOVIEMODE_PLAY || (movieMode == MOVIEMODE_FINISHED && currFrameCounter == (int)currMovieData.records.size())) { strcpy(message, "Movie is now Read+Write"); movie_readonly = false; From f16f6548bb2a15a9e813feecaa0b103ae8db4d9e Mon Sep 17 00:00:00 2001 From: aquanull Date: Thu, 5 Apr 2018 08:18:53 +0800 Subject: [PATCH 09/18] Adds 2 movie recording modes imported from VBA-rr. Frame display is modified to indicate the currently selected mode. --- src/drivers/win/config.cpp | 2 + src/drivers/win/res.rc | 34 +++++++++++- src/drivers/win/resource.h | 16 ++++-- src/drivers/win/window.cpp | 50 +++++++++++++++++ src/input.cpp | 7 ++- src/input.h | 6 +++ src/movie.cpp | 108 ++++++++++++++++++++++++++++++------- src/movie.h | 17 ++++++ 8 files changed, 215 insertions(+), 25 deletions(-) diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index 87de1a48..8f798956 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -61,6 +61,7 @@ extern bool disableMovieMessages; extern bool replaceP2StartWithMicrophone; extern bool SingleInstanceOnly; extern bool Show_FPS; +extern int movieRecordMode; extern bool oldInputDisplay; extern bool fullSaveStateLoads; extern int frameSkipAmt; @@ -470,6 +471,7 @@ static CFGSTRUCT fceuconfig[] = AC(replaceP2StartWithMicrophone), AC(SingleInstanceOnly), AC(Show_FPS), + AC(movieRecordMode), ENDCFGSTRUCT }; diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 95b39718..1e9e6102 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -1856,7 +1856,7 @@ BEGIN MENUITEM "&Stop Movie", MENU_STOP_MOVIE MENUITEM "Play from &Beginning", ID_FILE_PLAYMOVIEFROMBEGINNING MENUITEM "&Toggle Recording/Playing", ID_FILE_TOGGLE_RECORDING_MOVIE - POPUP "&Modify" + POPUP "&Quickly Modify" BEGIN MENUITEM "&Insert 1 Frame", ID_FILE_INSERT_1_FRAME MENUITEM "&Delete 1 Frame", ID_FILE_DELETE_1_FRAME @@ -1864,6 +1864,14 @@ BEGIN MENUITEM "&Truncate at Current Frame", ID_FILE_TRUNCATE_MOVIE END MENUITEM SEPARATOR + POPUP "Record &Mode" + BEGIN + MENUITEM "&Next Record Mode", ID_FILE_NEXTRECORDMODE + MENUITEM SEPARATOR + MENUITEM "&Truncate", ID_FILE_RECORDMODE_TRUNCATE + MENUITEM "&Overwrite[W]", ID_FILE_RECORDMODE_OVERWRITE + MENUITEM "&Insert[I]", ID_FILE_RECORDMODE_INSERT + END MENUITEM "&Read-only", ID_FILE_MOVIE_TOGGLEREAD END POPUP "&AVI/Wav" @@ -2273,6 +2281,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE END + POPUP "Record Mode" + BEGIN + MENUITEM "&Truncate", FCEUX_CONTEXT_RECORDMODE_TRUNCATE + MENUITEM "&Overwrite[W]", FCEUX_CONTEXT_RECORDMODE_OVERWRITE + MENUITEM "&Insert[I]", FCEUX_CONTEXT_RECORDMODE_INSERT + END MENUITEM SEPARATOR MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO @@ -2298,6 +2312,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE END + POPUP "Record Mode" + BEGIN + MENUITEM "&Truncate", FCEUX_CONTEXT_RECORDMODE_TRUNCATE + MENUITEM "&Overwrite[W]", FCEUX_CONTEXT_RECORDMODE_OVERWRITE + MENUITEM "&Insert[I]", FCEUX_CONTEXT_RECORDMODE_INSERT + END MENUITEM SEPARATOR MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE MENUITEM "Undo loadstate", FCEUX_CONTEXT_UNDOLOADSTATE @@ -2324,6 +2344,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE END + POPUP "Record Mode" + BEGIN + MENUITEM "&Truncate", FCEUX_CONTEXT_RECORDMODE_TRUNCATE + MENUITEM "&Overwrite[W]", FCEUX_CONTEXT_RECORDMODE_OVERWRITE + MENUITEM "&Insert[I]", FCEUX_CONTEXT_RECORDMODE_INSERT + END MENUITEM SEPARATOR MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE MENUITEM "Rewind to last auto-save", FCEUX_CONTEXT_REWINDTOLASTAUTO @@ -2349,6 +2375,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Truncate at Current Frame", FCEUX_CONTEXT_TRUNCATE_MOVIE END + POPUP "Record Mode" + BEGIN + MENUITEM "&Truncate", FCEUX_CONTEXT_RECORDMODE_TRUNCATE + MENUITEM "&Overwrite[W]", FCEUX_CONTEXT_RECORDMODE_OVERWRITE + MENUITEM "&Insert[I]", FCEUX_CONTEXT_RECORDMODE_INSERT + END MENUITEM SEPARATOR MENUITEM "Undo savestate", FCEUX_CONTEXT_UNDOSAVESTATE MENUITEM "Undo loadstate", FCEUX_CONTEXT_UNDOLOADSTATE diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 9a3f71ef..dcd58f63 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -833,6 +833,9 @@ #define MENU_DEBUGGER 40080 #define MENU_MEMORY_WATCH 40081 #define MENU_RAMFILTER 40082 +#define ID_FILE_RECENT 40100 +#define MEMW_HELP_WCOMMANDS 40101 +#define MEMW_OPTIONS_LOADLASTFILE 40102 #define MEMW_FILE_NEW 40103 #define MEMW_FILE_OPEN 40104 #define MEMW_FILE_SAVE 40105 @@ -840,13 +843,20 @@ #define MEMW_FILE_RECENT 40107 #define MEMW_FILE_CLOSE 40108 #define MEMW_OPTIONS_LOADSTART 40109 -#define MEMW_HELP_WCOMMANDS 40113 -#define MEMW_OPTIONS_LOADLASTFILE 40114 -#define ID_FILE_RECENT 40117 +#define ID_FILE_RECORDMODE_TRUNCATE 40110 +#define ID_FILE_RECORDMODE_OVERWRITE 40111 +#define ID_FILE_RECORDMODE_INSERT 40112 +#define ID_FILE_RECORDMODE_XOR 40113 +#define FCEUX_CONTEXT_RECORDMODE_TRUNCATE 40115 +#define FCEUX_CONTEXT_RECORDMODE_OVERWRITE 40116 +#define FCEUX_CONTEXT_RECORDMODE_INSERT 40117 +#define FCEUX_CONTEXT_RECORDMODE_XOR 40118 #define MENU_RECORD_WAV 40120 #define MENU_STOP_WAV 40121 #define MENU_TASEDIT 40124 #define MENU_PAUSEAFTERPLAYBACK 40126 +#define ID_FILE_NEXTRECORDMODE 40127 +#define ID_FILE_PREVRECORDMODE 40128 #define ACCEL_CTRL_O 40130 #define ACCEL_CTRL_E 40131 #define ACCEL_CTRL_W 40132 diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index df1adc80..971dc7c5 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -122,6 +122,7 @@ extern BOOL CALLBACK ReplayMetadataDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wP extern bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists extern bool oldInputDisplay; extern int RAMInitOption; +extern int movieRecordMode; //AutoFire----------------------------------------------- void ShowNetplayConsole(void); //mbg merge 7/17/06 YECH had to add @@ -417,6 +418,9 @@ void UpdateCheckedMenuItems() CheckMenuItem(fceumenu, polo2[x], *polo[x] ? MF_CHECKED : MF_UNCHECKED); } //File Menu + CheckMenuItem(fceumenu, ID_FILE_RECORDMODE_TRUNCATE, movieRecordMode == MOVIE_RECORD_MODE_TRUNCATE ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(fceumenu, ID_FILE_RECORDMODE_OVERWRITE, movieRecordMode == MOVIE_RECORD_MODE_OVERWRITE ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(fceumenu, ID_FILE_RECORDMODE_INSERT, movieRecordMode == MOVIE_RECORD_MODE_INSERT ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(fceumenu, ID_FILE_MOVIE_TOGGLEREAD, movie_readonly ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(fceumenu, ID_FILE_OPENLUAWINDOW, LuaConsoleHWnd ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(fceumenu, ID_AVI_ENABLEHUDRECORDING, FCEUI_AviEnableHUDrecording() ? MF_CHECKED : MF_UNCHECKED); @@ -510,6 +514,9 @@ void UpdateContextMenuItems(HMENU context, int whichContext) EnableMenuItem(context, FCEUX_CONTEXT_DELETE_1_FRAME, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(context, FCEUX_CONTEXT_TRUNCATE_MOVIE, MF_BYCOMMAND | MF_GRAYED); } + CheckMenuItem(context, FCEUX_CONTEXT_RECORDMODE_TRUNCATE, movieRecordMode == MOVIE_RECORD_MODE_TRUNCATE ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(context, FCEUX_CONTEXT_RECORDMODE_OVERWRITE, movieRecordMode == MOVIE_RECORD_MODE_OVERWRITE ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(context, FCEUX_CONTEXT_RECORDMODE_INSERT, movieRecordMode == MOVIE_RECORD_MODE_INSERT ? MF_CHECKED : MF_UNCHECKED); //Undo Loadstate if (CheckBackupSaveStateExist() && (undoLS || redoLS)) @@ -1804,6 +1811,24 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) case ID_FILE_TRUNCATE_MOVIE: FCEUI_MovieTruncate(); break; + case ID_FILE_NEXTRECORDMODE: + FCEUI_MovieNextRecordMode(); + break; + case ID_FILE_PREVRECORDMODE: + FCEUI_MoviePrevRecordMode(); + break; + case FCEUX_CONTEXT_RECORDMODE_TRUNCATE: + case ID_FILE_RECORDMODE_TRUNCATE: + FCEUI_MovieRecordModeTruncate(); + break; + case FCEUX_CONTEXT_RECORDMODE_OVERWRITE: + case ID_FILE_RECORDMODE_OVERWRITE: + FCEUI_MovieRecordModeOverwrite(); + break; + case FCEUX_CONTEXT_RECORDMODE_INSERT: + case ID_FILE_RECORDMODE_INSERT: + FCEUI_MovieRecordModeInsert(); + break; //Record Avi/Wav submenu case MENU_RECORD_AVI: @@ -2944,6 +2969,31 @@ void UpdateMenuHotkeys() combined = "&Read only\t" + combo; ChangeMenuItemText(ID_FILE_MOVIE_TOGGLEREAD, combined); + //Next Record Mode + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_NEXT_RECORD_MODE]); + combined = "&Next Record Mode\t" + combo; + ChangeMenuItemText(ID_FILE_NEXTRECORDMODE, combined); + + //Prev Record Mode + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_PREV_RECORD_MODE]); + combined = "&Prev Record Mode\t" + combo; + ChangeMenuItemText(ID_FILE_PREVRECORDMODE, combined); + + //Record Mode Truncate + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_RECORD_MODE_TRUNCATE]); + combined = "&Truncate\t" + combo; + ChangeMenuItemText(ID_FILE_RECORDMODE_TRUNCATE, combined); + + //Record Mode Overwrite + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_RECORD_MODE_OVERWRITE]); + combined = "&Overwrite[W]\t" + combo; + ChangeMenuItemText(ID_FILE_RECORDMODE_OVERWRITE, combined); + + //Record Mode Insert + combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_MOVIE_RECORD_MODE_INSERT]); + combined = "&Insert[I]\t" + combo; + ChangeMenuItemText(ID_FILE_RECORDMODE_INSERT, combined); + //Screenshot combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_SCREENSHOT]); combined = "&Screenshot\t" + combo; diff --git a/src/input.cpp b/src/input.cpp index 21e3e4b6..5b06d827 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -819,7 +819,12 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_MOVIE_TRUNCATE, EMUCMDTYPE_MOVIE, FCEUI_MovieTruncate, 0, 0, "Truncate Movie At Current Frame", 0 }, { EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 }, { EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", EMUCMDFLAG_TASEDITOR }, - { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Toggle Frame Display", EMUCMDFLAG_TASEDITOR }, + { EMUCMD_MOVIE_NEXT_RECORD_MODE, EMUCMDTYPE_MOVIE, FCEUI_MovieNextRecordMode, 0, 0, "Next Record Mode", 0 }, + { EMUCMD_MOVIE_PREV_RECORD_MODE, EMUCMDTYPE_MOVIE, FCEUI_MoviePrevRecordMode, 0, 0, "Prev Record Mode", 0 }, + { EMUCMD_MOVIE_RECORD_MODE_TRUNCATE, EMUCMDTYPE_MOVIE, FCEUI_MovieRecordModeTruncate, 0, 0, "Record Mode Truncate", 0 }, + { EMUCMD_MOVIE_RECORD_MODE_OVERWRITE, EMUCMDTYPE_MOVIE, FCEUI_MovieRecordModeOverwrite, 0, 0, "Record Mode Overwrite", 0 }, + { EMUCMD_MOVIE_RECORD_MODE_INSERT, EMUCMDTYPE_MOVIE, FCEUI_MovieRecordModeInsert, 0, 0, "Record Mode Insert", 0 }, + { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Toggle Frame Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleInputDisplay, 0, 0, "Toggle Input Display", EMUCMDFLAG_TASEDITOR }, { EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", EMUCMDFLAG_TASEDITOR }, diff --git a/src/input.h b/src/input.h index f4e20674..14b72677 100644 --- a/src/input.h +++ b/src/input.h @@ -253,6 +253,12 @@ enum EMUCMD EMUCMD_MOVIE_INSERT_1_FRAME, EMUCMD_MOVIE_DELETE_1_FRAME, + EMUCMD_MOVIE_NEXT_RECORD_MODE, + EMUCMD_MOVIE_PREV_RECORD_MODE, + EMUCMD_MOVIE_RECORD_MODE_TRUNCATE, + EMUCMD_MOVIE_RECORD_MODE_OVERWRITE, + EMUCMD_MOVIE_RECORD_MODE_INSERT, + EMUCMD_MAX }; diff --git a/src/movie.cpp b/src/movie.cpp index b4ad8ceb..a4338306 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -98,6 +98,7 @@ int input_display = 0; int frame_display = 0; int rerecord_display = 0; bool fullSaveStateLoads = false; //Option for loading a savestates full contents in read+write mode instead of up to the frame count in the savestate (useful as a recovery option) +int movieRecordMode = 0; //Option for various movie recording modes such as TRUNCATE (normal), OVERWRITE etc. SFORMAT FCEUMOV_STATEINFO[]={ { &currFrameCounter, 4|FCEUSTATE_RLSB, "FCNT"}, @@ -762,6 +763,27 @@ static const char *GetMovieModeStr() return "."; } +static const char *GetMovieReadOnlyStr() +{ + if (movieMode == MOVIEMODE_RECORD) + return movie_readonly ? " R-O" : ""; + else + return movie_readonly ? "" : " R+W"; +} + +static const char *GetMovieRecordModeStr() +{ + switch (movieRecordMode) + { + case MOVIE_RECORD_MODE_OVERWRITE: + return " [W]"; + case MOVIE_RECORD_MODE_INSERT: + return " [I]"; + default: + return ""; + } +} + static EMUFILE *openRecordingMovie(const char* fname) { if (osRecordingMovie) @@ -1241,14 +1263,29 @@ void FCEUMOV_AddInputState() mr.commands = _currCommand; _currCommand = 0; - //Adelikat: in normal mode, this is done at the time of loading a savestate in read+write mode + //aquanull: now it supports other recording modes that don't necessarily truncate further frame data //If the user chooses it can be delayed to here - if (fullSaveStateLoads && (currFrameCounter < (int)currMovieData.records.size())) - currMovieData.truncateAt(currFrameCounter); + if (currFrameCounter < (int)currMovieData.records.size()) + switch (movieRecordMode) + { + case MOVIE_RECORD_MODE_OVERWRITE: + currMovieData.records[currFrameCounter].Clone(mr); + break; + case MOVIE_RECORD_MODE_INSERT: + //FIXME: this could be very insufficient + currMovieData.records.insert(currMovieData.records.begin() + currFrameCounter, mr); + break; + //case MOVIE_RECORD_MODE_TRUNCATE: + default: + //Adelikat: in normal mode, this is done at the time of loading a savestate in read+write mode + currMovieData.truncateAt(currFrameCounter); + currMovieData.records.push_back(mr); + break; + } + else + currMovieData.records.push_back(mr); - mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size()); // to disk - - currMovieData.records.push_back(mr); + mr.dump(&currMovieData, osRecordingMovie, currFrameCounter); // to disk } currFrameCounter++; @@ -1285,33 +1322,39 @@ void FCEU_DrawMovies(uint8 *XBuf) // not the best place, but just working assert((NULL != osRecordingMovie) == (movieMode == MOVIEMODE_RECORD)); - if(frame_display) + if (frame_display) { char counterbuf[32] = {0}; int color = 0x20; - if(movieMode == MOVIEMODE_PLAY) - sprintf(counterbuf,"%d/%d",currFrameCounter,(int)currMovieData.records.size()); - else if(movieMode == MOVIEMODE_RECORD) - sprintf(counterbuf,"%d",currFrameCounter); - else if (movieMode == MOVIEMODE_FINISHED) + + if (movieMode == MOVIEMODE_PLAY) { - sprintf(counterbuf,"%d/%d (finished)",currFrameCounter,(int)currMovieData.records.size()); + sprintf(counterbuf, "%d/%d%s%s", currFrameCounter, (int)currMovieData.records.size(), GetMovieRecordModeStr(), GetMovieReadOnlyStr()); + } else if (movieMode == MOVIEMODE_RECORD) + { + if (movieRecordMode == MOVIE_RECORD_MODE_TRUNCATE) + sprintf(counterbuf, "%d%s%s (record)", currFrameCounter, GetMovieRecordModeStr(), GetMovieReadOnlyStr()); // nearly classic + else + sprintf(counterbuf, "%d/%d%s%s (record)", currFrameCounter, (int)currMovieData.records.size(), GetMovieRecordModeStr(), GetMovieReadOnlyStr()); + } else if (movieMode == MOVIEMODE_FINISHED) + { + sprintf(counterbuf,"%d/%d%s%s (finished)",currFrameCounter,(int)currMovieData.records.size(), GetMovieRecordModeStr(), GetMovieReadOnlyStr()); color = 0x17; //Show red to get attention - } else if(movieMode == MOVIEMODE_TASEDITOR) + } else if (movieMode == MOVIEMODE_TASEDITOR) { sprintf(counterbuf,"%d",currFrameCounter); } else sprintf(counterbuf,"%d (no movie)",currFrameCounter); - if(counterbuf[0]) + if (counterbuf[0]) DrawTextTrans(ClipSidesOffset+XBuf+FCEU_TextScanlineOffsetFromBottom(30)+1, 256, (uint8*)counterbuf, color+0x80); } - if(rerecord_display && movieMode != MOVIEMODE_INACTIVE) + if (rerecord_display && movieMode != MOVIEMODE_INACTIVE) { char counterbuf[32] = {0}; - sprintf(counterbuf,"%d",currMovieData.rerecordCount); + sprintf(counterbuf, "%d", currMovieData.rerecordCount); - if(counterbuf[0]) + if (counterbuf[0]) DrawTextTrans(ClipSidesOffset+XBuf+FCEU_TextScanlineOffsetFromBottom(50)+1, 256, (uint8*)counterbuf, 0x28+0x80); } } @@ -1668,9 +1711,9 @@ void FCEUI_MovieToggleReadOnly() strcpy(message, "Movie is now Read-Only"); else strcpy(message, "Movie is now Read+Write"); - + strcat(message, GetMovieModeStr()); - FCEU_DispMessage(message, 0); + FCEU_DispMessage(message,0); } void FCEUI_MovieToggleRecording() @@ -1820,6 +1863,31 @@ void FCEUI_MovieTruncate() FCEU_DispMessage(message, 0); } +void FCEUI_MovieNextRecordMode() +{ + movieRecordMode = (movieRecordMode + 1) % MOVIE_RECORD_MODE_MAX; +} + +void FCEUI_MoviePrevRecordMode() +{ + movieRecordMode = (movieRecordMode + MOVIE_RECORD_MODE_MAX - 1) % MOVIE_RECORD_MODE_MAX; +} + +void FCEUI_MovieRecordModeTruncate() +{ + movieRecordMode = MOVIE_RECORD_MODE_TRUNCATE; +} + +void FCEUI_MovieRecordModeOverwrite() +{ + movieRecordMode = MOVIE_RECORD_MODE_OVERWRITE; +} + +void FCEUI_MovieRecordModeInsert() +{ + movieRecordMode = MOVIE_RECORD_MODE_INSERT; +} + void FCEUI_MoviePlayFromBeginning(void) { if (movieMode == MOVIEMODE_TASEDITOR) diff --git a/src/movie.h b/src/movie.h index f6229f6b..43af163d 100644 --- a/src/movie.h +++ b/src/movie.h @@ -65,6 +65,16 @@ enum EMOVIEMODE MOVIEMODE_FINISHED = 16 }; +enum EMOVIERECORDMODE +{ + MOVIE_RECORD_MODE_TRUNCATE = 0, + MOVIE_RECORD_MODE_OVERWRITE = 1, + MOVIE_RECORD_MODE_INSERT = 2, + //MOVIE_RECORD_MODE_XOR = 3, + + MOVIE_RECORD_MODE_MAX +}; + enum EMOVIECMD { MOVIECMD_RESET = 1, @@ -267,6 +277,8 @@ extern bool freshMovie; extern bool movie_readonly; extern bool autoMovieBackup; extern bool fullSaveStateLoads; +extern int movieRecordMode; + //-------------------------------------------------- void FCEUI_MakeBackupMovie(bool dispMessage); void FCEUI_CreateMovieFile(std::string fn); @@ -281,6 +293,11 @@ void FCEUI_MovieToggleRecording(); void FCEUI_MovieInsertFrame(); void FCEUI_MovieDeleteFrame(); void FCEUI_MovieTruncate(); +void FCEUI_MovieNextRecordMode(); +void FCEUI_MoviePrevRecordMode(); +void FCEUI_MovieRecordModeTruncate(); +void FCEUI_MovieRecordModeOverwrite(); +void FCEUI_MovieRecordModeInsert(); bool FCEUI_GetMovieToggleReadOnly(); void FCEUI_SetMovieToggleReadOnly(bool which); int FCEUI_GetMovieLength(); From 56f61b9b0be42d99f374007635e73e16b8d5a569 Mon Sep 17 00:00:00 2001 From: aquanull Date: Thu, 5 Apr 2018 18:51:00 +0800 Subject: [PATCH 10/18] Now it clears previous input display when starts playing a movie from power-on. --- src/movie.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/movie.cpp b/src/movie.cpp index a4338306..8430729c 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -1053,6 +1053,7 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe) freshMovie = true; //Movie has been loaded, so it must be unaltered if (bindSavestate) AutoSS = false; //If bind savestate to movie is true, then their isn't a valid auto-save to load, so flag it + cur_input_display = 0; //clear previous input display //fully reload the game to reinitialize everything before playing any movie poweron(true); @@ -1906,6 +1907,7 @@ void FCEUI_MoviePlayFromBeginning(void) { movie_readonly = true; movieMode = MOVIEMODE_PLAY; + cur_input_display = 0; //clear previous input display poweron(true); currFrameCounter = 0; FCEU_DispMessage("Movie is now Read-Only. Playing from beginning.",0); From 9137dfbf3fcbfd9f75b86d5e4b220866bd508543 Mon Sep 17 00:00:00 2001 From: aquanull Date: Thu, 5 Apr 2018 18:51:16 +0800 Subject: [PATCH 11/18] Tiny refactoring on input display. --- src/video.cpp | 134 +++++++++++++++++--------------------------------- 1 file changed, 44 insertions(+), 90 deletions(-) diff --git a/src/video.cpp b/src/video.cpp index 3634d78e..d9654c96 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -178,6 +178,31 @@ static void ReallySnap(void) FCEU_DispMessage("Screen snapshot %d saved.",0,x-1); } +static uint32 GetButtonColor(uint32 held, uint32 c, uint32 ci, int bit) +{ + uint32 on = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0x90 : 0xA7; //Standard, or Gray depending on movie mode + uint32 oni = 0xA0; //Color for immediate keyboard buttons + uint32 blend = 0xB6; //Blend of immiate and last held buttons + uint32 ahold = 0x87; //Auto hold + uint32 off = 0xCF; + + uint32 color; + uint8 mask = 1u << bit; + if (held & mask) { //If auto-hold + if (!(ci & mask)) + color = ahold; + else + color = (c & mask) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! + } + else { + if (c & mask) + color = (ci & mask) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors + else + color = (ci & mask) ? oni : off; + } + return color; +} + void FCEU_PutImage(void) { if(dosnapsave==2) //Save screenshot as, currently only flagged & run by the Win32 build. //TODO SDL: implement this? @@ -247,19 +272,10 @@ void FCEU_PutImage(void) if(input_display) { extern uint32 JSAutoHeld; - uint32 held; - - int controller, c, ci, color; int i, j; - uint32 on = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0x90:0xA7; //Standard, or Gray depending on movie mode - uint32 oni = 0xA0; //Color for immediate keyboard buttons - uint32 blend = 0xB6; //Blend of immiate and last held buttons - uint32 ahold = 0x87; //Auto hold - uint32 off = 0xCF; - uint8 *t = XBuf+(FSettings.LastSLine-9)*256 + 20; //mbg merge 7/17/06 changed t to uint8* if(input_display > 4) input_display = 4; - for(controller = 0; controller < input_display; controller++, t += 56) + for(int controller = 0; controller < input_display; controller++, t += 56) { for(i = 0; i < 34;i++) for(j = 0; j <9 ; j++) @@ -267,33 +283,27 @@ void FCEU_PutImage(void) for(i = 3; i < 6; i++) for(j = 3; j< 6; j++) t[i+j*256] = 0xCF; - c = cur_input_display >> (controller * 8); + uint32 held = 0; + uint32 c = cur_input_display >> (controller * 8); + uint32 ci = 0; + uint32 color; + +#ifdef WIN32 // This doesn't work in anything except windows for now. // It doesn't get set anywhere in other ports. -#ifdef WIN32 - if (!oldInputDisplay) ci = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0:GetGamepadPressedImmediate() >> (controller * 8); - else ci = 0; + if (!oldInputDisplay) + ci = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0 : GetGamepadPressedImmediate() >> (controller * 8); - if (!oldInputDisplay && !FCEUMOV_Mode(MOVIEMODE_PLAY)) held = (JSAutoHeld >> (controller * 8)); - else held = 0; + if (!oldInputDisplay && !FCEUMOV_Mode(MOVIEMODE_PLAY)) + held = (JSAutoHeld >> (controller * 8)); #else // Put other port info here - ci = 0; - held = 0; #endif //adelikat: I apologize to anyone who ever sifts through this color assignment //A - if (held&1) { //If auto-hold - if (!(ci&1) ) color = ahold; - else - color = (c&1) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&1) color = (ci&1) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&1) ? oni : off; - } + color = GetButtonColor(held, c, ci, 0); for(i=0; i < 4; i++) { for(j = 0; j < 4; j++) @@ -304,15 +314,7 @@ void FCEU_PutImage(void) } } //B - if (held&2) { //If auto-hold - if (!(ci&2) ) color = ahold; - else - color = (c&2) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&2) color = (ci&2) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&2) ? oni : off; - } + color = GetButtonColor(held, c, ci, 1); for(i=0; i < 4; i++) { for(j = 0; j < 4; j++) @@ -323,45 +325,21 @@ void FCEU_PutImage(void) } } //Select - if (held&4) { //If auto-hold - if (!(ci&4) ) color = ahold; - else - color = (c&4) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&4) color = (ci&4) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&4) ? oni : off; - } + color = GetButtonColor(held, c, ci, 2); for(i = 0; i < 4; i++) { t[11+5*256+i] = color; t[11+6*256+i] = color; } //Start - if (held&8) { //If auto-hold - if (!(ci&8) ) color = ahold; - else - color = (c&8) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&8) color = (ci&8) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&8) ? oni : off; - } + color = GetButtonColor(held, c, ci, 3); for(i = 0; i < 4; i++) { t[17+5*256+i] = color; t[17+6*256+i] = color; } //Up - if (held&16) { //If auto-hold - if (!(ci&16) ) color = ahold; - else - color = (c&16) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&16) color = (ci&16) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&16) ? oni : off; - } + color = GetButtonColor(held, c, ci, 4); for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) @@ -370,15 +348,7 @@ void FCEU_PutImage(void) } } //Down - if (held&32) { //If auto-hold - if (!(ci&32) ) color = ahold; - else - color = (c&32) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&32) color = (ci&32) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&32) ? oni : off; - } + color = GetButtonColor(held, c, ci, 5); for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) @@ -387,15 +357,7 @@ void FCEU_PutImage(void) } } //Left - if (held&64) { //If auto-hold - if (!(ci&64) ) color = ahold; - else - color = (c&64) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&64) color = (ci&64) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&64) ? oni : off; - } + color = GetButtonColor(held, c, ci, 6); for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) @@ -404,15 +366,7 @@ void FCEU_PutImage(void) } } //Right - if (held&128) { //If auto-hold - if (!(ci&128) ) color = ahold; - else - color = (c&128) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! - } - else { - if (c&128) color = (ci&128) ? blend : on; //If immedaite buttons are pressed and they match the previous frame, blend the colors - else color = (ci&128) ? oni : off; - } + color = GetButtonColor(held, c, ci, 7); for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) From c7710ae244e9c8b01c0247a04aa702c616906bcd Mon Sep 17 00:00:00 2001 From: aquanull Date: Thu, 12 Apr 2018 22:43:39 +0800 Subject: [PATCH 12/18] Fix for the interframe-pause-skips-updating-next-frame bugs, mostly noticeable when dumping AVIs. --- src/drivers/win/debugger.cpp | 2 +- src/fceu.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp index 46e5b3fe..2aa92940 100644 --- a/src/drivers/win/debugger.cpp +++ b/src/drivers/win/debugger.cpp @@ -2200,7 +2200,7 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara //mbg merge 7/18/06 changed pausing check and set if (FCEUI_EmulationPaused()) { UpdateRegs(hwndDlg); - FCEUI_ToggleEmulationPause(); + FCEUI_SetEmulationPaused(0); //DebuggerWasUpdated = false done in above function; } break; diff --git a/src/fceu.cpp b/src/fceu.cpp index 062286a5..6952964f 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -112,6 +112,7 @@ bool movieSubtitles = true; //Toggle for displaying movie subtitles bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated. bool AutoResumePlay = false; char romNameWhenClosingEmulator[2048] = {0}; +bool togglePausedRequested = false; //Flaged true to pause at frame boundary FCEUGI::FCEUGI() : filename(0), @@ -656,6 +657,14 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski JustFrameAdvanced = false; + //do pausing at frame boundary to avoid inconsistency + if (togglePausedRequested) + { + togglePausedRequested = false; + if (!frameAdvanceRequested) + EmulationPaused ^= EMULATIONPAUSED_PAUSED; + } + if (frameAdvanceRequested) { if (frameAdvance_Delay_count == 0 || frameAdvance_Delay_count >= frameAdvance_Delay) @@ -1119,7 +1128,7 @@ void FCEUI_SetEmulationPaused(int val) { void FCEUI_ToggleEmulationPause(void) { - EmulationPaused = (EmulationPaused & EMULATIONPAUSED_PAUSED) ^ EMULATIONPAUSED_PAUSED; + togglePausedRequested = true;; DebuggerWasUpdated = false; } From da4194ec7a03a922901eb46fa8b7fb80e3233943 Mon Sep 17 00:00:00 2001 From: aquanull Date: Fri, 13 Apr 2018 11:59:34 +0800 Subject: [PATCH 13/18] Fixed the bug that the first frame of user input after movie end would be ignored. --- src/drivers/win/input.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/drivers/win/input.cpp b/src/drivers/win/input.cpp index 12762c9e..3021348e 100644 --- a/src/drivers/win/input.cpp +++ b/src/drivers/win/input.cpp @@ -245,9 +245,6 @@ int DTestButton(ButtConfig *bc) void UpdateGamepad(bool snes) { - if(FCEUMOV_Mode(MOVIEMODE_PLAY)) - return; - int JS=0; if(FCEUMOV_Mode(MOVIEMODE_RECORD)) AutoFire(); @@ -422,10 +419,13 @@ void FCEUD_UpdateInput() bool joy=false; bool mouse=false; bool mouse_relative=false; - EMOVIEMODE FCEUMOVState = FCEUMOV_Mode(); - UpdateRawInputAndHotkeys(); + //aquanull: if we are ok with getting real input even when emulation is paused, why should we bother skipping it when playing a movie? + bool skipRealInput = (FCEUMOV_Mode() == MOVIEMODE_PLAY && currFrameCounter < (int)currMovieData.records.size()); + UpdateRawInputAndHotkeys(); + + if (!skipRealInput) //FatRatKnight: Moved this if out of the function, a more concise fix may be desired. { for(int x=0;x<2;x++) switch(InputType[x]) @@ -469,11 +469,8 @@ void FCEUD_UpdateInput() if(joy) UpdateGamepad(false); - if (FCEUMOVState != MOVIEMODE_PLAY) //FatRatKnight: Moved this if out of the function, a more concise fix may be desired. - { - if (mouse) GetMouseData(MouseData); - if (mouse_relative) GetMouseRelative(MouseRelative); - } + if (mouse) GetMouseData(MouseData); + if (mouse_relative) GetMouseRelative(MouseRelative); } } From 3b531d0d7c22799a99b23de9a06951c9337047c5 Mon Sep 17 00:00:00 2001 From: aquanull Date: Wed, 4 Apr 2018 18:26:57 +0800 Subject: [PATCH 14/18] Small fixes. --- src/drivers/win/debugger.cpp | 4 ++-- src/drivers/win/debuggersp.cpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp index 2aa92940..30275e52 100644 --- a/src/drivers/win/debugger.cpp +++ b/src/drivers/win/debugger.cpp @@ -1770,9 +1770,9 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara { CheckDlgButton(hwndDlg, IDC_DEBUGGER_BREAK_ON_CYCLES, break_on_cycles ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_DEBUGGER_BREAK_ON_INSTRUCTIONS, break_on_instructions ? BST_CHECKED : BST_UNCHECKED); - sprintf(str, "%d", break_cycles_limit); + sprintf(str, "%u", (unsigned)break_cycles_limit); SetDlgItemText(hwndDlg, IDC_DEBUGGER_CYCLES_EXCEED, str); - sprintf(str, "%d", break_instructions_limit); + sprintf(str, "%u", (unsigned)break_instructions_limit); SetDlgItemText(hwndDlg, IDC_DEBUGGER_INSTRUCTIONS_EXCEED, str); CheckDlgButton(hwndDlg, IDC_DEBUGGER_BREAK_ON_BAD_OP, FCEUI_Debugger().badopbreak ? BST_CHECKED : BST_UNCHECKED); diff --git a/src/drivers/win/debuggersp.cpp b/src/drivers/win/debuggersp.cpp index 47b4c8f3..e2180ef9 100644 --- a/src/drivers/win/debuggersp.cpp +++ b/src/drivers/win/debuggersp.cpp @@ -429,7 +429,9 @@ Name* parse(char* lines, const char* filename) } } else { - sscanf(cur->offset, "%*[$]%4X", &(cur->offsetNumeric)); + unsigned int tempOffset; + sscanf(cur->offset, "%*[$]%4X", &(tempOffset)); + cur->offsetNumeric = (uint16)tempOffset; // Add the node to the list of address nodes if (prev) { From fe64ca3771029b928da55c9b7bf2e217e6e55a5f Mon Sep 17 00:00:00 2001 From: "aquanull@gmail.com" Date: Mon, 24 Dec 2018 12:01:25 +0800 Subject: [PATCH 15/18] Fixed the ancient buffer overflows in Memory Watch. --- src/drivers/win/memview.cpp | 4 +- src/drivers/win/memwatch.cpp | 101 ++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/src/drivers/win/memview.cpp b/src/drivers/win/memview.cpp index 4344a4c0..7ce539a4 100644 --- a/src/drivers/win/memview.cpp +++ b/src/drivers/win/memview.cpp @@ -2242,7 +2242,7 @@ BOOL CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam break; case WM_CLOSE: case WM_QUIT: - GetDlgItemText(hwndDlg,IDC_MEMVIEWFIND_WHAT,FindTextBox,59); + GetDlgItemText(hwndDlg,IDC_MEMVIEWFIND_WHAT,FindTextBox,60); DestroyWindow(hwndDlg); hMemFind = 0; hwndDlg = 0; @@ -2302,7 +2302,7 @@ void FindNext(){ unsigned char data[60]; int datasize = 0, i, j, inputc = -1, found; - if(hMemFind) GetDlgItemText(hMemFind,IDC_MEMVIEWFIND_WHAT,str,59); + if(hMemFind) GetDlgItemText(hMemFind,IDC_MEMVIEWFIND_WHAT,str,60); else strcpy(str,FindTextBox); for(i = 0;str[i] != 0;i++){ diff --git a/src/drivers/win/memwatch.cpp b/src/drivers/win/memwatch.cpp index 96c2321d..b2a203d1 100644 --- a/src/drivers/win/memwatch.cpp +++ b/src/drivers/win/memwatch.cpp @@ -72,12 +72,12 @@ extern void RemoveRecentItem(unsigned int which, char**bufferArray, const unsign //Ram change monitor globals----------------------------------- bool RamChangeInitialize = false; //Set true during memw WM_INIT const int MAX_RAMMONITOR = 4; //Maximum number of Ram values that can be monitored -char editboxnow[MAX_RAMMONITOR][5]; //current address put into editbox 00 -char editboxlast[MAX_RAMMONITOR][5]; //last address put into editbox (1 frame ago) +char editboxnow[MAX_RAMMONITOR][8]; //current address put into editbox 00 +char editboxlast[MAX_RAMMONITOR][8]; //last address put into editbox (1 frame ago) int editlast[MAX_RAMMONITOR]; //last address value (1 frame ago) int editnow[MAX_RAMMONITOR]; //current address value unsigned int editcount[MAX_RAMMONITOR]; //Current counter value -char editchangem[MAX_RAMMONITOR][5]; //counter converted to string +char editchangem[MAX_RAMMONITOR][12]; //counter converted to string //------------------------------------------------- @@ -286,15 +286,15 @@ void UpdateMemWatch() //Display blue if address is frozen if (FrozenAddressCount && FrozenAddresses.size()) { - for (unsigned int x = 0; x < FrozenAddressCount; x++) - { - if (mwrec.addr == FrozenAddresses[x]) + for (unsigned int x = 0; x < FrozenAddressCount; x++) { - //SetTextColor(hdc,RGB(0,0,255)); - SetTextColor(hdc,GetSysColor(COLOR_HIGHLIGHT)); + if (mwrec.addr == FrozenAddresses[x]) + { + //SetTextColor(hdc,RGB(0,0,255)); + SetTextColor(hdc,GetSysColor(COLOR_HIGHLIGHT)); + } } } - } char* text; if(mwrec.valid && GameInfo) @@ -336,7 +336,6 @@ void UpdateMemWatch() TextOut(hdc,0,0,text,strlen(text)); SetTextColor(hdc,RGB(0,0,0)); } - } } @@ -388,14 +387,14 @@ bool iftextchanged() int i,j; for(i=0;i Date: Mon, 24 Dec 2018 12:01:28 +0800 Subject: [PATCH 16/18] Fixed potential buffer overflows in RAM Search. --- src/drivers/win/ram_search.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/drivers/win/ram_search.cpp b/src/drivers/win/ram_search.cpp index 13452b8d..c73e41a2 100644 --- a/src/drivers/win/ram_search.cpp +++ b/src/drivers/win/ram_search.cpp @@ -146,23 +146,23 @@ void ResetMemoryRegions() { MemoryRegion& region = *iter; region.virtualIndex = nextVirtualIndex; - nextVirtualIndex = region.virtualIndex + region.size; + nextVirtualIndex = region.virtualIndex + region.size + 4; } //assert(nextVirtualIndex <= MAX_RAM_SIZE); if(nextVirtualIndex > MAX_RAM_SIZE) { - s_prevValues = (unsigned char*)realloc(s_prevValues, sizeof(char)*(nextVirtualIndex+4)); - memset(s_prevValues, 0, sizeof(char)*(nextVirtualIndex+4)); + s_prevValues = (unsigned char*)realloc(s_prevValues, sizeof(unsigned char)*nextVirtualIndex); + memset(s_prevValues, 0, sizeof(unsigned char)*nextVirtualIndex); - s_curValues = (unsigned char*)realloc(s_curValues, sizeof(char)*(nextVirtualIndex+4)); - memset(s_curValues, 0, sizeof(char)*(nextVirtualIndex+4)); + s_curValues = (unsigned char*)realloc(s_curValues, sizeof(unsigned char)*nextVirtualIndex); + memset(s_curValues, 0, sizeof(unsigned char)*nextVirtualIndex); - s_numChanges = (unsigned short*)realloc(s_numChanges, sizeof(short)*(nextVirtualIndex+4)); - memset(s_numChanges, 0, sizeof(short)*(nextVirtualIndex+4)); + s_numChanges = (unsigned short*)realloc(s_numChanges, sizeof(unsigned short)*nextVirtualIndex); + memset(s_numChanges, 0, sizeof(unsigned short)*nextVirtualIndex); - s_itemIndexToRegionPointer = (MemoryRegion**)realloc(s_itemIndexToRegionPointer, sizeof(MemoryRegion*)*(nextVirtualIndex+4)); - memset(s_itemIndexToRegionPointer, 0, sizeof(MemoryRegion*)*(nextVirtualIndex+4)); + s_itemIndexToRegionPointer = (MemoryRegion**)realloc(s_itemIndexToRegionPointer, sizeof(MemoryRegion*)*nextVirtualIndex); + memset(s_itemIndexToRegionPointer, 0, sizeof(MemoryRegion*)*nextVirtualIndex); MAX_RAM_SIZE = nextVirtualIndex; } From 08c602a3f2c1a92364231ff55e7de497da59b79e Mon Sep 17 00:00:00 2001 From: "aquanull@gmail.com" Date: Mon, 24 Dec 2018 12:01:32 +0800 Subject: [PATCH 17/18] Registered Lua callbacks via gui.register() are now only called at frame boundaries. --- src/fceu.cpp | 2 ++ src/ppu.cpp | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/fceu.cpp b/src/fceu.cpp index 6952964f..659307ea 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -731,6 +731,8 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION); #endif + FCEU_PutImage(); + #ifdef WIN32 //These Windows only dialogs need to be updated only once per frame so they are included here UpdateCheatList(); // CaH4e3: can't see why, this is only cause problems with selection - adelikat: selection is only a problem when not paused, it shoudl be paused to select, we want to see the values update diff --git a/src/ppu.cpp b/src/ppu.cpp index 7c78b8bc..175cee26 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -1862,7 +1862,6 @@ int FCEUPPU_Loop(int skip) { } else #endif { - FCEU_PutImage(); return(1); } } @@ -2429,7 +2428,5 @@ int FCEUX_PPU_Loop(int skip) { } finish: - FCEU_PutImage(); - return 0; } From dd5a0e908e5e31ca54cfd5b1b276e33e094d2ff6 Mon Sep 17 00:00:00 2001 From: "aquanull@gmail.com" Date: Mon, 24 Dec 2018 13:54:32 +0800 Subject: [PATCH 18/18] Re-enabled running the Lua script when loaded. --- src/lua-engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index e09333e3..da812a0a 100644 --- a/src/lua-engine.cpp +++ b/src/lua-engine.cpp @@ -6178,7 +6178,7 @@ int FCEU_LoadLuaCode(const char *filename, const char *arg) { //if (wasPaused) FCEUI_ToggleEmulationPause(); // And run it right now. :) - //FCEU_LuaFrameBoundary(); + FCEU_LuaFrameBoundary(); // Set up our protection hook to be executed once every 10,000 bytecode instructions. //lua_sethook(thread, FCEU_LuaHookFunction, LUA_MASKCOUNT, 10000);