Files
archived-pcsx2/pcsx2/Recording/InputRecording.cpp
Tyler Wilding 08d923ca6f recording: Append copyright headers
Squashed commits:

[47be08613] recording: Forgot to refactor the usage of std::size
2019-04-21 00:45:44 +02:00

221 lines
6.0 KiB
C++

/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2019 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "AppSaveStates.h"
#include "AppGameDatabase.h"
#include "Common.h"
#include "Counters.h"
#include "MemoryTypes.h"
#include "SaveState.h"
#include "Recording/RecordingControls.h"
#include "InputRecording.h"
#include <vector>
InputRecording g_InputRecording;
// --------------------------------
// Tag and save framecount along with savestate
// --------------------------------
void SaveStateBase::InputRecordingFreeze()
{
FreezeTag("InputRecording");
Freeze(g_FrameCount);
if (IsLoading()) {
g_InputRecordingData.addUndoCount();
}
}
//----------------------------------
// Main func for handling controller input data
// Called by Sio.cpp::sioWriteController
//----------------------------------
void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 & bufCount, u8 buf[])
{
// TODO - Multi-Tap Support
// Only examine controllers 1 / 2
if (port < 0 || 1 < port)
return;
//==========================
// This appears to try to ensure that we are only paying attention
// to the frames that matter, the ones that are reading from
// the controller.
//
// See - Lilypad.cpp:1254
// 0x42 is the magic number for the default read query
//
// NOTE: this appears to break if you have logging enabled in LilyPad's config!
//==========================
if (bufCount == 1) {
if (data == 0x42)
{
fInterruptFrame = true;
}
else {
fInterruptFrame = false;
return;
}
}
else if ( bufCount == 2 ) {
// See - LilyPad.cpp:1255
// 0x5A is always the second byte in the buffer
// when the normal READ_DATA_AND_VIBRRATE (0x42)
// query is executed, this looks like a sanity check
if (buf[bufCount] != 0x5A) {
fInterruptFrame = false;
return;
}
}
if (!fInterruptFrame)
return;
if (state == NONE)
return;
// We do not want to record or save the first two
// bytes in the data returned from LilyPad
if (bufCount < 3)
return;
//---------------
// Read or Write
//---------------
const u8 &nowBuf = buf[bufCount];
if (state == RECORD)
{
InputRecordingData.updateFrameMax(g_FrameCount);
InputRecordingData.writeKeyBuf(g_FrameCount, port, bufCount - 3, nowBuf);
}
else if (state == REPLAY)
{
if (InputRecordingData.getMaxFrame() <= g_FrameCount)
{
// Pause the emulation but the movie is not closed
g_RecordingControls.Pause();
return;
}
u8 tmp = 0;
if (InputRecordingData.readKeyBuf(tmp, g_FrameCount, port, bufCount - 3)) {
buf[bufCount] = tmp;
}
}
}
//----------------------------------
// stop
//----------------------------------
void InputRecording::Stop() {
state = NONE;
if (InputRecordingData.Close()) {
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
}
}
//----------------------------------
// start
//----------------------------------
void InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
{
g_RecordingControls.Pause();
Stop();
// create
if (!InputRecordingData.Open(FileName, true, fromSaveState)) {
return;
}
// Set author name
if (!authorName.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())
{
Game_Data game;
if (GameDB->findGame(game, gameKey))
{
gameName = game.getString("Name");
gameName += L" (" + game.getString("Region") + L")";
}
}
}
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));
// 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");
}
}
state = REPLAY;
recordingConLog(wxString::Format(L"[REC]: Replaying movie - [%s]\n", FileName));
recordingConLog(wxString::Format(L"Recording File Version: %d\n", InputRecordingData.getHeader().version));
recordingConLog(wxString::Format(L"Associated Game Name / ISO Filename: %s\n", InputRecordingData.getHeader().gameName));
recordingConLog(wxString::Format(L"Author: %s\n", InputRecordingData.getHeader().author));
recordingConLog(wxString::Format(L"MaxFrame: %d\n", InputRecordingData.getMaxFrame()));
recordingConLog(wxString::Format(L"UndoCount: %d\n", InputRecordingData.getUndoCount()));
}
//----------------------------------
// shortcut key
//----------------------------------
void InputRecording::RecordModeToggle()
{
if (state == REPLAY) {
state = RECORD;
recordingConLog("[REC]: Record mode ON.\n");
}
else if (state == RECORD) {
state = REPLAY;
recordingConLog("[REC]: Replay mode ON.\n");
}
}