From d7c23fa92ef3b5829a2bd6ad137367b4e94b1678 Mon Sep 17 00:00:00 2001 From: harry Date: Sat, 4 Mar 2023 16:34:21 -0500 Subject: [PATCH] FCEU state recorder in work. --- src/emufile.h | 4 +- src/fceu.cpp | 9 +++ src/state.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/state.h | 6 ++ 4 files changed, 178 insertions(+), 2 deletions(-) diff --git a/src/emufile.h b/src/emufile.h index 0bd65c3d..623f6c21 100644 --- a/src/emufile.h +++ b/src/emufile.h @@ -179,10 +179,10 @@ public: va_start(argptr, format); vsprintf(tempbuf,format,argptr); - fwrite(tempbuf,amt); + fwrite(tempbuf,amt); delete[] tempbuf; - va_end(argptr); + va_end(argptr); return amt; }; diff --git a/src/fceu.cpp b/src/fceu.cpp index 49f5c750..ce870582 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -208,6 +208,8 @@ static void FCEU_CloseGame(void) GameInterface(GI_CLOSE); + FCEU_StateRecorderStop(); + FCEUI_StopMovie(); ResetExState(0, 0); @@ -592,6 +594,12 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen } FCEU_fclose(fp); + + if ( FCEU_StateRecorderIsEnabled() ) + { + FCEU_StateRecorderStart(); + } + return GameInfo; } @@ -793,6 +801,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski AutoFire(); UpdateAutosave(); + FCEU_StateRecorderUpdate(); #ifdef _S9XLUA_H FCEU_LuaFrameBoundary(); diff --git a/src/state.cpp b/src/state.cpp index 0ef771e8..cdce4ad8 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -1179,3 +1179,164 @@ void RedoLoadState() redoLS = false; //Flag that RedoLoadState can not be run again undoLS = true; //Flag that LoadBackup can be run again } + +//----------------------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------------------- +//----------- Save State History ---------------- +//----------------------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------------------- +class StateRecorder +{ + public: + StateRecorder(void) + { + size_t ringBufSize = 60; + + for (size_t i=0; i(currFrameCounter); + + if (curFrame != frameCounter) + { + frameCounter = curFrame; + + if ( (frameCounter % framesPerSnap) == 0 ) + { + int ringBufSize = static_cast( ringBuf.size() ); + + EMUFILE_MEMORY *em = ringBuf[ ringHead ]; + + em->set_len(0); + + FCEUSS_SaveMS( em, compressionLevel ); + + //printf("Frame:%u Save:%i Size:%zu Total:%zukB \n", frameCounter, ringHead, em->size(), dataSize() / 1024 ); + + ringHead = (ringHead + 1) % ringBufSize; + + if (ringStart == ringHead) + { // Buffer Overrun + ringStart = (ringHead + 1) % ringBufSize; + } + } + } + } + + int loadState( int numSnapsFromLatest ) + { + int ringBufSize = static_cast( ringBuf.size() ); + + if (numSnapsFromLatest < 0) + { + numSnapsFromLatest = 0; + } + numSnapsFromLatest = numSnapsFromLatest % ringBufSize; + + int snapIdx = ringHead - numSnapsFromLatest - 1; + + if (snapIdx < 0) + { + snapIdx = snapIdx + ringBufSize; + } + + EMUFILE_MEMORY *em = ringBuf[ snapIdx ]; + + FCEUSS_LoadFP( em, SSLOADPARAM_NOBACKUP ); + + return 0; + } + + int numSnapsSaved(void) + { + int numSnaps = ringHead - ringStart; + + if (numSnaps < 0) + { + numSnaps = numSnaps + static_cast( ringBuf.size() ); + } + return numSnaps; + } + + size_t dataSize(void) + { + return ringBuf.size() * ringBuf[0]->size(); + } + + static bool enabled; + private: + + void doSnap(void) + { + + } + + std::vector ringBuf; + int ringHead; + int ringTail; + int ringStart; + int compressionLevel; + unsigned int frameCounter; + unsigned int framesPerSnap; + +}; + +static StateRecorder *stateRecorder = nullptr; +bool StateRecorder::enabled = false; + +int FCEU_StateRecorderStart(void) +{ + if (stateRecorder == nullptr) + { + stateRecorder = new StateRecorder(); + } + return stateRecorder == nullptr; +} + +int FCEU_StateRecorderStop(void) +{ + if (stateRecorder != nullptr) + { + delete stateRecorder; stateRecorder = nullptr; + } + return stateRecorder != nullptr; +} + +int FCEU_StateRecorderUpdate(void) +{ + if (stateRecorder != nullptr) + { + stateRecorder->update(); + } + return 0; +} + +bool FCEU_StateRecorderIsEnabled(void) +{ + return StateRecorder::enabled; +} + +bool FCEU_StateRecorderRunning(void) +{ + return stateRecorder != nullptr; +} diff --git a/src/state.h b/src/state.h index 4157dc9e..3899a7aa 100644 --- a/src/state.h +++ b/src/state.h @@ -78,3 +78,9 @@ extern bool backupSavestates; //Whether or not to make backups, true by defaul bool CheckBackupSaveStateExist(); //Checks if backupsavestate exists extern bool compressSavestates; //Whether or not to compress non-movie savestates (by default, yes) + +int FCEU_StateRecorderStart(void); +int FCEU_StateRecorderStop(void); +int FCEU_StateRecorderUpdate(void); +bool FCEU_StateRecorderRunning(void); +bool FCEU_StateRecorderIsEnabled(void);