From 8836d84954bc81a9dc2e651d2fcb8ecd80d637a6 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 3 Apr 2022 22:26:22 +0200 Subject: [PATCH] Remove Rewind code and Movie code --- Core/BizhawkMovie.cpp | 225 -------------------- Core/BizhawkMovie.h | 37 ---- Core/Console.cpp | 13 -- Core/Console.h | 4 - Core/ControlManager.cpp | 7 - Core/EmulationSettings.h | 1 - Core/FDS.cpp | 5 +- Core/FceuxMovie.cpp | 79 ------- Core/FceuxMovie.h | 16 -- Core/GameClient.cpp | 112 ---------- Core/GameClient.h | 42 ---- Core/GameClientConnection.cpp | 270 ------------------------ Core/GameClientConnection.h | 61 ------ Core/GameConnection.cpp | 99 --------- Core/GameConnection.h | 45 ---- Core/GameServer.cpp | 242 --------------------- Core/GameServer.h | 58 ------ Core/GameServerConnection.cpp | 248 ---------------------- Core/GameServerConnection.h | 52 ----- Core/HistoryViewer.cpp | 164 --------------- Core/HistoryViewer.h | 39 ---- Core/IInputRecorder.h | 6 - Core/MesenMovie.cpp | 340 ------------------------------ Core/MesenMovie.h | 52 ----- Core/MovieDataMessage.h | 37 ---- Core/MovieManager.cpp | 70 ------- Core/MovieManager.h | 31 --- Core/MovieRecorder.cpp | 265 ----------------------- Core/MovieRecorder.h | 86 -------- Core/RewindData.cpp | 46 ---- Core/RewindData.h | 25 --- Core/RewindManager.cpp | 382 ---------------------------------- Core/RewindManager.h | 78 ------- Core/SaveStateManager.cpp | 5 - Core/VsControlManager.h | 3 +- Libretro/Makefile.common | 13 -- 36 files changed, 3 insertions(+), 3255 deletions(-) delete mode 100644 Core/BizhawkMovie.cpp delete mode 100644 Core/BizhawkMovie.h delete mode 100644 Core/FceuxMovie.cpp delete mode 100644 Core/FceuxMovie.h delete mode 100644 Core/GameClient.cpp delete mode 100644 Core/GameClient.h delete mode 100644 Core/GameClientConnection.cpp delete mode 100644 Core/GameClientConnection.h delete mode 100644 Core/GameConnection.cpp delete mode 100644 Core/GameConnection.h delete mode 100644 Core/GameServer.cpp delete mode 100644 Core/GameServer.h delete mode 100644 Core/GameServerConnection.cpp delete mode 100644 Core/GameServerConnection.h delete mode 100644 Core/HistoryViewer.cpp delete mode 100644 Core/HistoryViewer.h delete mode 100644 Core/MesenMovie.cpp delete mode 100644 Core/MesenMovie.h delete mode 100644 Core/MovieDataMessage.h delete mode 100644 Core/MovieManager.cpp delete mode 100644 Core/MovieManager.h delete mode 100644 Core/MovieRecorder.cpp delete mode 100644 Core/MovieRecorder.h delete mode 100644 Core/RewindData.cpp delete mode 100644 Core/RewindData.h delete mode 100644 Core/RewindManager.cpp delete mode 100644 Core/RewindManager.h diff --git a/Core/BizhawkMovie.cpp b/Core/BizhawkMovie.cpp deleted file mode 100644 index 8e4efa22..00000000 --- a/Core/BizhawkMovie.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include "stdafx.h" -#include "ControlManager.h" -#include "SystemActionManager.h" -#include "FdsSystemActionManager.h" -#include "VsSystemActionManager.h" -#include "BizhawkMovie.h" -#include "VsControlManager.h" -#include "Console.h" -#include "BatteryManager.h" -#include "NotificationManager.h" - -BizhawkMovie::BizhawkMovie(shared_ptr console) -{ - _console = console; - _originalPowerOnState = _console->GetSettings()->GetRamPowerOnState(); -} - -BizhawkMovie::~BizhawkMovie() -{ - Stop(); -} - -void BizhawkMovie::Stop() -{ - if(_isPlaying) { - MessageManager::DisplayMessage("Movies", "MovieEnded"); - - _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::MovieEnded); - if(_console->GetSettings()->CheckFlag(EmulationFlags::PauseOnMovieEnd)) { - _console->GetSettings()->SetFlags(EmulationFlags::Paused); - } - - _console->GetSettings()->SetRamPowerOnState(_originalPowerOnState); - _isPlaying = false; - } - _console->GetControlManager()->UnregisterInputProvider(this); -} - -bool BizhawkMovie::SetInput(BaseControlDevice *device) -{ - SystemActionManager* actionManager = dynamic_cast(device); - int32_t pollCounter = _console->GetControlManager()->GetPollCounter(); - if(actionManager) { - if(pollCounter < (int32_t)_systemActionByFrame.size()) { - uint32_t systemAction = _systemActionByFrame[pollCounter]; - if(systemAction & 0x01) { - actionManager->SetBit(SystemActionManager::Buttons::PowerButton); - } - if(systemAction & 0x02) { - actionManager->SetBit(SystemActionManager::Buttons::ResetButton); - } - - VsSystemActionManager* vsActionManager = dynamic_cast(device); - if(vsActionManager) { - if(systemAction & 0x04) { - actionManager->SetBit(VsSystemActionManager::VsButtons::InsertCoin1); - } - if(systemAction & 0x08) { - actionManager->SetBit(VsSystemActionManager::VsButtons::InsertCoin2); - } - if(systemAction & 0x10) { - actionManager->SetBit(VsSystemActionManager::VsButtons::ServiceButton); - } - } - - FdsSystemActionManager* fdsActionManager = dynamic_cast(device); - if(fdsActionManager) { - //FDS timings between NesHawk & Mesen are currently significantly different - //So FDS games will always go out of sync - if(systemAction & 0x04) { - fdsActionManager->SetBit(FdsSystemActionManager::FdsButtons::EjectDiskButton); - } - - if(systemAction >= 8) { - systemAction >>= 3; - uint32_t diskNumber = 0; - while(!(systemAction & 0x01)) { - systemAction >>= 1; - diskNumber++; - } - - fdsActionManager->SetBit(FdsSystemActionManager::FdsButtons::InsertDisk1 + diskNumber); - } - } - } - } else { - int port = device->GetPort(); - StandardController* controller = dynamic_cast(device); - if(controller) { - if(pollCounter < (int32_t)_dataByFrame[port].size()) { - controller->SetTextState(_dataByFrame[port][pollCounter]); - } else { - Stop(); - } - } - } - - return true; -} - -bool BizhawkMovie::InitializeGameData(ZipReader &reader) -{ - stringstream fileData; - if(!reader.GetStream("Header.txt", fileData)) { - return false; - } - - _console->GetControlManager()->SetPollCounter(0); - - while(!fileData.eof()) { - string line; - std::getline(fileData, line); - if(line.compare(0, 4, "SHA1", 4) == 0) { - if(line.size() >= 45) { - HashInfo hashInfo; - hashInfo.Sha1 = line.substr(5, 40); - if(_console->LoadMatchingRom("", hashInfo)) { - return true; - } - } - } else if(line.compare(0, 3, "MD5", 3) == 0) { - if(line.size() >= 36) { - HashInfo hashInfo; - hashInfo.PrgChrMd5 = line.substr(4, 32); - std::transform(hashInfo.PrgChrMd5.begin(), hashInfo.PrgChrMd5.end(), hashInfo.PrgChrMd5.begin(), ::toupper); - if(_console->LoadMatchingRom("", hashInfo)) { - return true; - } - } - } - } - return false; -} - -bool BizhawkMovie::InitializeInputData(ZipReader &reader) -{ - stringstream inputData; - if(!reader.GetStream("Input Log.txt", inputData)) { - return false; - } - - int systemActionCount = 2; - shared_ptr fdsActionManager = _console->GetSystemActionManager(); - if(fdsActionManager) { - //Eject disk + Insert Disk #XX - systemActionCount += fdsActionManager->GetSideCount() + 1; - } else { - shared_ptr vsActionManager = _console->GetSystemActionManager(); - if(vsActionManager) { - //Insert coin 1, 2 + service button - systemActionCount += 3; - } - } - - while(!inputData.eof()) { - string line; - std::getline(inputData, line); - - if(line.size() > 0 && line[0] == '|') { - line.erase(std::remove(line.begin(), line.end(), '|'), line.end()); - line = line.substr(0, line.size() - 1); - - //Read power/reset/FDS/VS/etc. commands - uint32_t systemAction = 0; - for(int i = 0; i < systemActionCount; i++) { - if(line[i] != '.') { - systemAction |= (1 << i); - } - } - _systemActionByFrame.push_back(systemAction); - - line = line.substr(systemActionCount); - int port = 0; - while(line.size() >= 8) { - _dataByFrame[port].push_back(line.substr(0, 8)); - line = line.substr(8); - port++; - } - while(port < 4) { - _dataByFrame[port].push_back("........"); - port++; - } - } - } - - return _dataByFrame[0].size() > 0; -} - -bool BizhawkMovie::Play(VirtualFile &file) -{ - _console->Pause(); - ZipReader reader; - - std::stringstream ss; - file.ReadFile(ss); - - reader.LoadArchive(ss); - - _console->GetNotificationManager()->RegisterNotificationListener(shared_from_this()); - _console->GetSettings()->SetRamPowerOnState(RamPowerOnState::AllOnes); - _console->GetBatteryManager()->SetBatteryProvider(shared_from_this()); - if(InitializeInputData(reader) && InitializeGameData(reader)) { - //NesHawk initializes memory to 1s - _isPlaying = true; - } - _console->Resume(); - return _isPlaying; -} - -bool BizhawkMovie::IsPlaying() -{ - return _isPlaying; -} - -void BizhawkMovie::ProcessNotification(ConsoleNotificationType type, void* parameter) -{ - if(type == ConsoleNotificationType::GameLoaded) { - _console->GetControlManager()->RegisterInputProvider(this); - } -} - -vector BizhawkMovie::LoadBattery(string extension) -{ - return vector(); -} diff --git a/Core/BizhawkMovie.h b/Core/BizhawkMovie.h deleted file mode 100644 index 901353ae..00000000 --- a/Core/BizhawkMovie.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "stdafx.h" -#include "MovieManager.h" -#include "../Utilities/ZipReader.h" -#include "INotificationListener.h" -#include "BatteryManager.h" - -class VirtualFile; -class Console; - -class BizhawkMovie : public IMovie, public INotificationListener, public IBatteryProvider, public std::enable_shared_from_this -{ -private: - bool InitializeGameData(ZipReader &reader); - bool InitializeInputData(ZipReader &reader); - void Stop(); - -protected: - shared_ptr _console; - - vector _systemActionByFrame; - vector _dataByFrame[4]; - bool _isPlaying = false; - RamPowerOnState _originalPowerOnState; - -public: - BizhawkMovie(shared_ptr); - virtual ~BizhawkMovie(); - - bool SetInput(BaseControlDevice *device) override; - bool Play(VirtualFile &file) override; - bool IsPlaying() override; - - // Inherited via INotificationListener - virtual void ProcessNotification(ConsoleNotificationType type, void * parameter) override; - virtual vector LoadBattery(string extension) override; -}; \ No newline at end of file diff --git a/Core/Console.cpp b/Core/Console.cpp index b9da36d7..5041e460 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -21,7 +21,6 @@ #include "NsfPpu.h" #include "SoundMixer.h" #include "NsfMapper.h" -#include "MovieManager.h" #include "SaveStateManager.h" #include "HdPackBuilder.h" #include "HdAudioDevice.h" @@ -39,7 +38,6 @@ #include "VideoDecoder.h" #include "VideoRenderer.h" #include "NotificationManager.h" -#include "HistoryViewer.h" #include "ConsolePauseHelper.h" #include "EventManager.h" @@ -65,7 +63,6 @@ Console::Console(shared_ptr master, EmulationSettings* initialSettings) Console::~Console() { - MovieManager::Stop(); } void Console::Init() @@ -266,7 +263,6 @@ bool Console::Initialize(VirtualFile &romFile, VirtualFile &patchFile, bool forP _patchFilename = patchFile; //Changed game, stop all recordings - MovieManager::Stop(); _soundMixer->StopRecording(); StopRecordingHdPack(); } @@ -468,11 +464,6 @@ CheatManager* Console::GetCheatManager() return _cheatManager.get(); } -HistoryViewer* Console::GetHistoryViewer() -{ - return _historyViewer.get(); -} - VirtualFile Console::GetRomPath() { return static_cast(_romFilepath); @@ -640,9 +631,6 @@ void Console::Run() RunSlaveCpu(); } - if(_historyViewer) { - _historyViewer->ProcessEndOfFrame(); - } _settings->DisableOverclocking(_disableOcNextFrame || IsNsf()); _disableOcNextFrame = false; @@ -734,7 +722,6 @@ void Console::Run() StopRecordingHdPack(); - MovieManager::Stop(); _soundMixer->StopRecording(); _settings->ClearFlags(EmulationFlags::ForceMaxSpeed); diff --git a/Core/Console.h b/Core/Console.h index 64514f26..2323da46 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -6,7 +6,6 @@ #include "VirtualFile.h" class BaseMapper; -class HistoryViewer; class APU; class CPU; class PPU; @@ -47,8 +46,6 @@ private: SimpleLock _stopLock; atomic _pauseCounter; - shared_ptr _historyViewer; - shared_ptr _cpu; shared_ptr _ppu; shared_ptr _apu; @@ -127,7 +124,6 @@ public: ControlManager* GetControlManager(); MemoryManager* GetMemoryManager(); CheatManager* GetCheatManager(); - HistoryViewer* GetHistoryViewer(); bool LoadMatchingRom(string romName, HashInfo hashInfo); string FindMatchingRom(string romName, HashInfo hashInfo); diff --git a/Core/ControlManager.cpp b/Core/ControlManager.cpp index 9ca5ab07..077e72cd 100644 --- a/Core/ControlManager.cpp +++ b/Core/ControlManager.cpp @@ -3,7 +3,6 @@ #include "BaseMapper.h" #include "EmulationSettings.h" #include "Console.h" -#include "GameServerConnection.h" #include "MemoryManager.h" #include "IKeyManager.h" #include "IInputProvider.h" @@ -290,12 +289,6 @@ void ControlManager::UpdateInputState() //log += "|" + device->GetTextState(); } - if(!_console->GetSettings()->IsRunAheadFrame()) { - for(IInputRecorder* recorder : _inputRecorders) { - recorder->RecordInput(_controlDevices); - } - } - //Used by VS System games RemapControllerButtons(); diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index fbefddf8..578b79ac 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -3,7 +3,6 @@ #include #include "stdafx.h" #include "MessageManager.h" -#include "GameClient.h" #include "KeyManager.h" #include "../Utilities/SimpleLock.h" diff --git a/Core/FDS.cpp b/Core/FDS.cpp index 1855bdc6..b5c17a83 100644 --- a/Core/FDS.cpp +++ b/Core/FDS.cpp @@ -6,7 +6,6 @@ #include "FdsAudio.h" #include "MemoryManager.h" #include "BatteryManager.h" -#include "MovieManager.h" void FDS::InitMapper() { @@ -553,5 +552,5 @@ bool FDS::IsDiskInserted() bool FDS::IsAutoInsertDiskEnabled() { - return !_disableAutoInsertDisk && _settings->CheckFlag(EmulationFlags::FdsAutoInsertDisk) && !MovieManager::Playing() && !MovieManager::Recording(); -} \ No newline at end of file + return !_disableAutoInsertDisk && _settings->CheckFlag(EmulationFlags::FdsAutoInsertDisk); +} diff --git a/Core/FceuxMovie.cpp b/Core/FceuxMovie.cpp deleted file mode 100644 index adfc7103..00000000 --- a/Core/FceuxMovie.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "stdafx.h" -#include -#include "../Utilities/StringUtilities.h" -#include "../Utilities/HexUtilities.h" -#include "../Utilities/Base64.h" -#include "ControlManager.h" -#include "FceuxMovie.h" -#include "Console.h" -#include "NotificationManager.h" - -bool FceuxMovie::InitializeData(stringstream &filestream) -{ - bool result = false; - - _dataByFrame[0].push_back(""); - _dataByFrame[1].push_back(""); - _dataByFrame[2].push_back(""); - _dataByFrame[3].push_back(""); - - _console->GetControlManager()->SetPollCounter(0); - - while(!filestream.eof()) { - string line; - std::getline(filestream, line); - if(line.compare(0, 19, "romChecksum base64:", 19) == 0) { - vector md5array = Base64::Decode(line.substr(19, line.size() - 20)); - HashInfo hashInfo; - hashInfo.PrgChrMd5 = HexUtilities::ToHex(md5array); - _console->GetSettings()->SetRamPowerOnState(RamPowerOnState::AllZeros); - if(_console->LoadMatchingRom("", hashInfo)) { - result = true; - } else { - return false; - } - } else if(line.size() > 0 && line[0] == '|') { - vector lineData = StringUtilities::Split(line.substr(1), '|'); - - if(lineData.size() == 0) { - continue; - } - - //Read power/reset/FDS/VS/etc. commands - uint32_t systemAction = 0; - try { - systemAction = (uint32_t)std::atol(lineData[0].c_str()); - } catch(std::exception&) { - } - _systemActionByFrame.push_back(systemAction); - - //Only supports regular controllers (up to 4 of them) - for(size_t i = 1; i < lineData.size() && i < 5; i++) { - if(lineData[i].size() >= 8) { - string data = lineData[i].substr(3, 1) + lineData[i].substr(2, 1) + lineData[i].substr(1, 1) + lineData[i].substr(0, 1); - _dataByFrame[i - 1].push_back(data + lineData[i].substr(4, 4)); - } else { - _dataByFrame[i - 1].push_back(""); - } - } - } - } - return result; -} - -bool FceuxMovie::Play(VirtualFile &file) -{ - _console->Pause(); - - std::stringstream ss; - file.ReadFile(ss); - _console->GetNotificationManager()->RegisterNotificationListener(shared_from_this()); - _console->GetBatteryManager()->SetBatteryProvider(shared_from_this()); - if(InitializeData(ss)) { - _console->Reset(false); - _isPlaying = true; - } - - _console->Resume(); - return _isPlaying; -} \ No newline at end of file diff --git a/Core/FceuxMovie.h b/Core/FceuxMovie.h deleted file mode 100644 index 244505ec..00000000 --- a/Core/FceuxMovie.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "stdafx.h" -#include "../Utilities/ZipReader.h" -#include "MovieManager.h" -#include "BizhawkMovie.h" - -class FceuxMovie : public BizhawkMovie -{ -private: - bool InitializeData(stringstream &filestream); - -public: - using BizhawkMovie::BizhawkMovie; - - bool Play(VirtualFile &file) override; -}; \ No newline at end of file diff --git a/Core/GameClient.cpp b/Core/GameClient.cpp deleted file mode 100644 index 61a5f243..00000000 --- a/Core/GameClient.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "stdafx.h" -#include -using std::thread; - -#include "MessageManager.h" -#include "GameClient.h" -#include "Console.h" -#include "NotificationManager.h" -#include "../Utilities/Socket.h" -#include "ClientConnectionData.h" -#include "GameClientConnection.h" - -shared_ptr GameClient::_instance; - -GameClient::GameClient(shared_ptr console) -{ - _console = console; - _stop = false; -} - -GameClient::~GameClient() -{ - _stop = true; - if(_clientThread) { - _clientThread->join(); - } -} - -bool GameClient::Connected() -{ - shared_ptr instance = _instance; - return instance ? instance->_connected : false; -} - -void GameClient::Connect(shared_ptr console, ClientConnectionData &connectionData) -{ - _instance.reset(new GameClient(console)); - console->GetNotificationManager()->RegisterNotificationListener(_instance); - - shared_ptr instance = _instance; - if(instance) { - instance->PrivateConnect(connectionData); - instance->_clientThread.reset(new thread(&GameClient::Exec, instance.get())); - } -} - -void GameClient::Disconnect() -{ - _instance.reset(); -} - -shared_ptr GameClient::GetConnection() -{ - shared_ptr instance = _instance; - return instance ? instance->_connection : nullptr; -} - -void GameClient::PrivateConnect(ClientConnectionData &connectionData) -{ - _stop = false; - shared_ptr socket(new Socket()); - if(socket->Connect(connectionData.Host.c_str(), connectionData.Port)) { - _connection.reset(new GameClientConnection(_console, socket, connectionData)); - _console->GetNotificationManager()->RegisterNotificationListener(_connection); - _connected = true; - } else { - MessageManager::DisplayMessage("NetPlay", "CouldNotConnect"); - _connected = false; - } -} - -void GameClient::Exec() -{ - if(_connected) { - while(!_stop) { - if(!_connection->ConnectionError()) { - _connection->ProcessMessages(); - _connection->SendInput(); - } else { - _connected = false; - _connection->Shutdown(); - _connection.reset(); - break; - } - std::this_thread::sleep_for(std::chrono::duration(1)); - } - } -} - -void GameClient::ProcessNotification(ConsoleNotificationType type, void* parameter) -{ -} - -void GameClient::SelectController(uint8_t port) -{ - shared_ptr connection = GetConnection(); - if(connection) { - connection->SelectController(port); - } -} - -uint8_t GameClient::GetAvailableControllers() -{ - shared_ptr connection = GetConnection(); - return connection ? connection->GetAvailableControllers() : 0; -} - -uint8_t GameClient::GetControllerPort() -{ - shared_ptr connection = GetConnection(); - return connection ? connection->GetControllerPort() : GameConnection::SpectatorPort; -} diff --git a/Core/GameClient.h b/Core/GameClient.h deleted file mode 100644 index 3774af19..00000000 --- a/Core/GameClient.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "INotificationListener.h" - -using std::thread; -class Socket; -class GameClientConnection; -class ClientConnectionData; -class Console; - -class GameClient : public INotificationListener -{ -private: - static shared_ptr _instance; - - shared_ptr _console; - unique_ptr _clientThread; - atomic _stop; - - shared_ptr _connection; - bool _connected = false; - - static shared_ptr GetConnection(); - - void PrivateConnect(ClientConnectionData &connectionData); - void Exec(); - -public: - GameClient(shared_ptr console); - virtual ~GameClient(); - - static bool Connected(); - static void Connect(shared_ptr console, ClientConnectionData &connectionData); - static void Disconnect(); - - static void SelectController(uint8_t port); - static uint8_t GetControllerPort(); - static uint8_t GetAvailableControllers(); - - void ProcessNotification(ConsoleNotificationType type, void* parameter) override; -}; \ No newline at end of file diff --git a/Core/GameClientConnection.cpp b/Core/GameClientConnection.cpp deleted file mode 100644 index 7db73e76..00000000 --- a/Core/GameClientConnection.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#include "stdafx.h" -#include "GameClientConnection.h" -#include "HandShakeMessage.h" -#include "InputDataMessage.h" -#include "MovieDataMessage.h" -#include "GameInformationMessage.h" -#include "SaveStateMessage.h" -#include "Console.h" -#include "EmulationSettings.h" -#include "ControlManager.h" -#include "ClientConnectionData.h" -#include "StandardController.h" -#include "Zapper.h" -#include "ArkanoidController.h" -#include "BandaiHyperShot.h" -#include "SelectControllerMessage.h" -#include "PlayerListMessage.h" -#include "ForceDisconnectMessage.h" -#include "ServerInformationMessage.h" -#include "NotificationManager.h" - -GameClientConnection::GameClientConnection(shared_ptr console, shared_ptr socket, ClientConnectionData &connectionData) : GameConnection(console, socket) -{ - _connectionData = connectionData; - _shutdown = false; - _enableControllers = false; - _minimumQueueSize = 3; - - MessageManager::DisplayMessage("NetPlay", "ConnectedToServer"); -} - -GameClientConnection::~GameClientConnection() -{ - Shutdown(); -} - -void GameClientConnection::Shutdown() -{ - if(!_shutdown) { - _shutdown = true; - DisableControllers(); - - ControlManager* controlManager = _console->GetControlManager(); - if(controlManager) { - controlManager->UnregisterInputProvider(this); - } - _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::DisconnectedFromServer); - MessageManager::DisplayMessage("NetPlay", "ConnectionLost"); - _console->GetSettings()->ClearFlags(EmulationFlags::ForceMaxSpeed); - } -} - -void GameClientConnection::SendHandshake() -{ - HandShakeMessage message(_connectionData.PlayerName, HandShakeMessage::GetPasswordHash(_connectionData.Password, _serverSalt), _connectionData.Spectator); - SendNetMessage(message); -} - -void GameClientConnection::SendControllerSelection(uint8_t port) -{ - SelectControllerMessage message(port); - SendNetMessage(message); -} - -void GameClientConnection::ClearInputData() -{ - LockHandler lock = _writeLock.AcquireSafe(); - for(int i = 0; i < BaseControlDevice::PortCount; i++) { - _inputSize[i] = 0; - _inputData[i].clear(); - } -} - -void GameClientConnection::ProcessMessage(NetMessage* message) -{ - GameInformationMessage* gameInfo; - - switch(message->GetType()) { - case MessageType::ServerInformation: - _serverSalt = ((ServerInformationMessage*)message)->GetHashSalt(); - SendHandshake(); - break; - - case MessageType::SaveState: - if(_gameLoaded) { - DisableControllers(); - _console->Pause(); - ClearInputData(); - ((SaveStateMessage*)message)->LoadState(_console); - _enableControllers = true; - InitControlDevice(); - _console->Resume(); - } - break; - - case MessageType::MovieData: - if(_gameLoaded) { - PushControllerState(((MovieDataMessage*)message)->GetPortNumber(), ((MovieDataMessage*)message)->GetInputState()); - } - break; - - case MessageType::ForceDisconnect: - MessageManager::DisplayMessage("NetPlay", ((ForceDisconnectMessage*)message)->GetMessage()); - break; - - case MessageType::PlayerList: - _playerList = ((PlayerListMessage*)message)->GetPlayerList(); - break; - - case MessageType::GameInformation: - DisableControllers(); - _console->Pause(); - gameInfo = (GameInformationMessage*)message; - if(gameInfo->GetPort() != _controllerPort) { - _controllerPort = gameInfo->GetPort(); - - if(_controllerPort == GameConnection::SpectatorPort) { - MessageManager::DisplayMessage("NetPlay", "ConnectedAsSpectator"); - } else { - MessageManager::DisplayMessage("NetPlay", "ConnectedAsPlayer", std::to_string(_controllerPort + 1)); - } - } - - ClearInputData(); - - _gameLoaded = AttemptLoadGame(gameInfo->GetRomFilename(), gameInfo->GetCrc32Hash()); - if(gameInfo->IsPaused()) { - _console->GetSettings()->SetFlags(EmulationFlags::Paused); - } else { - _console->GetSettings()->ClearFlags(EmulationFlags::Paused); - } - _console->Resume(); - break; - default: - break; - } -} - -bool GameClientConnection::AttemptLoadGame(string filename, uint32_t crc32Hash) -{ - if(filename.size() > 0) { - HashInfo hashInfo; - hashInfo.Crc32 = crc32Hash; - if(_console->LoadMatchingRom(filename, hashInfo)) { - return true; - } else { - MessageManager::DisplayMessage("NetPlay", "CouldNotFindRom"); - return false; - } - } - return false; -} - -void GameClientConnection::PushControllerState(uint8_t port, ControlDeviceState state) -{ - LockHandler lock = _writeLock.AcquireSafe(); - _inputData[port].push_back(state); - _inputSize[port]++; - - if(_inputData[port].size() >= _minimumQueueSize) { - _waitForInput[port].Signal(); - } -} - -void GameClientConnection::DisableControllers() -{ - //Used to prevent deadlocks when client is trying to fill its buffer while the host changes the current game/settings/etc. (i.e situations where we need to call Console::Pause()) - ClearInputData(); - _enableControllers = false; - for(int i = 0; i < BaseControlDevice::PortCount; i++) { - _waitForInput[i].Signal(); - } -} - -bool GameClientConnection::SetInput(BaseControlDevice *device) -{ - if(_enableControllers) { - uint8_t port = device->GetPort(); - while(_inputSize[port] == 0) { - _waitForInput[port].Wait(); - - if(port == 0 && _minimumQueueSize < 10) { - //Increase buffer size - reduces freezes at the cost of additional lag - _minimumQueueSize++; - } - - if(_shutdown || !_enableControllers) { - return true; - } - } - - LockHandler lock = _writeLock.AcquireSafe(); - ControlDeviceState state = _inputData[port].front(); - _inputData[port].pop_front(); - _inputSize[port]--; - - if(_inputData[port].size() > _minimumQueueSize) { - //Too much data, catch up - _console->GetSettings()->SetFlags(EmulationFlags::ForceMaxSpeed); - } else { - _console->GetSettings()->ClearFlags(EmulationFlags::ForceMaxSpeed); - _console->GetSettings()->SetEmulationSpeed(100); - } - - device->SetRawState(state); - } - return true; -} - -void GameClientConnection::InitControlDevice() -{ - if(_controllerPort == BaseControlDevice::ExpDevicePort) { - _newControlDevice = ControlManager::CreateExpansionDevice(_console->GetSettings()->GetExpansionDevice(), _console); - } else { - //Pretend we are using port 0 (to use player 1's keybindings during netplay) - _newControlDevice = ControlManager::CreateControllerDevice(_console->GetSettings()->GetControllerType(_controllerPort), 0, _console); - } -} - -void GameClientConnection::ProcessNotification(ConsoleNotificationType type, void* parameter) -{ - if(type == ConsoleNotificationType::ConfigChanged) { - InitControlDevice(); - } else if(type == ConsoleNotificationType::GameLoaded) { - _console->GetControlManager()->RegisterInputProvider(this); - } -} - -void GameClientConnection::SendInput() -{ - if(_gameLoaded) { - if(_newControlDevice) { - _controlDevice = _newControlDevice; - _newControlDevice.reset(); - } - - ControlDeviceState inputState; - if(_controlDevice) { - _controlDevice->SetStateFromInput(); - inputState = _controlDevice->GetRawState(); - } - - if(_lastInputSent != inputState) { - InputDataMessage message(inputState); - SendNetMessage(message); - _lastInputSent = inputState; - } - } -} - -void GameClientConnection::SelectController(uint8_t port) -{ - SendControllerSelection(port); -} - -uint8_t GameClientConnection::GetAvailableControllers() -{ - uint8_t availablePorts = (1 << BaseControlDevice::PortCount) - 1; - for(PlayerInfo &playerInfo : _playerList) { - if(playerInfo.ControllerPort < BaseControlDevice::PortCount) { - availablePorts &= ~(1 << playerInfo.ControllerPort); - } - } - return availablePorts; -} - -uint8_t GameClientConnection::GetControllerPort() -{ - return _controllerPort; -} \ No newline at end of file diff --git a/Core/GameClientConnection.h b/Core/GameClientConnection.h deleted file mode 100644 index 25406ad6..00000000 --- a/Core/GameClientConnection.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "GameConnection.h" -#include "../Utilities/AutoResetEvent.h" -#include "../Utilities/SimpleLock.h" -#include "BaseControlDevice.h" -#include "IInputProvider.h" -#include "ControlDeviceState.h" -#include "ClientConnectionData.h" - -class Console; - -class GameClientConnection : public GameConnection, public INotificationListener, public IInputProvider -{ -private: - std::deque _inputData[BaseControlDevice::PortCount]; - atomic _inputSize[BaseControlDevice::PortCount]; - AutoResetEvent _waitForInput[BaseControlDevice::PortCount]; - SimpleLock _writeLock; - atomic _shutdown; - atomic _enableControllers; - atomic _minimumQueueSize; - - vector _playerList; - - shared_ptr _controlDevice; - shared_ptr _newControlDevice; - ControlDeviceState _lastInputSent; - bool _gameLoaded = false; - uint8_t _controllerPort = GameConnection::SpectatorPort; - ClientConnectionData _connectionData; - string _serverSalt; - -private: - void SendHandshake(); - void SendControllerSelection(uint8_t port); - void ClearInputData(); - void PushControllerState(uint8_t port, ControlDeviceState state); - void DisableControllers(); - bool AttemptLoadGame(string filename, uint32_t crc32Hash); - -protected: - void ProcessMessage(NetMessage* message) override; - -public: - GameClientConnection(shared_ptr console, shared_ptr socket, ClientConnectionData &connectionData); - virtual ~GameClientConnection(); - - void Shutdown(); - - void ProcessNotification(ConsoleNotificationType type, void* parameter) override; - - bool SetInput(BaseControlDevice *device) override; - void InitControlDevice(); - void SendInput(); - - void SelectController(uint8_t port); - uint8_t GetAvailableControllers(); - uint8_t GetControllerPort(); -}; \ No newline at end of file diff --git a/Core/GameConnection.cpp b/Core/GameConnection.cpp deleted file mode 100644 index 094ec03f..00000000 --- a/Core/GameConnection.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "stdafx.h" -#include "GameConnection.h" -#include "HandShakeMessage.h" -#include "InputDataMessage.h" -#include "MovieDataMessage.h" -#include "GameInformationMessage.h" -#include "SaveStateMessage.h" -#include "PlayerListMessage.h" -#include "SelectControllerMessage.h" -#include "ClientConnectionData.h" -#include "ForceDisconnectMessage.h" -#include "ServerInformationMessage.h" - -GameConnection::GameConnection(shared_ptr console, shared_ptr socket) -{ - _console = console; - _socket = socket; -} - -void GameConnection::ReadSocket() -{ - auto lock = _socketLock.AcquireSafe(); - int bytesReceived = _socket->Recv((char*)_readBuffer + _readPosition, 0x40000 - _readPosition, 0); - if(bytesReceived > 0) { - _readPosition += bytesReceived; - } -} - -bool GameConnection::ExtractMessage(void *buffer, uint32_t &messageLength) -{ - messageLength = _readBuffer[0] | (_readBuffer[1] << 8) | (_readBuffer[2] << 16) | (_readBuffer[3] << 24); - - if(messageLength > 1000000) { - MessageManager::Log("[Netplay] Invalid data received, closing connection."); - Disconnect(); - return false; - } - - int packetLength = messageLength + sizeof(messageLength); - - if(_readPosition >= packetLength) { - memcpy(buffer, _readBuffer+sizeof(messageLength), messageLength); - memmove(_readBuffer, _readBuffer + packetLength, _readPosition - packetLength); - _readPosition -= packetLength; - return true; - } - return false; -} - -NetMessage* GameConnection::ReadMessage() -{ - ReadSocket(); - - if(_readPosition > 4) { - uint32_t messageLength; - if(ExtractMessage(_messageBuffer, messageLength)) { - switch((MessageType)_messageBuffer[0]) { - case MessageType::HandShake: return new HandShakeMessage(_messageBuffer, messageLength); - case MessageType::SaveState: return new SaveStateMessage(_messageBuffer, messageLength); - case MessageType::InputData: return new InputDataMessage(_messageBuffer, messageLength); - case MessageType::MovieData: return new MovieDataMessage(_messageBuffer, messageLength); - case MessageType::GameInformation: return new GameInformationMessage(_messageBuffer, messageLength); - case MessageType::PlayerList: return new PlayerListMessage(_messageBuffer, messageLength); - case MessageType::SelectController: return new SelectControllerMessage(_messageBuffer, messageLength); - case MessageType::ForceDisconnect: return new ForceDisconnectMessage(_messageBuffer, messageLength); - case MessageType::ServerInformation: return new ServerInformationMessage(_messageBuffer, messageLength); - } - } - } - return nullptr; -} - -void GameConnection::SendNetMessage(NetMessage &message) -{ - auto lock = _socketLock.AcquireSafe(); - message.Send(*_socket.get()); -} - -void GameConnection::Disconnect() -{ - auto lock = _socketLock.AcquireSafe(); - _socket->Close(); -} - -bool GameConnection::ConnectionError() -{ - return _socket->ConnectionError(); -} - -void GameConnection::ProcessMessages() -{ - NetMessage* message; - while((message = ReadMessage()) != nullptr) { - //Loop until all messages have been processed - message->Initialize(); - ProcessMessage(message); - delete message; - } -} \ No newline at end of file diff --git a/Core/GameConnection.h b/Core/GameConnection.h deleted file mode 100644 index 66450c8a..00000000 --- a/Core/GameConnection.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include "stdafx.h" -#include "../Utilities/SimpleLock.h" - -class Socket; -class NetMessage; -class Console; - -struct PlayerInfo -{ - string Name; - uint8_t ControllerPort; - bool IsHost; -}; - -class GameConnection -{ -protected: - shared_ptr _socket; - shared_ptr _console; - - uint8_t _readBuffer[0x40000] = {}; - uint8_t _messageBuffer[0x40000] = {}; - int _readPosition = 0; - SimpleLock _socketLock; - -private: - void ReadSocket(); - - bool ExtractMessage(void *buffer, uint32_t &messageLength); - NetMessage* ReadMessage(); - - virtual void ProcessMessage(NetMessage* message) = 0; - -protected: - void Disconnect(); - -public: - static constexpr uint8_t SpectatorPort = 0xFF; - GameConnection(shared_ptr console, shared_ptr socket); - - bool ConnectionError(); - void ProcessMessages(); - void SendNetMessage(NetMessage &message); -}; \ No newline at end of file diff --git a/Core/GameServer.cpp b/Core/GameServer.cpp deleted file mode 100644 index 66948144..00000000 --- a/Core/GameServer.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include "stdafx.h" -#include -using std::thread; - -#include "MessageManager.h" -#include "GameServer.h" -#include "Console.h" -#include "ControlManager.h" -#include "../Utilities/Socket.h" -#include "PlayerListMessage.h" -#include "NotificationManager.h" - -shared_ptr GameServer::Instance; - -GameServer::GameServer(shared_ptr console, uint16_t listenPort, string password, string hostPlayerName) -{ - _console = console; - _stop = false; - _port = listenPort; - _password = password; - _hostPlayerName = hostPlayerName; - _hostControllerPort = 0; - - //If a game is already running, register ourselves as an input recorder/provider right away - RegisterServerInput(); -} - -GameServer::~GameServer() -{ - _stop = true; - _serverThread->join(); - - Stop(); - - ControlManager* controlManager = _console->GetControlManager(); - if(controlManager) { - controlManager->UnregisterInputRecorder(this); - controlManager->UnregisterInputProvider(this); - } -} - -void GameServer::RegisterServerInput() -{ - ControlManager* controlManager = _console->GetControlManager(); - if(controlManager) { - controlManager->RegisterInputRecorder(this); - controlManager->RegisterInputProvider(this); - } -} - -void GameServer::AcceptConnections() -{ - while(true) { - shared_ptr socket = _listener->Accept(); - if(!socket->ConnectionError()) { - auto connection = shared_ptr(new GameServerConnection(_console, socket, _password)); - _console->GetNotificationManager()->RegisterNotificationListener(connection); - _openConnections.push_back(connection); - } else { - break; - } - } - _listener->Listen(10); -} - -void GameServer::UpdateConnections() -{ - vector> connectionsToRemove; - for(shared_ptr connection : _openConnections) { - if(connection->ConnectionError()) { - connectionsToRemove.push_back(connection); - } else { - connection->ProcessMessages(); - } - } - - for(shared_ptr gameConnection : connectionsToRemove) { - _openConnections.remove(gameConnection); - } -} - -list> GameServer::GetConnectionList() -{ - if(GameServer::Started()) { - return Instance->_openConnections; - } else { - return list>(); - } -} - -bool GameServer::SetInput(BaseControlDevice *device) -{ - uint8_t port = device->GetPort(); - - GameServerConnection* connection = GameServerConnection::GetNetPlayDevice(port); - if(connection) { - //Device is controlled by a client - device->SetRawState(connection->GetState()); - return true; - } - - //Host is controlling this device - return false; -} - -void GameServer::RecordInput(vector> devices) -{ - for(shared_ptr &device : devices) { - for(shared_ptr connection : _openConnections) { - if(!connection->ConnectionError()) { - //Send movie stream - connection->SendMovieData(device->GetPort(), device->GetRawState()); - } - } - } -} - -void GameServer::ProcessNotification(ConsoleNotificationType type, void * parameter) -{ - if(type == ConsoleNotificationType::GameLoaded) { - //Register the server as an input provider/recorder - RegisterServerInput(); - } -} - -void GameServer::Exec() -{ - _listener.reset(new Socket()); - _listener->Bind(_port); - _listener->Listen(10); - _stop = false; - _initialized = true; - MessageManager::DisplayMessage("NetPlay" , "ServerStarted", std::to_string(_port)); - - while(!_stop) { - AcceptConnections(); - UpdateConnections(); - - std::this_thread::sleep_for(std::chrono::duration(1)); - } -} - -void GameServer::Stop() -{ - _initialized = false; - _listener.reset(); - MessageManager::DisplayMessage("NetPlay", "ServerStopped"); -} - -void GameServer::StartServer(shared_ptr console, uint16_t port, string password, string hostPlayerName) -{ - Instance.reset(new GameServer(console, port, password, hostPlayerName)); - console->GetNotificationManager()->RegisterNotificationListener(Instance); - Instance->_serverThread.reset(new thread(&GameServer::Exec, Instance.get())); -} - -void GameServer::StopServer() -{ - if(Instance) { - Instance.reset(); - } -} - -bool GameServer::Started() -{ - if(Instance) { - return Instance->_initialized; - } else { - return false; - } -} - -string GameServer::GetHostPlayerName() -{ - if(GameServer::Started()) { - return Instance->_hostPlayerName; - } - return ""; -} - -uint8_t GameServer::GetHostControllerPort() -{ - if(GameServer::Started()) { - return Instance->_hostControllerPort; - } - return GameConnection::SpectatorPort; -} - -void GameServer::SetHostControllerPort(uint8_t port) -{ - if(GameServer::Started()) { - Instance->_console->Pause(); - if(port == GameConnection::SpectatorPort || GetAvailableControllers() & (1 << port)) { - //Port is available - Instance->_hostControllerPort = port; - SendPlayerList(); - } - Instance->_console->Resume(); - } -} - -uint8_t GameServer::GetAvailableControllers() -{ - uint8_t availablePorts = (1 << BaseControlDevice::PortCount) - 1; - for(PlayerInfo &playerInfo : GetPlayerList()) { - if(playerInfo.ControllerPort < BaseControlDevice::PortCount) { - availablePorts &= ~(1 << playerInfo.ControllerPort); - } - } - return availablePorts; -} - -vector GameServer::GetPlayerList() -{ - vector playerList; - - PlayerInfo playerInfo; - playerInfo.Name = GetHostPlayerName(); - playerInfo.ControllerPort = GetHostControllerPort(); - playerInfo.IsHost = true; - playerList.push_back(playerInfo); - - for(shared_ptr &connection : GetConnectionList()) { - playerInfo.Name = connection->GetPlayerName(); - playerInfo.ControllerPort = connection->GetControllerPort(); - playerInfo.IsHost = false; - playerList.push_back(playerInfo); - } - - return playerList; -} - -void GameServer::SendPlayerList() -{ - vector playerList = GetPlayerList(); - - for(shared_ptr &connection : GetConnectionList()) { - //Send player list update to all connections - PlayerListMessage message(playerList); - connection->SendNetMessage(message); - } -} \ No newline at end of file diff --git a/Core/GameServer.h b/Core/GameServer.h deleted file mode 100644 index 475519da..00000000 --- a/Core/GameServer.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "GameServerConnection.h" -#include "INotificationListener.h" -#include "IInputProvider.h" -#include "IInputRecorder.h" - -using std::thread; -class Console; - -class GameServer : public IInputRecorder, public IInputProvider, public INotificationListener -{ -private: - static shared_ptr Instance; - shared_ptr _console; - unique_ptr _serverThread; - atomic _stop; - unique_ptr _listener; - uint16_t _port; - string _password; - list> _openConnections; - bool _initialized = false; - - string _hostPlayerName; - uint8_t _hostControllerPort; - - void AcceptConnections(); - void UpdateConnections(); - - void Exec(); - void Stop(); - -public: - GameServer(shared_ptr console, uint16_t port, string password, string hostPlayerName); - virtual ~GameServer(); - - void RegisterServerInput(); - - static void StartServer(shared_ptr console, uint16_t port, string password, string hostPlayerName); - static void StopServer(); - static bool Started(); - - static string GetHostPlayerName(); - static uint8_t GetHostControllerPort(); - static void SetHostControllerPort(uint8_t port); - static uint8_t GetAvailableControllers(); - static vector GetPlayerList(); - static void SendPlayerList(); - - static list> GetConnectionList(); - - bool SetInput(BaseControlDevice *device) override; - void RecordInput(vector> devices) override; - - // Inherited via INotificationListener - virtual void ProcessNotification(ConsoleNotificationType type, void * parameter) override; -}; \ No newline at end of file diff --git a/Core/GameServerConnection.cpp b/Core/GameServerConnection.cpp deleted file mode 100644 index da9525db..00000000 --- a/Core/GameServerConnection.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#include "stdafx.h" -#include -#include "MessageManager.h" -#include "GameServerConnection.h" -#include "HandShakeMessage.h" -#include "InputDataMessage.h" -#include "MovieDataMessage.h" -#include "GameInformationMessage.h" -#include "SaveStateMessage.h" -#include "Console.h" -#include "ControlManager.h" -#include "ClientConnectionData.h" -#include "EmulationSettings.h" -#include "StandardController.h" -#include "SelectControllerMessage.h" -#include "PlayerListMessage.h" -#include "GameServer.h" -#include "ForceDisconnectMessage.h" -#include "BaseControlDevice.h" -#include "ServerInformationMessage.h" - -GameServerConnection* GameServerConnection::_netPlayDevices[BaseControlDevice::PortCount] = { }; - -GameServerConnection::GameServerConnection(shared_ptr console, shared_ptr socket, string serverPassword) : GameConnection(console, socket) -{ - //Server-side connection - _serverPassword = serverPassword; - _controllerPort = GameConnection::SpectatorPort; - SendServerInformation(); -} - -GameServerConnection::~GameServerConnection() -{ - if(!_playerName.empty()) { - MessageManager::DisplayMessage("NetPlay", _playerName + " (Player " + std::to_string(_controllerPort + 1) + ") disconnected."); - } - - UnregisterNetPlayDevice(this); -} - -void GameServerConnection::SendServerInformation() -{ - std::random_device rd; - std::mt19937 engine(rd()); - std::uniform_int_distribution<> dist((int)' ', (int)'~'); - string hash(50, ' '); - for(int i = 0; i < 50; i++) { - int random = dist(engine); - hash[i] = (char)random; - } - - _connectionHash = hash; - - ServerInformationMessage message(hash); - SendNetMessage(message); -} - -void GameServerConnection::SendGameInformation() -{ - _console->Pause(); - RomInfo romInfo = _console->GetRomInfo(); - GameInformationMessage gameInfo(romInfo.RomName, romInfo.Hash.Crc32, _controllerPort, _console->GetSettings()->CheckFlag(EmulationFlags::Paused)); - SendNetMessage(gameInfo); - SaveStateMessage saveState(_console); - SendNetMessage(saveState); - _console->Resume(); -} - -void GameServerConnection::SendMovieData(uint8_t port, ControlDeviceState state) -{ - if(_handshakeCompleted) { - MovieDataMessage message(state, port); - SendNetMessage(message); - } -} - -void GameServerConnection::SendForceDisconnectMessage(string disconnectMessage) -{ - ForceDisconnectMessage message(disconnectMessage); - SendNetMessage(message); - Disconnect(); -} - -void GameServerConnection::PushState(ControlDeviceState state) -{ - if(_inputData.size() == 0 || state != _inputData.back()) { - _inputData.clear(); - _inputData.push_back(state); - } -} - -ControlDeviceState GameServerConnection::GetState() -{ - size_t inputBufferSize = _inputData.size(); - ControlDeviceState stateData; - if(inputBufferSize > 0) { - stateData = _inputData.front(); - if(inputBufferSize > 1) { - //Always keep the last one the client sent, it will be used until a new one is received - _inputData.pop_front(); - } - } - return stateData; -} - -void GameServerConnection::ProcessHandshakeResponse(HandShakeMessage* message) -{ - //Send the game's current state to the client and register the controller - if(message->IsValid()) { - if(message->CheckPassword(_serverPassword, _connectionHash)) { - _console->Pause(); - - _controllerPort = message->IsSpectator() ? GameConnection::SpectatorPort : GetFirstFreeControllerPort(); - _playerName = message->GetPlayerName(); - - string playerPortMessage = _controllerPort == GameConnection::SpectatorPort ? "Spectator" : "Player " + std::to_string(_controllerPort + 1); - - MessageManager::DisplayMessage("NetPlay", _playerName + " (" + playerPortMessage + ") connected."); - - if(_console->GetRomInfo().RomName.size() > 0) { - SendGameInformation(); - } - - _handshakeCompleted = true; - RegisterNetPlayDevice(this, _controllerPort); - GameServer::SendPlayerList(); - _console->Resume(); - } else { - SendForceDisconnectMessage("The password you provided did not match - you have been disconnected."); - } - } else { - SendForceDisconnectMessage("Server is using a different version of Mesen (" + EmulationSettings::GetMesenVersionString() + ") - you have been disconnected."); - MessageManager::DisplayMessage("NetPlay", + "NetplayVersionMismatch", message->GetPlayerName()); - } -} - -void GameServerConnection::ProcessMessage(NetMessage* message) -{ - switch(message->GetType()) { - case MessageType::HandShake: - ProcessHandshakeResponse((HandShakeMessage*)message); - break; - - case MessageType::InputData: - if(!_handshakeCompleted) { - SendForceDisconnectMessage("Handshake has not been completed - invalid packet"); - return; - } - PushState(((InputDataMessage*)message)->GetInputState()); - break; - - case MessageType::SelectController: - if(!_handshakeCompleted) { - SendForceDisconnectMessage("Handshake has not been completed - invalid packet"); - return; - } - SelectControllerPort(((SelectControllerMessage*)message)->GetPortNumber()); - break; - - default: - break; - } -} - -void GameServerConnection::SelectControllerPort(uint8_t port) -{ - _console->Pause(); - if(port == GameConnection::SpectatorPort) { - //Client wants to be a spectator, make sure we are not using any controller - UnregisterNetPlayDevice(this); - _controllerPort = port; - } else { - GameServerConnection* netPlayDevice = GetNetPlayDevice(port); - if(netPlayDevice == this) { - //Nothing to do, we're already this player - } else if(netPlayDevice == nullptr) { - //This port is free, we can switch - UnregisterNetPlayDevice(this); - RegisterNetPlayDevice(this, port); - _controllerPort = port; - } else { - //Another player is using this port, we can't use it - } - } - SendGameInformation(); - GameServer::SendPlayerList(); - _console->Resume(); -} - -void GameServerConnection::ProcessNotification(ConsoleNotificationType type, void* parameter) -{ - switch(type) { - case ConsoleNotificationType::GamePaused: - case ConsoleNotificationType::GameResumed: - case ConsoleNotificationType::GameReset: - case ConsoleNotificationType::StateLoaded: - case ConsoleNotificationType::CheatAdded: - case ConsoleNotificationType::ConfigChanged: - case ConsoleNotificationType::GameInitCompleted: - SendGameInformation(); - break; - default: - break; - } -} - -void GameServerConnection::RegisterNetPlayDevice(GameServerConnection* device, uint8_t port) -{ - GameServerConnection::_netPlayDevices[port] = device; -} - -void GameServerConnection::UnregisterNetPlayDevice(GameServerConnection* device) -{ - if(device != nullptr) { - for(int i = 0; i < BaseControlDevice::PortCount; i++) { - if(GameServerConnection::_netPlayDevices[i] == device) { - GameServerConnection::_netPlayDevices[i] = nullptr; - break; - } - } - } -} - -GameServerConnection* GameServerConnection::GetNetPlayDevice(uint8_t port) -{ - return GameServerConnection::_netPlayDevices[port]; -} - -uint8_t GameServerConnection::GetFirstFreeControllerPort() -{ - uint8_t hostPost = GameServer::GetHostControllerPort(); - for(int i = 0; i < BaseControlDevice::PortCount; i++) { - if(hostPost != i && GameServerConnection::_netPlayDevices[i] == nullptr) { - return i; - } - } - return GameConnection::SpectatorPort; -} - -string GameServerConnection::GetPlayerName() -{ - return _playerName; -} - -uint8_t GameServerConnection::GetControllerPort() -{ - return _controllerPort; -} \ No newline at end of file diff --git a/Core/GameServerConnection.h b/Core/GameServerConnection.h deleted file mode 100644 index 008df010..00000000 --- a/Core/GameServerConnection.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "GameConnection.h" -#include "INotificationListener.h" -#include "BaseControlDevice.h" -#include "ControlDeviceState.h" - -class HandShakeMessage; - -class GameServerConnection : public GameConnection, public INotificationListener -{ -private: - static GameServerConnection* _netPlayDevices[BaseControlDevice::PortCount]; - - list _inputData; - string _playerName; - int _controllerPort; - string _connectionHash; - string _serverPassword; - bool _handshakeCompleted = false; - - void PushState(ControlDeviceState state); - void SendServerInformation(); - void SendGameInformation(); - void SelectControllerPort(uint8_t port); - - void SendForceDisconnectMessage(string disconnectMessage); - - void ProcessHandshakeResponse(HandShakeMessage* message); - - static void RegisterNetPlayDevice(GameServerConnection* connection, uint8_t port); - static void UnregisterNetPlayDevice(GameServerConnection* device); - static uint8_t GetFirstFreeControllerPort(); - -protected: - void ProcessMessage(NetMessage* message) override; - -public: - GameServerConnection(shared_ptr console, shared_ptr socket, string serverPassword); - virtual ~GameServerConnection(); - - ControlDeviceState GetState(); - void SendMovieData(uint8_t port, ControlDeviceState state); - - string GetPlayerName(); - uint8_t GetControllerPort(); - - virtual void ProcessNotification(ConsoleNotificationType type, void* parameter) override; - - static GameServerConnection* GetNetPlayDevice(uint8_t port); -}; diff --git a/Core/HistoryViewer.cpp b/Core/HistoryViewer.cpp deleted file mode 100644 index bb59ceba..00000000 --- a/Core/HistoryViewer.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "stdafx.h" -#include "HistoryViewer.h" -#include "RewindData.h" -#include "Console.h" -#include "BaseControlDevice.h" -#include "SoundMixer.h" -#include "NotificationManager.h" -#include "RomData.h" -#include "MovieRecorder.h" -#include "SaveStateManager.h" - -HistoryViewer::HistoryViewer(shared_ptr console) -{ - _console = console; - _position = 0; - _pollCounter = 0; -} - -HistoryViewer::~HistoryViewer() -{ -} - -void HistoryViewer::SetHistoryData(std::deque &history) -{ - _history = history; - - _console->GetControlManager()->UnregisterInputProvider(this); - _console->GetControlManager()->RegisterInputProvider(this); - - SeekTo(0); -} - -uint32_t HistoryViewer::GetHistoryLength() -{ - //Returns history length in number of frames - return (uint32_t)(_history.size() * HistoryViewer::BufferSize); -} - -void HistoryViewer::GetHistorySegments(uint32_t *segmentBuffer, uint32_t &bufferSize) -{ - uint32_t segmentIndex = 0; - for(size_t i = 0; i < _history.size(); i++) { - if(_history[i].EndOfSegment) { - segmentBuffer[segmentIndex] = (uint32_t)i; - segmentIndex++; - - if(segmentIndex == bufferSize) { - //Reached buffer size, can't return any more values - break; - } - } - } - bufferSize = segmentIndex; -} - -uint32_t HistoryViewer::GetPosition() -{ - return _position; -} - -void HistoryViewer::SeekTo(uint32_t seekPosition) -{ - //Seek to the specified position - if(seekPosition < _history.size()) { - _console->Pause(); - - bool wasPaused = _console->GetSettings()->CheckFlag(EmulationFlags::Paused); - _console->GetSettings()->ClearFlags(EmulationFlags::Paused); - _position = seekPosition; - RewindData rewindData = _history[_position]; - rewindData.LoadState(_console); - - _pollCounter = 0; - - if(wasPaused) { - _console->GetSettings()->SetFlags(EmulationFlags::Paused); - } - - _console->Resume(); - } -} - -bool HistoryViewer::CreateSaveState(string outputFile, uint32_t position) -{ - if(position < _history.size()) { - std::stringstream stateData; - _console->GetSaveStateManager()->GetSaveStateHeader(stateData); - _history[position].GetStateData(stateData); - - ofstream output(outputFile, ios::binary); - if(output) { - output << stateData.rdbuf(); - output.close(); - return true; - } - } - return false; -} - -bool HistoryViewer::SaveMovie(string movieFile, uint32_t startPosition, uint32_t endPosition) -{ - //Take a savestate to be able to restore it after generating the movie file - //(the movie generation uses the console's inputs, which could affect the emulation otherwise) - stringstream state; - _console->Pause(); - _console->SaveState(state); - - //Convert the rewind data to a .mmo file - unique_ptr recorder(new MovieRecorder(_console)); - bool result = recorder->CreateMovie(movieFile, _history, startPosition, endPosition); - - //Resume the state and resume - _console->LoadState(state); - _console->Resume(); - return result; -} - -void HistoryViewer::ResumeGameplay(shared_ptr console, uint32_t resumePosition) -{ - console->Pause(); - if(_console->GetRomInfo().Hash.Sha1 != console->GetRomInfo().Hash.Sha1) { - //Load game on the main window if they aren't the same - console->Initialize(_console->GetRomPath(), _console->GetPatchFile()); - } - if(resumePosition < _history.size()) { - _history[resumePosition].LoadState(console); - } else { - _history[_history.size() - 1].LoadState(console); - } - console->Resume(); -} - -bool HistoryViewer::SetInput(BaseControlDevice *device) -{ - uint8_t port = device->GetPort(); - if(_position < _history.size()) { - std::deque &stateData = _history[_position].InputLogs[port]; - if(_pollCounter < stateData.size()) { - ControlDeviceState state = stateData[_pollCounter]; - device->SetRawState(state); - } - } - if(port == 0 && _pollCounter < 30) { - _pollCounter++; - } - return true; -} - -void HistoryViewer::ProcessEndOfFrame() -{ - if(_pollCounter == HistoryViewer::BufferSize) { - _pollCounter = 0; - _position++; - - if(_position >= _history.size()) { - //Reached the end of history data - _console->GetSettings()->SetFlags(EmulationFlags::Paused); - return; - } - - RewindData rewindData = _history[_position]; - rewindData.LoadState(_console); - } -} diff --git a/Core/HistoryViewer.h b/Core/HistoryViewer.h deleted file mode 100644 index f6d1139e..00000000 --- a/Core/HistoryViewer.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "IInputProvider.h" -#include "RewindData.h" - -class Console; - -class HistoryViewer : public IInputProvider -{ -private: - static constexpr int32_t BufferSize = 30; //Number of frames between each save state - - shared_ptr _console; - std::deque _history; - uint32_t _position; - uint32_t _pollCounter; - -public: - HistoryViewer(shared_ptr console); - virtual ~HistoryViewer(); - - void SetHistoryData(std::deque &history); - - uint32_t GetHistoryLength(); - void GetHistorySegments(uint32_t * segmentBuffer, uint32_t &bufferSize); - uint32_t GetPosition(); - void SeekTo(uint32_t seekPosition); - - bool CreateSaveState(string outputFile, uint32_t position); - bool SaveMovie(string movieFile, uint32_t startPosition, uint32_t endPosition); - - void ResumeGameplay(shared_ptr console, uint32_t resumePosition); - - void ProcessEndOfFrame(); - - // Inherited via IInputProvider - bool SetInput(BaseControlDevice * device) override; -}; \ No newline at end of file diff --git a/Core/IInputRecorder.h b/Core/IInputRecorder.h index 3e7195d8..739f7c9f 100644 --- a/Core/IInputRecorder.h +++ b/Core/IInputRecorder.h @@ -2,9 +2,3 @@ #include "stdafx.h" class BaseControlDevice; - -class IInputRecorder -{ -public: - virtual void RecordInput(vector> devices) = 0; -}; \ No newline at end of file diff --git a/Core/MesenMovie.cpp b/Core/MesenMovie.cpp deleted file mode 100644 index a86d9973..00000000 --- a/Core/MesenMovie.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include "stdafx.h" -#include "../Utilities/ZipReader.h" -#include "../Utilities/StringUtilities.h" -#include "../Utilities/HexUtilities.h" -#include "MesenMovie.h" -#include "MessageManager.h" -#include "ControlManager.h" -#include "BaseControlDevice.h" -#include "Console.h" -#include "SaveStateManager.h" -#include "CheatManager.h" -#include "MovieRecorder.h" -#include "BatteryManager.h" -#include "VirtualFile.h" -#include "NotificationManager.h" -#include "RomData.h" - -MesenMovie::MesenMovie(shared_ptr console) -{ - _console = console; -} - -MesenMovie::~MesenMovie() -{ - Stop(); -} - -void MesenMovie::Stop() -{ - if(_playing) { - MessageManager::DisplayMessage("Movies", "MovieEnded"); - - _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::MovieEnded); - if(_console->GetSettings()->CheckFlag(EmulationFlags::PauseOnMovieEnd)) { - _console->GetSettings()->SetFlags(EmulationFlags::Paused); - } - - _playing = false; - } - _console->GetSettings()->SetInputPollScanline(241); - _console->GetControlManager()->UnregisterInputProvider(this); -} - -bool MesenMovie::SetInput(BaseControlDevice *device) -{ - uint32_t inputRowIndex = _console->GetControlManager()->GetPollCounter(); - - if(_inputData.size() > inputRowIndex && _inputData[inputRowIndex].size() > _deviceIndex) { - device->SetTextState(_inputData[inputRowIndex][_deviceIndex]); - - _deviceIndex++; - if(_deviceIndex >= _inputData[inputRowIndex].size()) { - //Move to the next frame's data - _deviceIndex = 0; - } - } else { - Stop(); - } - return true; -} - -bool MesenMovie::IsPlaying() -{ - return _playing; -} - -vector MesenMovie::LoadBattery(string extension) -{ - vector batteryData; - _reader->ExtractFile("Battery" + extension, batteryData); - return batteryData; -} - -void MesenMovie::ProcessNotification(ConsoleNotificationType type, void * parameter) -{ - if(type == ConsoleNotificationType::GameLoaded) { - _console->GetControlManager()->RegisterInputProvider(this); - } -} - -bool MesenMovie::Play(VirtualFile &file) -{ - _movieFile = file; - - std::stringstream ss; - file.ReadFile(ss); - - _reader.reset(new ZipReader()); - _reader->LoadArchive(ss); - - stringstream settingsData, inputData; - if(!_reader->GetStream("GameSettings.txt", settingsData)) { - MessageManager::Log("[Movie] File not found: GameSettings.txt"); - return false; - } - if(!_reader->GetStream("Input.txt", inputData)) { - MessageManager::Log("[Movie] File not found: Input.txt"); - return false; - } - - while(inputData) { - string line; - std::getline(inputData, line); - if(line.substr(0, 1) == "|") { - _inputData.push_back(StringUtilities::Split(line.substr(1), '|')); - } - } - - _deviceIndex = 0; - - ParseSettings(settingsData); - - _console->Pause(); - - _console->GetBatteryManager()->SetBatteryProvider(shared_from_this()); - _console->GetNotificationManager()->RegisterNotificationListener(shared_from_this()); - ApplySettings(); - - //Disable auto-configure input option (otherwise the movie file's input types are ignored) - bool autoConfigureInput = _console->GetSettings()->CheckFlag(EmulationFlags::AutoConfigureInput); - _console->GetSettings()->ClearFlags(EmulationFlags::AutoConfigureInput); - - ControlManager *controlManager = _console->GetControlManager(); - if(controlManager) { - //ControlManager can be empty if no game is loaded - controlManager->SetPollCounter(0); - } - - bool gameLoaded = LoadGame(); - _console->GetSettings()->SetFlagState(EmulationFlags::AutoConfigureInput, autoConfigureInput); - - if(!gameLoaded) { - _console->Resume(); - return false; - } - - stringstream saveStateData; - if(_reader->GetStream("SaveState.mst", saveStateData)) { - if(!_console->GetSaveStateManager()->LoadState(saveStateData, true)) { - _console->Resume(); - return false; - } else { - _console->GetControlManager()->SetPollCounter(0); - } - } - - _playing = true; - - _console->Resume(); - - return true; -} - -template -T FromString(string name, const vector &enumNames, T defaultValue) -{ - for(size_t i = 0; i < enumNames.size(); i++) { - if(name == enumNames[i]) { - return (T)i; - } - } - return defaultValue; -} - -void MesenMovie::ParseSettings(stringstream &data) -{ - while(!data.eof()) { - string line; - std::getline(data, line); - - if(!line.empty()) { - size_t index = line.find_first_of(' '); - if(index != string::npos) { - string name = line.substr(0, index); - string value = line.substr(index + 1); - - if(name == "Cheat") { - _cheats.push_back(value); - } else { - _settings[name] = value; - } - } - } - } -} - -bool MesenMovie::LoadGame() -{ - string mesenVersion = LoadString(_settings, MovieKeys::MesenVersion); - string gameFile = LoadString(_settings, MovieKeys::GameFile); - string sha1Hash = LoadString(_settings, MovieKeys::Sha1); - //string patchFile = LoadString(_settings, MovieKeys::PatchFile); - //string patchFileSha1 = LoadString(_settings, MovieKeys::PatchFileSha1); - //string patchedRomSha1 = LoadString(_settings, MovieKeys::PatchedRomSha1); - - if(_console->GetSettings()->CheckFlag(EmulationFlags::AllowMismatchingSaveState) && _console->GetRomInfo().RomName == gameFile) { - //Loaded game has the right name, and we don't want to validate the hash values - _console->PowerCycle(); - return true; - } - - HashInfo hashInfo; - hashInfo.Sha1 = sha1Hash; - - VirtualFile romFile = _console->FindMatchingRom(gameFile, hashInfo); - bool gameLoaded = false; - if(romFile.IsValid()) { - VirtualFile patchFile(_movieFile.GetFilePath(), "PatchData.dat"); - if(patchFile.IsValid()) { - gameLoaded = _console->Initialize(romFile, patchFile); - } else { - gameLoaded = _console->Initialize(romFile); - } - } - - return gameLoaded; -} - -void MesenMovie::ApplySettings() -{ - EmulationSettings* settings = _console->GetSettings(); - - NesModel region = FromString(LoadString(_settings, MovieKeys::Region), NesModelNames, NesModel::NTSC); - ConsoleType consoleType = FromString(LoadString(_settings, MovieKeys::ConsoleType), ConsoleTypeNames, ConsoleType::Nes); - ControllerType controller1 = FromString(LoadString(_settings, MovieKeys::Controller1), ControllerTypeNames, ControllerType::None); - ControllerType controller2 = FromString(LoadString(_settings, MovieKeys::Controller2), ControllerTypeNames, ControllerType::None); - ControllerType controller3 = FromString(LoadString(_settings, MovieKeys::Controller3), ControllerTypeNames, ControllerType::None); - ControllerType controller4 = FromString(LoadString(_settings, MovieKeys::Controller4), ControllerTypeNames, ControllerType::None); - ExpansionPortDevice expansionDevice = FromString(LoadString(_settings, MovieKeys::ExpansionDevice), ExpansionPortDeviceNames, ExpansionPortDevice::None); - - settings->SetNesModel(region); - settings->SetConsoleType(consoleType); - settings->SetControllerType(0, controller1); - settings->SetControllerType(1, controller2); - settings->SetControllerType(2, controller3); - settings->SetControllerType(3, controller4); - settings->SetExpansionDevice(expansionDevice); - - uint32_t ramPowerOnState = LoadInt(_settings, MovieKeys::RamPowerOnState); - if(ramPowerOnState == 0xFF) { - settings->SetRamPowerOnState(RamPowerOnState::AllOnes); - } else { - settings->SetRamPowerOnState(RamPowerOnState::AllZeros); - } - - settings->SetInputPollScanline(LoadInt(_settings, MovieKeys::InputPollScanline, 240)); - - settings->SetZapperDetectionRadius(LoadInt(_settings, MovieKeys::ZapperDetectionRadius)); - - settings->SetPpuNmiConfig( - LoadInt(_settings, MovieKeys::ExtraScanlinesBeforeNmi), - LoadInt(_settings, MovieKeys::ExtraScanlinesAfterNmi) - ); - - settings->SetFlagState(EmulationFlags::DisablePpu2004Reads, LoadBool(_settings, MovieKeys::DisablePpu2004Reads)); - settings->SetFlagState(EmulationFlags::DisablePaletteRead, LoadBool(_settings, MovieKeys::DisablePaletteRead)); - settings->SetFlagState(EmulationFlags::DisableOamAddrBug, LoadBool(_settings, MovieKeys::DisableOamAddrBug)); - settings->SetFlagState(EmulationFlags::UseNes101Hvc101Behavior, LoadBool(_settings, MovieKeys::UseNes101Hvc101Behavior)); - settings->SetFlagState(EmulationFlags::EnableOamDecay, LoadBool(_settings, MovieKeys::EnableOamDecay)); - settings->SetFlagState(EmulationFlags::DisablePpuReset, LoadBool(_settings, MovieKeys::DisablePpuReset)); - - settings->SetDipSwitches(HexUtilities::FromHex(LoadString(_settings, MovieKeys::DipSwitches))); - - LoadCheats(); -} - -uint32_t MesenMovie::LoadInt(std::unordered_map &settings, string name, uint32_t defaultValue) -{ - auto result = settings.find(name); - if(result != settings.end()) { - try { - return (uint32_t)std::stoul(result->second); - } catch(std::exception&) { - MessageManager::Log("[Movies] Invalid value for tag: " + name); - return defaultValue; - } - } else { - return defaultValue; - } -} - -bool MesenMovie::LoadBool(std::unordered_map &settings, string name) -{ - auto result = settings.find(name); - if(result != settings.end()) { - if(result->second == "true") { - return true; - } else if(result->second == "false") { - return false; - } else { - MessageManager::Log("[Movies] Invalid value for tag: " + name); - return false; - } - } else { - return false; - } -} - -string MesenMovie::LoadString(std::unordered_map &settings, string name) -{ - auto result = settings.find(name); - if(result != settings.end()) { - return result->second; - } else { - return ""; - } -} - -void MesenMovie::LoadCheats() -{ - vector cheats; - for(string cheatData : _cheats) { - CodeInfo code; - if(LoadCheat(cheatData, code)) { - cheats.push_back(code); - } - } - _console->GetCheatManager()->SetCheats(cheats); -} - -bool MesenMovie::LoadCheat(string cheatData, CodeInfo &code) -{ - vector data = StringUtilities::Split(cheatData, ' '); - - if(data.size() >= 3) { - uint32_t address = HexUtilities::FromHex(data[0]); - uint8_t value = HexUtilities::FromHex(data[1]); - bool relativeAddress = data[2] == "true"; - int32_t compareValue = data.size() > 3 ? HexUtilities::FromHex(data[3]) : -1; - - code.Address = address; - code.Value = value; - code.IsRelativeAddress = relativeAddress; - code.CompareValue = compareValue; - return true; - } else { - MessageManager::Log("[Movie] Invalid cheat definition: " + cheatData); - } - return false; -} diff --git a/Core/MesenMovie.h b/Core/MesenMovie.h deleted file mode 100644 index d8adeba2..00000000 --- a/Core/MesenMovie.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "stdafx.h" -#include "MovieManager.h" -#include "VirtualFile.h" -#include "BatteryManager.h" -#include "INotificationListener.h" - -class ZipReader; -class Console; -struct CodeInfo; - -class MesenMovie : public IMovie, public INotificationListener, public IBatteryProvider, public std::enable_shared_from_this -{ -private: - shared_ptr _console; - - VirtualFile _movieFile; - shared_ptr _reader; - bool _playing = false; - size_t _deviceIndex = 0; - vector> _inputData; - vector _cheats; - std::unordered_map _settings; - string _filename; - -private: - void ParseSettings(stringstream &data); - void ApplySettings(); - bool LoadGame(); - void Stop(); - - uint32_t LoadInt(std::unordered_map &settings, string name, uint32_t defaultValue = 0); - bool LoadBool(std::unordered_map &settings, string name); - string LoadString(std::unordered_map &settings, string name); - void LoadCheats(); - bool LoadCheat(string cheatData, CodeInfo &code); - -public: - MesenMovie(shared_ptr console); - virtual ~MesenMovie(); - - bool Play(VirtualFile &file) override; - bool SetInput(BaseControlDevice* device) override; - bool IsPlaying() override; - - // Inherited via IBatteryProvider - virtual vector LoadBattery(string extension) override; - - // Inherited via INotificationListener - virtual void ProcessNotification(ConsoleNotificationType type, void * parameter) override; -}; \ No newline at end of file diff --git a/Core/MovieDataMessage.h b/Core/MovieDataMessage.h deleted file mode 100644 index bafd7909..00000000 --- a/Core/MovieDataMessage.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "stdafx.h" -#include "NetMessage.h" -#include "ControlDeviceState.h" - -class MovieDataMessage : public NetMessage -{ -private: - uint8_t _portNumber; - ControlDeviceState _inputState; - -protected: - virtual void ProtectedStreamState() - { - Stream(_portNumber); - StreamArray(_inputState.State); - } - -public: - MovieDataMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) { } - - MovieDataMessage(ControlDeviceState state, uint8_t port) : NetMessage(MessageType::MovieData) - { - _portNumber = port; - _inputState = state; - } - - uint8_t GetPortNumber() - { - return _portNumber; - } - - ControlDeviceState GetInputState() - { - return _inputState; - } -}; \ No newline at end of file diff --git a/Core/MovieManager.cpp b/Core/MovieManager.cpp deleted file mode 100644 index 0c9d0ac9..00000000 --- a/Core/MovieManager.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "stdafx.h" -#include "../Utilities/FolderUtilities.h" -#include "MovieManager.h" -#include "MesenMovie.h" -#include "BizhawkMovie.h" -#include "FceuxMovie.h" -#include "MovieRecorder.h" -#include "VirtualFile.h" - -shared_ptr MovieManager::_player; -shared_ptr MovieManager::_recorder; - -void MovieManager::Record(RecordMovieOptions options, shared_ptr console) -{ - shared_ptr recorder(new MovieRecorder(console)); - if(recorder->Record(options)) { - _recorder = recorder; - } -} - -void MovieManager::Play(VirtualFile file, shared_ptr console) -{ - vector fileData; - if(file.IsValid() && file.ReadFile(fileData)) { - shared_ptr player; - if(memcmp(fileData.data(), "MMO", 3) == 0) { - //Old movie format, no longer supported - MessageManager::DisplayMessage("Movies", "MovieIncompatibleVersion"); - } else if(memcmp(fileData.data(), "PK", 2) == 0) { - //Mesen or Bizhawk movie - ZipReader reader; - reader.LoadArchive(fileData); - - vector files = reader.GetFileList(); - if(std::find(files.begin(), files.end(), "GameSettings.txt") != files.end()) { - player.reset(new MesenMovie(console)); - } else { - player.reset(new BizhawkMovie(console)); - } - } else if(memcmp(fileData.data(), "ver", 3) == 0) { - player.reset(new FceuxMovie(console)); - } - - if(player && player->Play(file)) { - _player = player; - - MessageManager::DisplayMessage("Movies", "MoviePlaying", file.GetFileName()); - } - } -} - -void MovieManager::Stop() -{ - _player.reset(); - - if(_recorder) { - _recorder.reset(); - } -} - -bool MovieManager::Playing() -{ - shared_ptr player = _player; - return player && player->IsPlaying(); -} - -bool MovieManager::Recording() -{ - return _recorder != nullptr; -} diff --git a/Core/MovieManager.h b/Core/MovieManager.h deleted file mode 100644 index b2761ffc..00000000 --- a/Core/MovieManager.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "stdafx.h" -#include "MessageManager.h" -#include "EmulationSettings.h" -#include "IInputProvider.h" -#include "Types.h" - -class MovieRecorder; -class VirtualFile; -class Console; - -class IMovie : public IInputProvider -{ -public: - virtual bool Play(VirtualFile &file) = 0; - virtual bool IsPlaying() = 0; -}; - -class MovieManager -{ -private: - static shared_ptr _player; - static shared_ptr _recorder; - -public: - static void Record(RecordMovieOptions options, shared_ptr console); - static void Play(VirtualFile file, shared_ptr console); - static void Stop(); - static bool Playing(); - static bool Recording(); -}; \ No newline at end of file diff --git a/Core/MovieRecorder.cpp b/Core/MovieRecorder.cpp deleted file mode 100644 index c3ada797..00000000 --- a/Core/MovieRecorder.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include "stdafx.h" -#include -#include "../Utilities/HexUtilities.h" -#include "../Utilities/FolderUtilities.h" -#include "../Utilities/ZipWriter.h" -#include "MovieRecorder.h" -#include "ControlManager.h" -#include "BaseControlDevice.h" -#include "Console.h" -#include "CheatManager.h" -#include "VirtualFile.h" -#include "SaveStateManager.h" -#include "NotificationManager.h" -#include "RomData.h" -#include "RewindData.h" - -MovieRecorder::MovieRecorder(shared_ptr console) -{ - _console = console; -} - -MovieRecorder::~MovieRecorder() -{ - Stop(); -} - -bool MovieRecorder::Record(RecordMovieOptions options) -{ - _filename = options.Filename; - _author = options.Author; - _description = options.Description; - _writer.reset(new ZipWriter()); - _inputData = stringstream(); - _saveStateData = stringstream(); - _hasSaveState = false; - - if(!_writer->Initialize(_filename)) { - _writer.reset(); - return false; - } else { - _console->Pause(); - - if(options.RecordFrom == RecordMovieFrom::StartWithoutSaveData) { - _console->GetBatteryManager()->SetBatteryProvider(shared_from_this()); - } - - //Save existing battery files - if(options.RecordFrom == RecordMovieFrom::StartWithSaveData) { - _console->GetBatteryManager()->SetBatteryRecorder(shared_from_this()); - } - - _console->GetNotificationManager()->RegisterNotificationListener(shared_from_this()); - if(options.RecordFrom == RecordMovieFrom::CurrentState) { - _console->GetControlManager()->RegisterInputRecorder(this); - _console->GetSaveStateManager()->SaveState(_saveStateData); - _hasSaveState = true; - } else { - _console->PowerCycle(); - } - _console->GetBatteryManager()->SetBatteryRecorder(nullptr); - _console->Resume(); - - MessageManager::DisplayMessage("Movies", "MovieRecordingTo", FolderUtilities::GetFilename(_filename, true)); - - return true; - } -} - -void MovieRecorder::GetGameSettings(stringstream &out) -{ - EmulationSettings* settings = _console->GetSettings(); - NesModel model = _console->GetModel(); - - WriteString(out, MovieKeys::MesenVersion, settings->GetMesenVersionString()); - WriteInt(out, MovieKeys::MovieFormatVersion, MovieRecorder::MovieFormatVersion); - - VirtualFile romFile = _console->GetRomPath(); - WriteString(out, MovieKeys::GameFile, romFile.GetFileName()); - WriteString(out, MovieKeys::Sha1, romFile.GetSha1Hash()); - - VirtualFile patchFile = _console->GetPatchFile(); - if(patchFile.IsValid()) { - WriteString(out, MovieKeys::PatchFile, patchFile.GetFileName()); - WriteString(out, MovieKeys::PatchFileSha1, patchFile.GetSha1Hash()); - WriteString(out, MovieKeys::PatchedRomSha1, _console->GetRomInfo().Hash.Sha1); - } - - switch(model) { - case NesModel::Auto: break; //Console::GetModel() will never return Auto. - case NesModel::NTSC: WriteString(out, MovieKeys::Region, "NTSC"); break; - case NesModel::PAL: WriteString(out, MovieKeys::Region, "PAL"); break; - case NesModel::Dendy: WriteString(out, MovieKeys::Region, "Dendy"); break; - } - - switch(settings->GetConsoleType()) { - case ConsoleType::Nes: WriteString(out, MovieKeys::ConsoleType, "NES"); break; - case ConsoleType::Famicom: WriteString(out, MovieKeys::ConsoleType, "Famicom"); break; - } - - WriteString(out, MovieKeys::Controller1, ControllerTypeNames[(int)settings->GetControllerType(0)]); - WriteString(out, MovieKeys::Controller2, ControllerTypeNames[(int)settings->GetControllerType(1)]); - if(settings->CheckFlag(EmulationFlags::HasFourScore)) { - WriteString(out, MovieKeys::Controller3, ControllerTypeNames[(int)settings->GetControllerType(2)]); - WriteString(out, MovieKeys::Controller4, ControllerTypeNames[(int)settings->GetControllerType(3)]); - } - - if(settings->GetConsoleType() == ConsoleType::Famicom) { - WriteString(out, MovieKeys::ExpansionDevice, ExpansionPortDeviceNames[(int)settings->GetExpansionDevice()]); - } - - WriteInt(out, MovieKeys::ExtraScanlinesBeforeNmi, settings->GetPpuExtraScanlinesBeforeNmi()); - WriteInt(out, MovieKeys::ExtraScanlinesAfterNmi, settings->GetPpuExtraScanlinesAfterNmi()); - WriteInt(out, MovieKeys::InputPollScanline, settings->GetInputPollScanline()); - - WriteBool(out, MovieKeys::DisablePpu2004Reads, settings->CheckFlag(EmulationFlags::DisablePpu2004Reads)); - WriteBool(out, MovieKeys::DisablePaletteRead, settings->CheckFlag(EmulationFlags::DisablePaletteRead)); - WriteBool(out, MovieKeys::DisableOamAddrBug, settings->CheckFlag(EmulationFlags::DisableOamAddrBug)); - WriteBool(out, MovieKeys::UseNes101Hvc101Behavior, settings->CheckFlag(EmulationFlags::UseNes101Hvc101Behavior)); - WriteBool(out, MovieKeys::EnableOamDecay, settings->CheckFlag(EmulationFlags::EnableOamDecay)); - WriteBool(out, MovieKeys::DisablePpuReset, settings->CheckFlag(EmulationFlags::DisablePpuReset)); - - WriteInt(out, MovieKeys::ZapperDetectionRadius, settings->GetZapperDetectionRadius()); - - switch(settings->GetRamPowerOnState()) { - case RamPowerOnState::AllZeros: WriteInt(out, MovieKeys::RamPowerOnState, 0x00); break; - case RamPowerOnState::AllOnes: WriteInt(out, MovieKeys::RamPowerOnState, 0xFF); break; - case RamPowerOnState::Random: WriteInt(out, MovieKeys::RamPowerOnState, -1); break; //TODO: Shouldn't be used for movies - } - - if(_console->GetDipSwitchCount() > 0) { - WriteString(out, MovieKeys::DipSwitches, HexUtilities::ToHex(settings->GetDipSwitches())); - } - - for(CodeInfo &code : _console->GetCheatManager()->GetCheats()) { - WriteCheat(out, code); - } -} - -void MovieRecorder::WriteCheat(stringstream &out, CodeInfo &code) -{ - out << "Cheat " << - HexUtilities::ToHex(code.Address) << " " << - HexUtilities::ToHex(code.Value) << " " << - (code.IsRelativeAddress ? "true" : "false") << " " << - (code.CompareValue < 0 ? HexUtilities::ToHex((uint8_t)code.CompareValue) : "") << "\n"; -} - -void MovieRecorder::WriteString(stringstream &out, string name, string value) -{ - out << name << " " << value << "\n"; -} - -void MovieRecorder::WriteInt(stringstream &out, string name, uint32_t value) -{ - out << name << " " << std::to_string(value) << "\n"; -} - -void MovieRecorder::WriteBool(stringstream &out, string name, bool enabled) -{ - out << name << " " << (enabled ? "true" : "false") << "\n"; -} - -bool MovieRecorder::Stop() -{ - if(_writer) { - _console->GetControlManager()->UnregisterInputRecorder(this); - - _writer->AddFile(_inputData, "Input.txt"); - - stringstream out; - GetGameSettings(out); - _writer->AddFile(out, "GameSettings.txt"); - - if(!_author.empty() || !_description.empty()) { - stringstream movieInfo; - WriteString(movieInfo, "Author", _author); - movieInfo << "Description\n" << _description; - _writer->AddFile(movieInfo, "MovieInfo.txt"); - } - - VirtualFile patchFile = _console->GetPatchFile(); - vector patchData; - if(patchFile.IsValid() && patchFile.ReadFile(patchData)) { - _writer->AddFile(patchData, "PatchData.dat"); - } - - if(_hasSaveState) { - _writer->AddFile(_saveStateData, "SaveState.mst"); - } - - for(auto kvp : _batteryData) { - _writer->AddFile(kvp.second, "Battery" + kvp.first); - } - - bool result = _writer->Save(); - if(result) { - MessageManager::DisplayMessage("Movies", "MovieSaved", FolderUtilities::GetFilename(_filename, true)); - } - return result; - } - - return false; -} - -void MovieRecorder::RecordInput(vector> devices) -{ - for(shared_ptr &device : devices) { - _inputData << ("|" + device->GetTextState()); - } - _inputData << "\n"; -} - -void MovieRecorder::OnLoadBattery(string extension, vector batteryData) -{ - _batteryData[extension] = batteryData; -} - -vector MovieRecorder::LoadBattery(string extension) -{ - return vector(); -} - -void MovieRecorder::ProcessNotification(ConsoleNotificationType type, void *parameter) -{ - if(type == ConsoleNotificationType::GameLoaded) { - _console->GetControlManager()->RegisterInputRecorder(this); - } -} - -bool MovieRecorder::CreateMovie(string movieFile, std::deque &data, uint32_t startPosition, uint32_t endPosition) -{ - _filename = movieFile; - _writer.reset(new ZipWriter()); - if(startPosition < data.size() && endPosition <= data.size() && _writer->Initialize(_filename)) { - vector> devices = _console->GetControlManager()->GetControlDevices(); - - if(startPosition > 0 || _console->GetRomInfo().HasBattery || _console->GetSettings()->GetRamPowerOnState() == RamPowerOnState::Random) { - //Create a movie from a savestate if we don't start from the beginning (or if the game has save ram, or if the power on ram state is random) - _hasSaveState = true; - _saveStateData = stringstream(); - _console->GetSaveStateManager()->GetSaveStateHeader(_saveStateData); - data[startPosition].GetStateData(_saveStateData); - } - - _inputData = stringstream(); - - for(uint32_t i = startPosition; i < endPosition; i++) { - RewindData rewindData = data[i]; - for(uint32_t i = 0; i < 30; i++) { - for(shared_ptr &device : devices) { - uint8_t port = device->GetPort(); - if(i < rewindData.InputLogs[port].size()) { - device->SetRawState(rewindData.InputLogs[port][i]); - _inputData << ("|" + device->GetTextState()); - } - } - _inputData << "\n"; - } - } - - //Write the movie file - return Stop(); - } - return false; -} \ No newline at end of file diff --git a/Core/MovieRecorder.h b/Core/MovieRecorder.h deleted file mode 100644 index 8a3f22b4..00000000 --- a/Core/MovieRecorder.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include -#include "IInputRecorder.h" -#include "BatteryManager.h" -#include "Types.h" -#include "INotificationListener.h" - -class ZipWriter; -class Console; -class RewindData; -struct CodeInfo; - -class MovieRecorder : public INotificationListener, public IInputRecorder, public IBatteryRecorder, public IBatteryProvider, public std::enable_shared_from_this -{ -private: - static const uint32_t MovieFormatVersion = 1; - - shared_ptr _console; - string _filename; - string _author; - string _description; - unique_ptr _writer; - std::unordered_map> _batteryData; - stringstream _inputData; - bool _hasSaveState = false; - stringstream _saveStateData; - - void GetGameSettings(stringstream &out); - void WriteCheat(stringstream &out, CodeInfo &code); - void WriteString(stringstream &out, string name, string value); - void WriteInt(stringstream &out, string name, uint32_t value); - void WriteBool(stringstream &out, string name, bool enabled); - -public: - MovieRecorder(shared_ptr console); - virtual ~MovieRecorder(); - - bool Record(RecordMovieOptions options); - bool Stop(); - - bool CreateMovie(string movieFile, std::deque &data, uint32_t startPosition, uint32_t endPosition); - - // Inherited via IInputRecorder - void RecordInput(vector> devices) override; - - // Inherited via IBatteryRecorder - virtual void OnLoadBattery(string extension, vector batteryData) override; - - // Inherited via IBatteryProvider - virtual vector LoadBattery(string extension) override; - - // Inherited via INotificationListener - virtual void ProcessNotification(ConsoleNotificationType type, void *parameter) override; -}; - -namespace MovieKeys -{ - constexpr const char* MesenVersion = "MesenVersion"; - constexpr const char* MovieFormatVersion = "MovieFormatVersion"; - constexpr const char* GameFile = "GameFile"; - constexpr const char* Sha1 = "SHA1"; - constexpr const char* PatchFile = "PatchFile"; - constexpr const char* PatchFileSha1 = "PatchFileSHA1"; - constexpr const char* PatchedRomSha1 = "PatchedRomSHA1"; - constexpr const char* Region = "Region"; - constexpr const char* ConsoleType = "ConsoleType"; - constexpr const char* Controller1 = "Controller1"; - constexpr const char* Controller2 = "Controller2"; - constexpr const char* Controller3 = "Controller3"; - constexpr const char* Controller4 = "Controller4"; - constexpr const char* ExpansionDevice = "ExpansionDevice"; - constexpr const char* ExtraScanlinesBeforeNmi = "ExtraScanlinesBeforeNmi"; - constexpr const char* ExtraScanlinesAfterNmi = "ExtraScanlinesAfterNmi"; - constexpr const char* DisablePpu2004Reads = "DisablePpu2004Reads"; - constexpr const char* DisablePaletteRead = "DisablePaletteRead"; - constexpr const char* DisableOamAddrBug = "DisableOamAddrBug"; - constexpr const char* UseNes101Hvc101Behavior = "UseNes101Hvc101Behavior"; - constexpr const char* EnableOamDecay = "EnableOamDecay"; - constexpr const char* DisablePpuReset = "DisablePpuReset"; - constexpr const char* ZapperDetectionRadius = "ZapperDetectionRadius"; - constexpr const char* RamPowerOnState = "RamPowerOnState"; - constexpr const char* DipSwitches = "DipSwitches"; - constexpr const char* InputPollScanline = "InputPollScanline"; -}; \ No newline at end of file diff --git a/Core/RewindData.cpp b/Core/RewindData.cpp deleted file mode 100644 index 4379eed9..00000000 --- a/Core/RewindData.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "stdafx.h" -#include "RewindData.h" -#include "Console.h" -#include "../Utilities/miniz.h" - -void RewindData::GetStateData(stringstream &stateData) -{ - unsigned long length = OriginalSaveStateSize; - uint8_t* buffer = new uint8_t[length]; - uncompress(buffer, &length, SaveStateData.data(), (unsigned long)SaveStateData.size()); - stateData.write((char*)buffer, length); - delete[] buffer; -} - -void RewindData::LoadState(shared_ptr &console) -{ - if(SaveStateData.size() > 0 && OriginalSaveStateSize > 0) { - unsigned long length = OriginalSaveStateSize; - uint8_t* buffer = new uint8_t[length]; - uncompress(buffer, &length, SaveStateData.data(), (unsigned long)SaveStateData.size()); - console->LoadState(buffer, length); - delete[] buffer; - } -} - -void RewindData::CompressState(string stateData, vector& compressedState) -{ - unsigned long compressedSize = compressBound((unsigned long)stateData.size()); - uint8_t* compressedData = new uint8_t[compressedSize]; - compress(compressedData, &compressedSize, (unsigned char*)stateData.c_str(), (unsigned long)stateData.size()); - compressedState = vector(compressedData, compressedData + compressedSize); - delete[] compressedData; -} - -void RewindData::SaveState(shared_ptr &console) -{ - std::stringstream state; - console->SaveState(state); - - string stateData = state.str(); - vector compressedState; - CompressState(stateData, compressedState); - SaveStateData = compressedState; - OriginalSaveStateSize = (uint32_t)stateData.size(); - FrameCount = 0; -} diff --git a/Core/RewindData.h b/Core/RewindData.h deleted file mode 100644 index f47894d3..00000000 --- a/Core/RewindData.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "BaseControlDevice.h" - -class Console; - -class RewindData -{ -private: - vector SaveStateData; - uint32_t OriginalSaveStateSize = 0; - - void CompressState(string stateData, vector &compressedState); - -public: - std::deque InputLogs[BaseControlDevice::PortCount]; - int32_t FrameCount = 0; - bool EndOfSegment = false; - - void GetStateData(stringstream &stateData); - - void LoadState(shared_ptr &console); - void SaveState(shared_ptr &console); -}; diff --git a/Core/RewindManager.cpp b/Core/RewindManager.cpp deleted file mode 100644 index ebb02dd1..00000000 --- a/Core/RewindManager.cpp +++ /dev/null @@ -1,382 +0,0 @@ -#include "stdafx.h" -#include "RewindManager.h" -#include "MessageManager.h" -#include "Console.h" -#include "VideoRenderer.h" -#include "SoundMixer.h" -#include "BaseControlDevice.h" -#include "HistoryViewer.h" - -RewindManager::RewindManager(shared_ptr console) -{ - _console = console; - _settings = console->GetSettings(); - _rewindState = RewindState::Stopped; - _framesToFastForward = 0; - _hasHistory = false; - AddHistoryBlock(); - - Initialize(); -} - -RewindManager::~RewindManager() -{ - _console->GetControlManager()->UnregisterInputProvider(this); - _console->GetControlManager()->UnregisterInputRecorder(this); -} - -void RewindManager::Initialize() -{ - _console->GetControlManager()->RegisterInputProvider(this); - _console->GetControlManager()->RegisterInputRecorder(this); -} - -void RewindManager::ClearBuffer() -{ - _hasHistory = false; - _history.clear(); - _historyBackup.clear(); - _currentHistory = RewindData(); - _framesToFastForward = 0; - _videoHistory.clear(); - _videoHistoryBuilder.clear(); - _audioHistory.clear(); - _audioHistoryBuilder.clear(); - _rewindState = RewindState::Stopped; - _currentHistory = RewindData(); -} - -void RewindManager::ProcessNotification(ConsoleNotificationType type, void * parameter) -{ - if(_settings->IsRunAheadFrame()) { - return; - } - - if(type == ConsoleNotificationType::PpuFrameDone) { - _hasHistory = _history.size() >= 2; - if(_settings->GetRewindBufferSize() > 0) { - switch(_rewindState) { - case RewindState::Starting: - case RewindState::Started: - case RewindState::Debugging: - _currentHistory.FrameCount--; - break; - - case RewindState::Stopping: - _framesToFastForward--; - _currentHistory.FrameCount++; - if(_framesToFastForward == 0) { - for(int i = 0; i < 4; i++) { - size_t numberToRemove = _currentHistory.InputLogs[i].size(); - _currentHistory.InputLogs[i] = _historyBackup.front().InputLogs[i]; - for(size_t j = 0; j < numberToRemove; j++) { - _currentHistory.InputLogs[i].pop_back(); - } - } - _historyBackup.clear(); - _rewindState = RewindState::Stopped; - _settings->ClearFlags(EmulationFlags::Rewind); - _settings->ClearFlags(EmulationFlags::ForceMaxSpeed); - } - break; - - case RewindState::Stopped: - _currentHistory.FrameCount++; - break; - } - } else { - ClearBuffer(); - } - } else if(type == ConsoleNotificationType::StateLoaded) { - if(_rewindState == RewindState::Stopped) { - //A save state was loaded by the user, mark as the end of the current "segment" (for history viewer) - _currentHistory.EndOfSegment = true; - } - } -} - -void RewindManager::AddHistoryBlock() -{ - uint32_t maxHistorySize = _settings->GetRewindBufferSize() * 120; - if(maxHistorySize > 0) { - while(_history.size() > maxHistorySize) { - _history.pop_front(); - } - - if(_currentHistory.FrameCount > 0) { - _history.push_back(_currentHistory); - } - _currentHistory = RewindData(); - _currentHistory.SaveState(_console); - } -} - -void RewindManager::PopHistory() -{ - if(_history.empty() && _currentHistory.FrameCount <= 0) { - StopRewinding(); - } else { - if(_currentHistory.FrameCount <= 0) { - _currentHistory = _history.back(); - _history.pop_back(); - } - - _historyBackup.push_front(_currentHistory); - _currentHistory.LoadState(_console); - if(!_audioHistoryBuilder.empty()) { - _audioHistory.insert(_audioHistory.begin(), _audioHistoryBuilder.begin(), _audioHistoryBuilder.end()); - _audioHistoryBuilder.clear(); - } - } -} - -void RewindManager::Start(bool forDebugger) -{ - if(_rewindState == RewindState::Stopped && _settings->GetRewindBufferSize() > 0) { - if(_history.empty() && !forDebugger) { - //No history to rewind - return; - } - - _console->Pause(); - - _rewindState = forDebugger ? RewindState::Debugging : RewindState::Starting; - _videoHistoryBuilder.clear(); - _videoHistory.clear(); - _audioHistoryBuilder.clear(); - _audioHistory.clear(); - _historyBackup.clear(); - - if(_history.empty()) { - _currentHistory.LoadState(_console); - } else { - PopHistory(); - } - - _settings->SetFlags(EmulationFlags::ForceMaxSpeed); - _settings->SetFlags(EmulationFlags::Rewind); - - _console->Resume(); - } -} - -void RewindManager::ForceStop() -{ - if(_rewindState != RewindState::Stopped) { - while(_historyBackup.size() > 1) { - _history.push_back(_historyBackup.front()); - _historyBackup.pop_front(); - } - if(!_historyBackup.empty()) { - _currentHistory = _historyBackup.front(); - } - _historyBackup.clear(); - _rewindState = RewindState::Stopped; - _settings->ClearFlags(EmulationFlags::ForceMaxSpeed); - _settings->ClearFlags(EmulationFlags::Rewind); - } -} - -void RewindManager::Stop() -{ - if(_rewindState >= RewindState::Starting) { - _console->Pause(); - if(_rewindState == RewindState::Started) { - //Move back to the save state containing the frame currently shown on the screen - if(_historyBackup.size() > 1) { - _framesToFastForward = (uint32_t)_videoHistory.size() + _historyBackup.front().FrameCount; - do { - _history.push_back(_historyBackup.front()); - _framesToFastForward -= _historyBackup.front().FrameCount; - _historyBackup.pop_front(); - - _currentHistory = _historyBackup.front(); - } - while(_framesToFastForward > RewindManager::BufferSize && _historyBackup.size() > 1); - } - } else { - //We started rewinding, but didn't actually visually rewind anything yet - //Move back to the save state containing the frame currently shown on the screen - while(_historyBackup.size() > 1) { - _history.push_back(_historyBackup.front()); - _historyBackup.pop_front(); - } - _currentHistory = _historyBackup.front(); - _framesToFastForward = _historyBackup.front().FrameCount; - } - - _currentHistory.LoadState(_console); - if(_framesToFastForward > 0) { - _rewindState = RewindState::Stopping; - _currentHistory.FrameCount = 0; - _settings->SetFlags(EmulationFlags::ForceMaxSpeed); - } else { - _rewindState = RewindState::Stopped; - _historyBackup.clear(); - _settings->ClearFlags(EmulationFlags::ForceMaxSpeed); - _settings->ClearFlags(EmulationFlags::Rewind); - } - - _videoHistoryBuilder.clear(); - _videoHistory.clear(); - _audioHistoryBuilder.clear(); - _audioHistory.clear(); - - _console->Resume(); - } -} - -void RewindManager::ProcessEndOfFrame() -{ - if(_rewindState >= RewindState::Starting) { - if(_currentHistory.FrameCount <= 0 && _rewindState != RewindState::Debugging) { - //If we're debugging, we want to keep running the emulation to the end of the next frame (even if it's incomplete) - //Otherwise the emulation might diverge due to missing inputs. - PopHistory(); - } - } else if(_currentHistory.FrameCount >= RewindManager::BufferSize) { - AddHistoryBlock(); - } -} - -void RewindManager::ProcessFrame(void * frameBuffer, uint32_t width, uint32_t height, bool forRewind) -{ - if(_rewindState == RewindState::Starting || _rewindState == RewindState::Started) { - if(!forRewind) { - //Ignore any frames that occur between start of rewind process & first rewinded frame completed - //These are caused by the fact that VideoDecoder is asynchronous - a previous (extra) frame can end up - //in the rewind queue, which causes display glitches - return; - } - - _videoHistoryBuilder.push_back(vector((uint32_t*)frameBuffer, (uint32_t*)frameBuffer + width*height)); - - if(_videoHistoryBuilder.size() == (size_t)_historyBackup.front().FrameCount) { - for(int i = (int)_videoHistoryBuilder.size() - 1; i >= 0; i--) { - _videoHistory.push_front(_videoHistoryBuilder[i]); - } - _videoHistoryBuilder.clear(); - } - - if(_rewindState == RewindState::Started || _videoHistory.size() >= RewindManager::BufferSize) { - _rewindState = RewindState::Started; - _settings->ClearFlags(EmulationFlags::ForceMaxSpeed); - if(!_videoHistory.empty()) { - _console->GetVideoRenderer()->UpdateFrame(_videoHistory.back().data(), width, height); - _videoHistory.pop_back(); - } - } - } else if(_rewindState == RewindState::Stopping || _rewindState == RewindState::Debugging) { - //Display nothing while resyncing - } else { - _console->GetVideoRenderer()->UpdateFrame(frameBuffer, width, height); - } -} - -bool RewindManager::ProcessAudio(int16_t * soundBuffer, uint32_t sampleCount, uint32_t sampleRate) -{ - if(_rewindState == RewindState::Starting || _rewindState == RewindState::Started) { - _audioHistoryBuilder.insert(_audioHistoryBuilder.end(), soundBuffer, soundBuffer + sampleCount * 2); - - if(_rewindState == RewindState::Started && _audioHistory.size() > sampleCount * 2) { - for(uint32_t i = 0; i < sampleCount * 2; i++) { - soundBuffer[i] = _audioHistory.back(); - _audioHistory.pop_back(); - } - - return true; - } else { - //Mute while we prepare to rewind - return false; - } - } else if(_rewindState == RewindState::Stopping || _rewindState == RewindState::Debugging) { - //Mute while we resync - return false; - } else { - return true; - } -} - -void RewindManager::RecordInput(vector> devices) -{ - if(_settings->GetRewindBufferSize() > 0 && _rewindState == RewindState::Stopped) { - for(shared_ptr &device : devices) { - _currentHistory.InputLogs[device->GetPort()].push_back(device->GetRawState()); - } - } -} - -bool RewindManager::SetInput(BaseControlDevice *device) -{ - uint8_t port = device->GetPort(); - if(!_currentHistory.InputLogs[port].empty() && IsRewinding()) { - ControlDeviceState state = _currentHistory.InputLogs[port].front(); - _currentHistory.InputLogs[port].pop_front(); - device->SetRawState(state); - return true; - } else { - return false; - } -} - -void RewindManager::StartRewinding(bool forDebugger) -{ - Start(forDebugger); -} - -void RewindManager::StopRewinding(bool forDebugger) -{ - if(forDebugger) { - ForceStop(); - } else { - Stop(); - } -} - -bool RewindManager::IsRewinding() -{ - return _rewindState != RewindState::Stopped; -} - -bool RewindManager::IsStepBack() -{ - return _rewindState == RewindState::Debugging; -} - -void RewindManager::RewindSeconds(uint32_t seconds) -{ - if(_rewindState == RewindState::Stopped) { - uint32_t removeCount = (seconds * 60 / RewindManager::BufferSize) + 1; - _console->Pause(); - for(uint32_t i = 0; i < removeCount; i++) { - if(!_history.empty()) { - _currentHistory = _history.back(); - _history.pop_back(); - } else { - break; - } - } - _currentHistory.LoadState(_console); - _console->Resume(); - } -} - -bool RewindManager::HasHistory() -{ - return _hasHistory; -} - -void RewindManager::CopyHistory(shared_ptr destHistoryViewer) -{ - destHistoryViewer->SetHistoryData(_history); -} - -void RewindManager::SendFrame(void * frameBuffer, uint32_t width, uint32_t height, bool forRewind) -{ - ProcessFrame(frameBuffer, width, height, forRewind); -} - -bool RewindManager::SendAudio(int16_t * soundBuffer, uint32_t sampleCount, uint32_t sampleRate) -{ - return ProcessAudio(soundBuffer, sampleCount, sampleRate); -} diff --git a/Core/RewindManager.h b/Core/RewindManager.h deleted file mode 100644 index 23519353..00000000 --- a/Core/RewindManager.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include "stdafx.h" -#include -#include "INotificationListener.h" -#include "RewindData.h" -#include "IInputProvider.h" -#include "IInputRecorder.h" - -class Console; -class HistoryViewer; - -enum class RewindState -{ - Stopped = 0, - Stopping = 1, - Starting = 2, - Started = 3, - Debugging = 4 -}; - -class RewindManager : public INotificationListener, public IInputProvider, public IInputRecorder -{ -private: - static constexpr int32_t BufferSize = 30; //Number of frames between each save state - - shared_ptr _console; - EmulationSettings* _settings; - - bool _hasHistory; - - std::deque _history; - std::deque _historyBackup; - RewindData _currentHistory; - - RewindState _rewindState; - int32_t _framesToFastForward; - - std::deque> _videoHistory; - vector> _videoHistoryBuilder; - std::deque _audioHistory; - vector _audioHistoryBuilder; - - void AddHistoryBlock(); - void PopHistory(); - - void Start(bool forDebugger); - void Stop(); - void ForceStop(); - - void ProcessFrame(void *frameBuffer, uint32_t width, uint32_t height, bool forRewind); - bool ProcessAudio(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate); - - void ClearBuffer(); - -public: - RewindManager(shared_ptr console); - virtual ~RewindManager(); - - void Initialize(); - - void ProcessNotification(ConsoleNotificationType type, void* parameter) override; - void ProcessEndOfFrame(); - - void RecordInput(vector> devices) override; - bool SetInput(BaseControlDevice *device) override; - - void StartRewinding(bool forDebugger = false); - void StopRewinding(bool forDebugger = false); - bool IsRewinding(); - bool IsStepBack(); - void RewindSeconds(uint32_t seconds); - - bool HasHistory(); - void CopyHistory(shared_ptr destHistoryViewer); - - void SendFrame(void *frameBuffer, uint32_t width, uint32_t height, bool forRewind); - bool SendAudio(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate); -}; \ No newline at end of file diff --git a/Core/SaveStateManager.cpp b/Core/SaveStateManager.cpp index 54e4ecc1..63e34cd0 100644 --- a/Core/SaveStateManager.cpp +++ b/Core/SaveStateManager.cpp @@ -5,7 +5,6 @@ #include "EmulationSettings.h" #include "VideoDecoder.h" #include "Debugger.h" -#include "MovieManager.h" #include "RomData.h" #include "DefaultVideoFilter.h" #include "PPU.h" @@ -97,10 +96,6 @@ 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/VsControlManager.h b/Core/VsControlManager.h index 459cb60a..3ef3df29 100644 --- a/Core/VsControlManager.h +++ b/Core/VsControlManager.h @@ -6,7 +6,6 @@ #include "VsZapper.h" #include #include "StandardController.h" -#include "MovieManager.h" #include "IInputProvider.h" class BaseControlDevice; @@ -68,4 +67,4 @@ public: // Inherited via IInputProvider virtual bool SetInput(BaseControlDevice* device) override; -}; \ No newline at end of file +}; diff --git a/Libretro/Makefile.common b/Libretro/Makefile.common index 6a323036..01c0d3ed 100644 --- a/Libretro/Makefile.common +++ b/Libretro/Makefile.common @@ -28,7 +28,6 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/BaseVideoFilter.cpp \ $(CORE_DIR)/BatteryManager.cpp \ $(CORE_DIR)/BisqwitNtscFilter.cpp \ - $(CORE_DIR)/BizhawkMovie.cpp \ $(CORE_DIR)/Breakpoint.cpp \ $(CORE_DIR)/CheatManager.cpp \ $(CORE_DIR)/CodeDataLogger.cpp \ @@ -46,22 +45,15 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/EmulationSettings.cpp \ $(CORE_DIR)/EventManager.cpp \ $(CORE_DIR)/ExpressionEvaluator.cpp \ - $(CORE_DIR)/FceuxMovie.cpp \ $(CORE_DIR)/FDS.cpp \ $(CORE_DIR)/FdsLoader.cpp \ - $(CORE_DIR)/GameClient.cpp \ - $(CORE_DIR)/GameClientConnection.cpp \ - $(CORE_DIR)/GameConnection.cpp \ $(CORE_DIR)/GameDatabase.cpp \ - $(CORE_DIR)/GameServer.cpp \ - $(CORE_DIR)/GameServerConnection.cpp \ $(CORE_DIR)/HdAudioDevice.cpp \ $(CORE_DIR)/HdNesPack.cpp \ $(CORE_DIR)/HdPackBuilder.cpp \ $(CORE_DIR)/HdPackLoader.cpp \ $(CORE_DIR)/HdPpu.cpp \ $(CORE_DIR)/HdVideoFilter.cpp \ - $(CORE_DIR)/HistoryViewer.cpp \ $(CORE_DIR)/iNesLoader.cpp \ $(CORE_DIR)/KeyManager.cpp \ $(CORE_DIR)/LabelManager.cpp \ @@ -69,10 +61,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/MemoryAccessCounter.cpp \ $(CORE_DIR)/MemoryDumper.cpp \ $(CORE_DIR)/MemoryManager.cpp \ - $(CORE_DIR)/MesenMovie.cpp \ $(CORE_DIR)/MessageManager.cpp \ - $(CORE_DIR)/MovieManager.cpp \ - $(CORE_DIR)/MovieRecorder.cpp \ $(CORE_DIR)/NESHeader.cpp \ $(CORE_DIR)/NotificationManager.cpp \ $(CORE_DIR)/NsfLoader.cpp \ @@ -83,8 +72,6 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/OggReader.cpp \ $(CORE_DIR)/PPU.cpp \ $(CORE_DIR)/ReverbFilter.cpp \ - $(CORE_DIR)/RewindData.cpp \ - $(CORE_DIR)/RewindManager.cpp \ $(CORE_DIR)/RomLoader.cpp \ $(CORE_DIR)/RotateFilter.cpp \ $(CORE_DIR)/SaveStateManager.cpp \