From a0289a5e95610765efe67279bc16a4c843d45b74 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sun, 26 Nov 2017 18:16:32 -0500 Subject: [PATCH] Movies: Allow rewinding in movies --- Core/BizhawkMovie.cpp | 6 +++++- Core/BizhawkMovie.h | 1 + Core/Console.cpp | 4 ---- Core/FceuxMovie.cpp | 1 + Core/GameClientConnection.cpp | 3 --- Core/MesenMovie.cpp | 20 ++++++++++++-------- Core/MesenMovie.h | 4 +++- Core/SaveStateManager.cpp | 5 +++++ Core/ShortcutKeyHandler.cpp | 2 +- 9 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Core/BizhawkMovie.cpp b/Core/BizhawkMovie.cpp index 5c28e67b..72564df3 100644 --- a/Core/BizhawkMovie.cpp +++ b/Core/BizhawkMovie.cpp @@ -30,7 +30,7 @@ void BizhawkMovie::Stop() bool BizhawkMovie::SetInput(BaseControlDevice *device) { SystemActionManager* actionManager = dynamic_cast(device); - int32_t frameNumber = PPU::GetFrameCount(); + int32_t frameNumber = _gameLoaded ? PPU::GetFrameCount() : 0; if(actionManager) { if(frameNumber < (int32_t)_systemActionByFrame.size()) { uint32_t systemAction = _systemActionByFrame[frameNumber]; @@ -96,6 +96,8 @@ bool BizhawkMovie::InitializeGameData(ZipReader &reader) return false; } + _gameLoaded = false; + while(!fileData.eof()) { string line; std::getline(fileData, line); @@ -104,6 +106,7 @@ bool BizhawkMovie::InitializeGameData(ZipReader &reader) HashInfo hashInfo; hashInfo.Sha1Hash = line.substr(5, 40); if(Console::LoadROM("", hashInfo)) { + _gameLoaded = true; return true; } } @@ -113,6 +116,7 @@ bool BizhawkMovie::InitializeGameData(ZipReader &reader) hashInfo.PrgChrMd5Hash = line.substr(4, 32); std::transform(hashInfo.PrgChrMd5Hash.begin(), hashInfo.PrgChrMd5Hash.end(), hashInfo.PrgChrMd5Hash.begin(), ::toupper); if(Console::LoadROM("", hashInfo)) { + _gameLoaded = true; return true; } } diff --git a/Core/BizhawkMovie.h b/Core/BizhawkMovie.h index b3b1d3d2..08aafbe6 100644 --- a/Core/BizhawkMovie.h +++ b/Core/BizhawkMovie.h @@ -16,6 +16,7 @@ protected: vector _systemActionByFrame; vector _dataByFrame[4]; bool _isPlaying = false; + bool _gameLoaded = false; RamPowerOnState _originalPowerOnState; public: diff --git a/Core/Console.cpp b/Core/Console.cpp index 32e427aa..f746373f 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -625,10 +625,6 @@ void Console::SaveState(ostream &saveStream) void Console::LoadState(istream &loadStream, uint32_t stateVersion) { if(Instance->_initialized) { - //Stop any movie that might have been playing/recording if a state is loaded - //(Note: Loading a state is disabled in the UI while a movie is playing/recording) - MovieManager::Stop(); - Instance->_cpu->LoadSnapshot(&loadStream, stateVersion); Instance->_ppu->LoadSnapshot(&loadStream, stateVersion); Instance->_memoryManager->LoadSnapshot(&loadStream, stateVersion); diff --git a/Core/FceuxMovie.cpp b/Core/FceuxMovie.cpp index 94d84c97..37cdfbf1 100644 --- a/Core/FceuxMovie.cpp +++ b/Core/FceuxMovie.cpp @@ -24,6 +24,7 @@ bool FceuxMovie::InitializeData(stringstream &filestream) HashInfo hashInfo; hashInfo.PrgChrMd5Hash = HexUtilities::ToHex(md5array); if(Console::LoadROM("", hashInfo)) { + _gameLoaded = true; result = true; } else { return false; diff --git a/Core/GameClientConnection.cpp b/Core/GameClientConnection.cpp index 3c8c3832..50088de7 100644 --- a/Core/GameClientConnection.cpp +++ b/Core/GameClientConnection.cpp @@ -152,8 +152,6 @@ void GameClientConnection::DisableControllers() bool GameClientConnection::SetInput(BaseControlDevice *device) { - device->SetRawState(ControlDeviceState()); - if(_enableControllers) { uint8_t port = device->GetPort(); while(_inputSize[port] == 0) { @@ -183,7 +181,6 @@ bool GameClientConnection::SetInput(BaseControlDevice *device) } device->SetRawState(state); - return true; } return true; } diff --git a/Core/MesenMovie.cpp b/Core/MesenMovie.cpp index 54a12847..51e459e2 100644 --- a/Core/MesenMovie.cpp +++ b/Core/MesenMovie.cpp @@ -12,6 +12,7 @@ #include "MovieRecorder.h" #include "BatteryManager.h" #include "VirtualFile.h" +#include "PPU.h" MesenMovie::MesenMovie() { @@ -33,14 +34,15 @@ void MesenMovie::Stop() bool MesenMovie::SetInput(BaseControlDevice *device) { - if(_inputData.size() > _readIndex && _inputData[_readIndex].size() > _deviceIndex) { - device->SetTextState(_inputData[_readIndex][_deviceIndex]); + uint32_t inputRowIndex = _gameLoaded ? PPU::GetFrameCount() - _firstFrameNumber : 0; + + if(_inputData.size() > inputRowIndex && _inputData[inputRowIndex].size() > _deviceIndex) { + device->SetTextState(_inputData[inputRowIndex][_deviceIndex]); _deviceIndex++; - if(_deviceIndex >= _inputData[_readIndex].size()) { + if(_deviceIndex >= _inputData[inputRowIndex].size()) { //Move to the next frame's data _deviceIndex = 0; - _readIndex++; } } else { Stop(); @@ -88,7 +90,6 @@ bool MesenMovie::Play(VirtualFile &file) } } - _readIndex = 0; _deviceIndex = 0; ParseSettings(settingsData); @@ -99,20 +100,23 @@ bool MesenMovie::Play(VirtualFile &file) ControlManager::RegisterInputProvider(this); ApplySettings(); + _gameLoaded = false; + if(!LoadGame()) { Console::Resume(); return false; } + _gameLoaded = true; + _firstFrameNumber = 0; + stringstream saveStateData; if(_reader->GetStream("SaveState.mst", saveStateData)) { if(!SaveStateManager::LoadState(saveStateData, true)) { Console::Resume(); return false; } else { - //Reset to first line of the input log - //TODO: Change this to allow rewinding during movie playback - _readIndex = 0; + _firstFrameNumber = PPU::GetFrameCount(); } } diff --git a/Core/MesenMovie.h b/Core/MesenMovie.h index f51b7f9a..c4d6776b 100644 --- a/Core/MesenMovie.h +++ b/Core/MesenMovie.h @@ -15,12 +15,14 @@ private: VirtualFile _movieFile; shared_ptr _reader; bool _playing = false; - size_t _readIndex = 0; size_t _deviceIndex = 0; vector> _inputData; vector _cheats; std::unordered_map _settings; string _filename; + + bool _gameLoaded = false; + uint32_t _firstFrameNumber = 0; private: void ParseSettings(stringstream &data); diff --git a/Core/SaveStateManager.cpp b/Core/SaveStateManager.cpp index 5ed81318..6246e339 100644 --- a/Core/SaveStateManager.cpp +++ b/Core/SaveStateManager.cpp @@ -8,6 +8,7 @@ #include "EmulationSettings.h" #include "VideoDecoder.h" #include "Debugger.h" +#include "MovieManager.h" const uint32_t SaveStateManager::FileFormatVersion; atomic SaveStateManager::_lastIndex(1); @@ -147,6 +148,10 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired) } } + //Stop any movie that might have been playing/recording if a state is loaded + //(Note: Loading a state is disabled in the UI while a movie is playing/recording) + MovieManager::Stop(); + Console::LoadState(stream, fileFormatVersion); return true; diff --git a/Core/ShortcutKeyHandler.cpp b/Core/ShortcutKeyHandler.cpp index 90f38253..5b649f9e 100644 --- a/Core/ShortcutKeyHandler.cpp +++ b/Core/ShortcutKeyHandler.cpp @@ -167,7 +167,7 @@ void ShortcutKeyHandler::CheckMappedKeys() } } - if(!isNetplayClient && !isMovieActive && !EmulationSettings::CheckFlag(NsfPlayerEnabled)) { + if(!isNetplayClient && !EmulationSettings::CheckFlag(NsfPlayerEnabled)) { if(DetectKeyPress(EmulatorShortcut::ToggleRewind)) { if(RewindManager::IsRewinding()) { RewindManager::StopRewinding();