From bc6164260dbfc274881de19cc43d9366df5d0b63 Mon Sep 17 00:00:00 2001 From: harry Date: Sat, 11 Mar 2023 07:47:58 -0500 Subject: [PATCH] State recorder in work. --- src/drivers/Qt/ConsoleWindow.cpp | 18 +++++++++ src/drivers/Qt/ConsoleWindow.h | 2 + src/drivers/Qt/config.cpp | 6 +++ src/drivers/Qt/config.h | 3 ++ src/state.cpp | 67 ++++++++++++++++++++++++++++++-- src/state.h | 2 + 6 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 0613edc9..b35f37aa 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -53,6 +53,7 @@ #include "../../input.h" #include "../../movie.h" #include "../../wave.h" +#include "../../state.h" #include "../../version.h" #include "common/os_utils.h" @@ -920,6 +921,9 @@ void consoleWin_t::initHotKeys(void) connect( Hotkeys[ HK_LOAD_STATE_7 ].getShortcut(), SIGNAL(activated()), this, SLOT(loadState7(void)) ); connect( Hotkeys[ HK_LOAD_STATE_8 ].getShortcut(), SIGNAL(activated()), this, SLOT(loadState8(void)) ); connect( Hotkeys[ HK_LOAD_STATE_9 ].getShortcut(), SIGNAL(activated()), this, SLOT(loadState9(void)) ); + + connect( Hotkeys[ HK_LOAD_PREV_STATE ].getShortcut(), SIGNAL(activated()), this, SLOT(loadPrevState(void)) ); + connect( Hotkeys[ HK_LOAD_NEXT_STATE ].getShortcut(), SIGNAL(activated()), this, SLOT(loadNextState(void)) ); } //--------------------------------------------------------------------------- void consoleWin_t::createMainMenu(void) @@ -2729,6 +2733,20 @@ void consoleWin_t::loadState7(void){ loadState(7); } void consoleWin_t::loadState8(void){ loadState(8); } void consoleWin_t::loadState9(void){ loadState(9); } +void consoleWin_t::loadPrevState(void) +{ + FCEU_WRAPPER_LOCK(); + FCEU_StateRecorderLoadState( FCEU_StateRecorderGetStateIndex()-1 ); + FCEU_WRAPPER_UNLOCK(); +} + +void consoleWin_t::loadNextState(void) +{ + FCEU_WRAPPER_LOCK(); + FCEU_StateRecorderLoadState( FCEU_StateRecorderGetStateIndex()-1 ); + FCEU_WRAPPER_UNLOCK(); +} + void consoleWin_t::quickSave(void) { FCEU_WRAPPER_LOCK(); diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index eda9fd34..59ccf23d 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -439,6 +439,8 @@ class consoleWin_t : public QMainWindow void loadState7(void); void loadState8(void); void loadState9(void); + void loadPrevState(void); + void loadNextState(void); void mainMenuOpen(void); void mainMenuClose(void); void warnAmbiguousShortcut( QShortcut*); diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index fc314283..7d7c1d87 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -295,6 +295,12 @@ int getHotKeyConfig( int i, const char **nameOut, const char **keySeqOut, const case HK_SELECT_STATE_PREV: name = "SelectStatePrev"; keySeq = ""; title = "Select Previous State Slot"; group = "State"; break; + case HK_LOAD_PREV_STATE: + name = "LoadPrevState"; keySeq = ""; title = "Load Previous Recorded State"; group = "State"; + break; + case HK_LOAD_NEXT_STATE: + name = "LoadNextState"; keySeq = ""; title = "Load Next Recorded State"; group = "State"; + break; case HK_VOLUME_MUTE: name = "VolumeMute"; keySeq = ""; title = "Sound Volume Mute"; group = "Sound"; break; diff --git a/src/drivers/Qt/config.h b/src/drivers/Qt/config.h index 54a6e5d8..60bbac7e 100644 --- a/src/drivers/Qt/config.h +++ b/src/drivers/Qt/config.h @@ -34,6 +34,9 @@ enum HOTKEY { HK_SELECT_STATE_5, HK_SELECT_STATE_6, HK_SELECT_STATE_7, HK_SELECT_STATE_8, HK_SELECT_STATE_9, HK_SELECT_STATE_NEXT, HK_SELECT_STATE_PREV, + // State Recorder + HK_LOAD_PREV_STATE, HK_LOAD_NEXT_STATE, + // GUI HK_FULLSCREEN, HK_MAIN_MENU_HIDE, diff --git a/src/state.cpp b/src/state.cpp index cdce4ad8..fdfbec4c 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -1202,6 +1202,9 @@ class StateRecorder frameCounter = 0; framesPerSnap = 3 * 60; compressionLevel = Z_NO_COMPRESSION; + lastState = ringHead; + loadIndexReset = false; + lastLoadFrame = 0; } ~StateRecorder(void) @@ -1215,9 +1218,22 @@ class StateRecorder void update(void) { + bool isPaused = FCEUI_EmulationPaused() ? true : false; + unsigned int curFrame = static_cast(currFrameCounter); - if (curFrame != frameCounter) + if (!isPaused && loadIndexReset) + { + int ringBufSize = static_cast( ringBuf.size() ); + + ringHead = (lastState + 1) % ringBufSize; + + frameCounter = curFrame; + + loadIndexReset = false; + } + + if (!isPaused && (curFrame > frameCounter) ) { frameCounter = curFrame; @@ -1233,17 +1249,19 @@ class StateRecorder //printf("Frame:%u Save:%i Size:%zu Total:%zukB \n", frameCounter, ringHead, em->size(), dataSize() / 1024 ); + lastState = ringHead; + ringHead = (ringHead + 1) % ringBufSize; if (ringStart == ringHead) - { // Buffer Overrun + { ringStart = (ringHead + 1) % ringBufSize; } } } } - int loadState( int numSnapsFromLatest ) + int loadStateRelativeToEnd( int numSnapsFromLatest ) { int ringBufSize = static_cast( ringBuf.size() ); @@ -1255,18 +1273,43 @@ class StateRecorder int snapIdx = ringHead - numSnapsFromLatest - 1; + loadStateByIndex(snapIdx); + + return 0; + } + + int loadStateByIndex( int snapIdx ) + { + int ringBufSize = static_cast( ringBuf.size() ); + if (snapIdx < 0) { snapIdx = snapIdx + ringBufSize; } + snapIdx = snapIdx % ringBufSize; EMUFILE_MEMORY *em = ringBuf[ snapIdx ]; FCEUSS_LoadFP( em, SSLOADPARAM_NOBACKUP ); + frameCounter = lastLoadFrame = static_cast(currFrameCounter); + + lastState = snapIdx; + loadIndexReset = true; + return 0; } + int getHeadIndex(void) + { + return ringHead; + } + + int getStartIndex(void) + { + return ringStart; + } + int numSnapsSaved(void) { int numSnaps = ringHead - ringStart; @@ -1284,6 +1327,7 @@ class StateRecorder } static bool enabled; + static int lastState; private: void doSnap(void) @@ -1298,11 +1342,14 @@ class StateRecorder int compressionLevel; unsigned int frameCounter; unsigned int framesPerSnap; + unsigned int lastLoadFrame; + bool loadIndexReset; }; static StateRecorder *stateRecorder = nullptr; bool StateRecorder::enabled = false; +int StateRecorder::lastState = 0; int FCEU_StateRecorderStart(void) { @@ -1340,3 +1387,17 @@ bool FCEU_StateRecorderRunning(void) { return stateRecorder != nullptr; } + +int FCEU_StateRecorderLoadState(int snapIndex) +{ + if (stateRecorder != nullptr) + { + stateRecorder->loadStateByIndex(snapIndex); + } + return 0; +} + +int FCEU_StateRecorderGetStateIndex(void) +{ + return StateRecorder::lastState; +} diff --git a/src/state.h b/src/state.h index 3899a7aa..097f1977 100644 --- a/src/state.h +++ b/src/state.h @@ -84,3 +84,5 @@ int FCEU_StateRecorderStop(void); int FCEU_StateRecorderUpdate(void); bool FCEU_StateRecorderRunning(void); bool FCEU_StateRecorderIsEnabled(void); +int FCEU_StateRecorderGetStateIndex(void); +int FCEU_StateRecorderLoadState(int snapIndex);