diff --git a/pcsx2/Recording/InputRecording.cpp b/pcsx2/Recording/InputRecording.cpp index f2ee85ece9..b255915372 100644 --- a/pcsx2/Recording/InputRecording.cpp +++ b/pcsx2/Recording/InputRecording.cpp @@ -1,6 +1,7 @@ #include "PrecompiledHeader.h" #include "AppSaveStates.h" +#include "AppGameDatabase.h" #include "Common.h" #include "Counters.h" #include "MemoryTypes.h" @@ -117,54 +118,73 @@ void InputRecording::Stop() { //---------------------------------- // start //---------------------------------- -void InputRecording::Start(wxString FileName,bool fReadOnly, VmStateBuffer* ss) +void InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName) { g_RecordingControls.Pause(); Stop(); - if (fReadOnly) + // create + if (!InputRecordingData.Open(FileName, true, fromSaveState)) { + return; + } + // Set author name + if (!authorName.IsEmpty()) { - if (!InputRecordingData.Open(FileName, false)) { - return; - } - if (!InputRecordingData.readHeaderAndCheck()) { - recordingConLog(L"[REC]: This file is not a correct InputRecording file.\n"); - InputRecordingData.Close(); - return; - } - // cdrom - if (!g_Conf->CurrentIso.IsEmpty()) + InputRecordingData.getHeader().setAuthor(authorName); + } + // Set Game Name + // Code loosely taken from AppCoreThread.cpp to resolve the Game Name + // Fallback is ISO name + wxString gameName; + const wxString gameKey(SysGetDiscID()); + if (!gameKey.IsEmpty()) + { + if (IGameDatabase* GameDB = AppHost_GetGameDatabase()) { - if (Path::GetFilename(g_Conf->CurrentIso) != InputRecordingData.getHeader().cdrom) { - recordingConLog(L"[REC]: Information on CD in Movie file is Different.\n"); + Game_Data game; + if (GameDB->findGame(game, gameKey)) + { + gameName = game.getString("Name"); + gameName += L" (" + game.getString("Region") + L")"; } } - state = REPLAY; - recordingConLog(wxString::Format(L"[REC]: Replaying movie - [%s]\n",FileName)); - recordingConLog(wxString::Format(L"MaxFrame: %d\n", InputRecordingData.getMaxFrame())); - recordingConLog(wxString::Format(L"UndoCount: %d\n", InputRecordingData.getUndoCount())); } - else - { - // create - if (!InputRecordingData.Open(FileName, true, ss)) { - return; - } - // cdrom - if (!g_Conf->CurrentIso.IsEmpty()) - { - InputRecordingData.getHeader().setCdrom(Path::GetFilename(g_Conf->CurrentIso)); - } - InputRecordingData.writeHeader(); - InputRecordingData.writeSavestate(); + InputRecordingData.getHeader().setGameName(!gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso)); + InputRecordingData.writeHeader(); + state = RECORD; + recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName)); - state = RECORD; - recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName)); - } // In every case, we reset the g_FrameCount g_FrameCount = 0; } +void InputRecording::Play(wxString FileName, bool fromSaveState) +{ + g_RecordingControls.Pause(); + Stop(); + + if (!InputRecordingData.Open(FileName, false, false)) { + return; + } + if (!InputRecordingData.readHeaderAndCheck()) { + recordingConLog(L"[REC]: This file is not a correct InputRecording file.\n"); + InputRecordingData.Close(); + return; + } + // Check author name + if (!g_Conf->CurrentIso.IsEmpty()) + { + if (Path::GetFilename(g_Conf->CurrentIso) != InputRecordingData.getHeader().gameName) { + recordingConLog(L"[REC]: Information on CD in Movie file is Different.\n"); + } + } + // TODO - probably output more informatiion on it + state = REPLAY; + recordingConLog(wxString::Format(L"[REC]: Replaying movie - [%s]\n", FileName)); + recordingConLog(wxString::Format(L"MaxFrame: %d\n", InputRecordingData.getMaxFrame())); + recordingConLog(wxString::Format(L"UndoCount: %d\n", InputRecordingData.getUndoCount())); +} + //---------------------------------- // shortcut key //---------------------------------- diff --git a/pcsx2/Recording/InputRecording.h b/pcsx2/Recording/InputRecording.h index e6afe1cf06..2b8e2d0872 100644 --- a/pcsx2/Recording/InputRecording.h +++ b/pcsx2/Recording/InputRecording.h @@ -16,7 +16,8 @@ public: // menu bar void Stop(); - void Start(wxString filename, bool fReadOnly, VmStateBuffer* ss = nullptr); + void Create(wxString filename, bool fromSaveState, wxString authorName); + void Play(wxString filename, bool fromSaveState); // shortcut key void RecordModeToggle(); diff --git a/pcsx2/Recording/InputRecordingFile.cpp b/pcsx2/Recording/InputRecordingFile.cpp index cdc0bf0598..3d9a5ce8a1 100644 --- a/pcsx2/Recording/InputRecordingFile.cpp +++ b/pcsx2/Recording/InputRecordingFile.cpp @@ -1,14 +1,15 @@ #include "PrecompiledHeader.h" -#include "MemoryTypes.h" #include "App.h" #include "Common.h" #include "Counters.h" +#include "MainFrame.h" +#include "MemoryTypes.h" #include "InputRecordingFile.h" #define HEADER_SIZE (sizeof(InputRecordingHeader)+4+4) -#define SAVESTATE_HEADER_SIZE (sizeof(bool) + sizeof(savestate.savestatesize) + sizeof(savestate.savestate[0]) * savestate.savestatesize) +#define SAVESTATE_HEADER_SIZE (sizeof(bool)) #define BLOCK_HEADER_SIZE (0) #define BLOCK_DATA_SIZE (18*2) #define BLOCK_SIZE (BLOCK_HEADER_SIZE+BLOCK_DATA_SIZE) @@ -29,10 +30,8 @@ long InputRecordingFile::_getBlockSeekPoint(const long & frame) } } -//---------------------------------- -// file -//---------------------------------- -bool InputRecordingFile::Open(const wxString path, bool fNewOpen, VmStateBuffer *ss) +// Inits the new (or existing) input recording file +bool InputRecordingFile::Open(const wxString path, bool fNewOpen, bool fromSaveState) { Close(); wxString mode = L"rb+"; @@ -50,14 +49,13 @@ bool InputRecordingFile::Open(const wxString path, bool fNewOpen, VmStateBuffer } filename = path; + // TODO - from power on its fine + // problems seem to be be based in how we are saving the savestate if (fNewOpen) { - if (ss) { + if (fromSaveState) { savestate.fromSavestate = true; - savestate.savestatesize = ss->GetLength(); - savestate.savestate.MakeRoomFor(ss->GetLength()); - for (size_t i = 0; i < ss->GetLength(); i++) { - savestate.savestate[i] = (*ss)[i]; - } + // TODO - Check if existing, if so rename + StateCopy_SaveToFile(path + "_SaveState.p2s"); } else { sApp.SysExecute(); @@ -65,17 +63,28 @@ bool InputRecordingFile::Open(const wxString path, bool fNewOpen, VmStateBuffer } return true; } + bool InputRecordingFile::Close() { if (recordingFile == NULL)return false; writeHeader(); - writeSavestate(); + writeSaveState(); fclose(recordingFile); recordingFile = NULL; filename = ""; return true; } +bool InputRecordingFile::writeSaveState() { + if (recordingFile == NULL) + { + return false; + } + fseek(recordingFile, SEEKPOINT_SAVESTATE, SEEK_SET); + if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1) return false; + return true; +} + //---------------------------------- // write frame //---------------------------------- @@ -111,9 +120,6 @@ bool InputRecordingFile::readKeyBuf(u8 & result,const uint & frame, const uint p return true; } - - - //=================================== // pad //=================================== @@ -126,6 +132,7 @@ void InputRecordingFile::getPadData(PadData & result, unsigned long frame) if (fread(result.buf, 1, BLOCK_DATA_SIZE, recordingFile) == 0)return; result.fExistKey = true; } + bool InputRecordingFile::DeletePadData(unsigned long frame) { if (recordingFile == NULL)return false; @@ -147,6 +154,7 @@ bool InputRecordingFile::DeletePadData(unsigned long frame) return true; } + bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key) { if (recordingFile == NULL)return false; @@ -174,88 +182,53 @@ bool InputRecordingFile::InsertPadData(unsigned long frame, const PadData& key) return true; } + bool InputRecordingFile::UpdatePadData(unsigned long frame, const PadData& key) { - if (recordingFile == NULL)return false; - if (!key.fExistKey)return false; + if (recordingFile == NULL) return false; + if (!key.fExistKey) return false; long seek = _getBlockSeekPoint(frame) + BLOCK_HEADER_SIZE; fseek(recordingFile, seek, SEEK_SET); - if (fwrite(key.buf, 1, BLOCK_DATA_SIZE, recordingFile) == 0)return false; + if (fwrite(key.buf, 1, BLOCK_DATA_SIZE, recordingFile) == 0) return false; fflush(recordingFile); return true; } - - - -//=================================== -// header -//=================================== +// TODO - see if we can get the actual game name, not just the ISO name +// Verify header of recording file bool InputRecordingFile::readHeaderAndCheck() { - if (recordingFile == NULL)return false; + if (recordingFile == NULL) return false; rewind(recordingFile); - if (fread(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1)return false; - if (fread(&MaxFrame, 4, 1, recordingFile) != 1)return false; - if (fread(&UndoCount, 4, 1, recordingFile) != 1)return false; + if (fread(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1) return false; + if (fread(&MaxFrame, 4, 1, recordingFile) != 1) return false; + if (fread(&UndoCount, 4, 1, recordingFile) != 1) return false; if (fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1) return false; if (savestate.fromSavestate) { - // We read the size (and the savestate) only if we must - if (fread(&savestate.savestatesize, sizeof(savestate.savestatesize), 1, recordingFile) != 1) return false; - if (savestate.savestatesize == 0) { - recordingConLog(L"[REC]: Invalid size of the savestate.\n"); - return false; - } - - savestate.savestate.MakeRoomFor(savestate.savestatesize); - // We read "savestatesize" * the size of a cell - if (fread(savestate.savestate.GetPtr(), sizeof(savestate.savestate[0]), savestate.savestatesize, recordingFile) - != savestate.savestatesize) return false; - - // We load the savestate - memLoadingState load(savestate.savestate); - UI_DisableSysActions(); - GetCoreThread().Pause(); - SysClearExecutionCache(); - load.FreezeAll(); - GetCoreThread().Resume(); + // TODO - check to see if the file is there, if it AINT, return false, throw an error, ETC (SAY WHAT FILE WE ARE LOOKING FOR) + StateCopy_LoadFromFile(filename + "_SaveState.p2s"); } else { sApp.SysExecute(); } - // ID - if (header.ID != 0xCC) { - return false; - } - // ver - if (header.version != 3) { + // Check for current verison + // TODO - more specific log if fails for this reason + if (header.version != 1) { return false; } return true; } bool InputRecordingFile::writeHeader() { - if (recordingFile == NULL)return false; + if (recordingFile == NULL) return false; rewind(recordingFile); if (fwrite(&header, sizeof(InputRecordingHeader), 1, recordingFile) != 1) return false; return true; } -bool InputRecordingFile::writeSavestate() -{ - if (recordingFile == NULL) return false; - fseek(recordingFile, SEEKPOINT_SAVESTATE, SEEK_SET); - if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1) return false; - if (savestate.fromSavestate) { - if (fwrite(&savestate.savestatesize, sizeof(savestate.savestatesize), 1, recordingFile) != 1) return false; - if (fwrite(savestate.savestate.GetPtr(), sizeof(savestate.savestate[0]), savestate.savestatesize, recordingFile) - != savestate.savestatesize) return false; - } - return true; -} bool InputRecordingFile::writeMaxFrame() { if (recordingFile == NULL)return false; @@ -263,6 +236,7 @@ bool InputRecordingFile::writeMaxFrame() if (fwrite(&MaxFrame, 4, 1, recordingFile) != 1) return false; return true; } + void InputRecordingFile::updateFrameMax(unsigned long frame) { if (MaxFrame >= frame) { @@ -273,13 +247,13 @@ void InputRecordingFile::updateFrameMax(unsigned long frame) fseek(recordingFile, SEEKPOINT_FRAMEMAX, SEEK_SET); fwrite(&MaxFrame, 4, 1, recordingFile); } + void InputRecordingFile::addUndoCount() { UndoCount++; if (recordingFile == NULL)return; fseek(recordingFile, SEEKPOINT_UNDOCOUNT, SEEK_SET); fwrite(&UndoCount, 4, 1, recordingFile); - } void InputRecordingHeader::setAuthor(wxString _author) @@ -288,14 +262,16 @@ void InputRecordingHeader::setAuthor(wxString _author) strncpy(author, _author.c_str(), max); author[max] = 0; } -void InputRecordingHeader::setCdrom(wxString _cdrom) + +void InputRecordingHeader::setGameName(wxString _gameName) { - int max = ArraySize(cdrom) - 1; - strncpy(cdrom, _cdrom.c_str(), max); - cdrom[max] = 0; + int max = ArraySize(gameName) - 1; + strncpy(gameName, _gameName.c_str(), max); + gameName[max] = 0; } + void InputRecordingHeader::init() { memset(author, 0, ArraySize(author)); - memset(cdrom, 0, ArraySize(cdrom)); + memset(gameName, 0, ArraySize(gameName)); } diff --git a/pcsx2/Recording/InputRecordingFile.h b/pcsx2/Recording/InputRecordingFile.h index eed27974b8..908a711294 100644 --- a/pcsx2/Recording/InputRecordingFile.h +++ b/pcsx2/Recording/InputRecordingFile.h @@ -5,87 +5,65 @@ struct InputRecordingHeader { - u8 version = 3; - u8 ID = 0xCC; - - char emu[50] = "pcsx2-1.5.X"; - char author[50] = ""; - char cdrom[50] = ""; + u8 version = 1; + char emu[50] = "PCSX2-1.5.X"; + char author[255] = ""; + char gameName[255] = ""; public: void setAuthor(wxString author); - void setCdrom(wxString cdrom); + void setGameName(wxString cdrom); void init(); }; -//---------------------------- -// InputRecordingSavestate // Contains info about the starting point of the movie -//---------------------------- struct InputRecordingSavestate { - bool fromSavestate = false; // Whether we start from the savestate or from power-on - unsigned int savestatesize; // The size of the savestate - VmStateBuffer savestate; // The savestate + // Whether we start from the savestate or from power-on + bool fromSavestate = false; }; -//---------------------------- -// InputRecordingFile -//---------------------------- + class InputRecordingFile { public: InputRecordingFile() {} ~InputRecordingFile() { Close(); } -public: - // file - bool Open(const wxString fn, bool fNewOpen, VmStateBuffer *ss = nullptr); + // Movie File Manipulation + bool Open(const wxString fn, bool fNewOpen, bool fromSaveState); bool Close(); - - // movie bool writeKeyBuf(const uint & frame, const uint port, const uint bufIndex, const u8 & buf); bool readKeyBuf(u8 & result, const uint & frame, const uint port, const uint bufIndex); - // pad data + // Controller Data void getPadData(PadData & result_pad, unsigned long frame); bool DeletePadData(unsigned long frame); bool InsertPadData(unsigned long frame, const PadData& key); bool UpdatePadData(unsigned long frame, const PadData& key); -private: - FILE * recordingFile = NULL; - wxString filename = ""; - -private: - - //-------------------- - // block - //-------------------- - long _getBlockSeekPoint(const long & frame); - - -public: - //-------------------- - // header - //-------------------- + // Header InputRecordingHeader& getHeader() { return header; } unsigned long& getMaxFrame() { return MaxFrame; } unsigned long& getUndoCount() { return UndoCount; } const wxString & getFilename() { return filename; } bool writeHeader(); - bool writeSavestate(); bool writeMaxFrame(); + bool writeSaveState(); bool readHeaderAndCheck(); void updateFrameMax(unsigned long frame); void addUndoCount(); private: + // Movie File + FILE * recordingFile = NULL; + wxString filename = ""; + long _getBlockSeekPoint(const long & frame); + + // Header InputRecordingHeader header; InputRecordingSavestate savestate; unsigned long MaxFrame = 0; unsigned long UndoCount = 0; - - }; diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index ad165278f9..f5abce9f34 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -788,7 +788,6 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event) { return; } - g_InputRecordingHeader.setAuthor(NewRecordingFrame->getAuthor()); // From Current Frame if (NewRecordingFrame->getFrom() == 0) { @@ -796,16 +795,13 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event) recordingConLog(L"[REC]: Game is not open, aborting new input recording.\n"); return; } - VmStateBuffer savestate; - memSavingState memSS(savestate); - memSS.FreezeAll(); - g_InputRecording.Start(NewRecordingFrame->getFile(), false, &savestate); + g_InputRecording.Create(NewRecordingFrame->getFile(), true, NewRecordingFrame->getAuthor()); } // From Power-On else if (NewRecordingFrame->getFrom() == 1) { // TODO extensively test this - g_InputRecording.Start(NewRecordingFrame->getFile(), false); + g_InputRecording.Create(NewRecordingFrame->getFile(), false, NewRecordingFrame->getAuthor()); } } m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false); @@ -815,12 +811,12 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event) { g_InputRecording.Stop(); - wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"", L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN); - if (openFileDialog.ShowModal() == wxID_CANCEL)return; // cancel + if (openFileDialog.ShowModal() == wxID_CANCEL) return; + wxString path = openFileDialog.GetPath(); - g_InputRecording.Start(path, true); + g_InputRecording.Play(path, true); m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false); m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true); }