input-rec: refactor core code, freeze wxWidgets version

This commit is contained in:
Tyler Wilding 2022-04-03 20:07:29 -04:00 committed by Tyler Wilding
parent 2e8076d909
commit 9aecf79d7f
18 changed files with 1193 additions and 91 deletions

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,13 +15,14 @@
#include "PrecompiledHeader.h"
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
#include "common/StringUtil.h"
#include "SaveState.h"
#include "Counters.h"
#include "SaveState.h"
#ifndef DISABLE_RECORDING
#include "gui/App.h"
#include "gui/AppSaveStates.h"
#include "DebugTools/Debug.h"
@ -31,12 +32,8 @@
#include "InputRecordingControls.h"
#include "Utilities/InputRecordingLogger.h"
#include "gui/AppSaveStates.h"
#include <fmt/format.h>
#endif
void SaveStateBase::InputRecordingFreeze()
{
// NOTE - BE CAREFUL
@ -44,7 +41,6 @@ void SaveStateBase::InputRecordingFreeze()
FreezeTag("InputRecording");
Freeze(g_FrameCount);
#ifndef DISABLE_RECORDING
if (g_Conf->EmuOptions.EnableRecordingTools)
{
// Loading a save-state is an asynchronous task. If we are playing a recording
@ -55,11 +51,8 @@ void SaveStateBase::InputRecordingFreeze()
else if (g_InputRecording.IsActive() && IsLoading())
g_InputRecording.SetFrameCounter(g_FrameCount);
}
#endif
}
#ifndef DISABLE_RECORDING
InputRecording g_InputRecording;
InputRecording::InputRecordingPad::InputRecordingPad()
@ -124,7 +117,7 @@ void InputRecording::ControllerInterrupt(u8& data, u8& port, u16& bufCount, u8 b
// Update controller data state for future VirtualPad / logging usage.
pads[port].padData->UpdateControllerData(bufIndex, bufVal);
if (pads[port].virtualPad->IsShown())
pads[port].virtualPad->UpdateControllerData(bufIndex, pads[port].padData);
}
@ -308,12 +301,12 @@ void InputRecording::SetupInitialState(u32 newStartingFrame)
incrementUndo = true;
inputRec::log("Replaying input recording");
inputRec::consoleMultiLog({fmt::format("File: {}", inputRecordingData.GetFilename().ToUTF8()),
fmt::format("PCSX2 Version Used: {}", std::string(inputRecordingData.GetHeader().emu)),
fmt::format("Recording File Version: {}", inputRecordingData.GetHeader().version),
fmt::format("Associated Game Name or ISO Filename: {}", std::string(inputRecordingData.GetHeader().gameName)),
fmt::format("Author: {}", inputRecordingData.GetHeader().author),
fmt::format("Total Frames: {}", inputRecordingData.GetTotalFrames()),
fmt::format("Undo Count: {}", inputRecordingData.GetUndoCount())});
fmt::format("PCSX2 Version Used: {}", std::string(inputRecordingData.GetHeader().emu)),
fmt::format("Recording File Version: {}", inputRecordingData.GetHeader().version),
fmt::format("Associated Game Name or ISO Filename: {}", std::string(inputRecordingData.GetHeader().gameName)),
fmt::format("Author: {}", inputRecordingData.GetHeader().author),
fmt::format("Total Frames: {}", inputRecordingData.GetTotalFrames()),
fmt::format("Undo Count: {}", inputRecordingData.GetUndoCount())});
SetToReplayMode();
}
@ -394,7 +387,7 @@ bool InputRecording::Play(wxWindow* parent, wxString filename)
if (!wxFileExists(savestate))
{
wxFileDialog loadStateDialog(parent, _("Select the savestate that will accompany this recording"), L"", L"",
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
if (loadStateDialog.ShowModal() == wxID_CANCEL)
{
inputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}", savestate.ToUTF8()));
@ -432,7 +425,7 @@ void InputRecording::GoToFirstFrame(wxWindow* parent)
inputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}\n", savestate.ToUTF8()));
wxFileDialog loadStateDialog(parent, _("Select a savestate to accompany the recording with"), L"", L"",
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
int result = loadStateDialog.ShowModal();
if (!initiallyPaused)
g_InputRecordingControls.Resume();
@ -443,7 +436,7 @@ void InputRecording::GoToFirstFrame(wxWindow* parent)
return;
}
savestate = loadStateDialog.GetPath();
inputRec::consoleLog(fmt::format ("Base savestate swapped to {}", savestate.ToUTF8()));
inputRec::consoleLog(fmt::format("Base savestate swapped to {}", savestate.ToUTF8()));
}
StateCopy_LoadFromFile(savestate);
}
@ -470,4 +463,365 @@ wxString InputRecording::resolveGameName()
return !gameName.empty() ? StringUtil::UTF8StringToWxString(gameName) : Path::GetFilename(g_Conf->CurrentIso);
}
#endif
#else
#include "common/StringUtil.h"
#include "SaveState.h"
#include "Counters.h"
#include "SaveState.h"
#include "VMManager.h"
#include "DebugTools/Debug.h"
#include "GameDatabase.h"
#include "InputRecording.h"
#include "InputRecordingControls.h"
#include "Utilities/InputRecordingLogger.h"
#include <fmt/format.h>
void SaveStateBase::InputRecordingFreeze()
{
// NOTE - BE CAREFUL
// CHANGING THIS WILL BREAK BACKWARDS COMPATIBILITY ON SAVESTATES
FreezeTag("InputRecording");
Freeze(g_FrameCount);
// Loading a save-state is an asynchronous task. If we are playing a recording
// that starts from a savestate (not power-on) and the starting (pcsx2 internal) frame
// marker has not been set (which comes from the save-state), we initialize it.
if (g_InputRecording.IsInitialLoad())
g_InputRecording.SetupInitialState(g_FrameCount);
else if (g_InputRecording.IsActive() && IsLoading())
g_InputRecording.SetFrameCounter(g_FrameCount);
}
InputRecording g_InputRecording;
InputRecording::InputRecordingPad::InputRecordingPad()
{
padData = new PadData;
}
InputRecording::InputRecordingPad::~InputRecordingPad()
{
delete padData;
}
void InputRecording::RecordingReset()
{
// Booting is an asynchronous task. If we are playing a recording
// that starts from power-on and the starting (pcsx2 internal) frame
// marker has not been set, we initialize it.
if (g_InputRecording.IsInitialLoad())
g_InputRecording.SetupInitialState(0);
else if (g_InputRecording.IsActive())
{
g_InputRecording.SetFrameCounter(0);
g_InputRecordingControls.Lock(0);
}
else
g_InputRecordingControls.Resume();
}
void InputRecording::ControllerInterrupt(u8& data, u8& port, u16& bufCount, u8 buf[])
{
// TODO - Multi-Tap Support
if (bufCount == 1)
fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE;
else if (bufCount == 2)
{
if (buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE)
fInterruptFrame = false;
}
else if (fInterruptFrame)
{
u8& bufVal = buf[bufCount];
const u16 bufIndex = bufCount - 3;
if (state == InputRecordingMode::Replaying)
{
if (frameCounter >= 0 && frameCounter < INT_MAX)
{
if (!inputRecordingData.ReadKeyBuffer(bufVal, frameCounter, port, bufIndex))
inputRec::consoleLog(fmt::format("Failed to read input data at frame {}", frameCounter));
// Update controller data state for future VirtualPad / logging usage.
pads[port].padData->UpdateControllerData(bufIndex, bufVal);
}
}
else
{
// Update controller data state for future VirtualPad / logging usage.
pads[port].padData->UpdateControllerData(bufIndex, bufVal);
// Commit the byte to the movie file if we are recording
if (state == InputRecordingMode::Recording)
{
if (frameCounter >= 0)
{
if (incrementUndo)
{
inputRecordingData.IncrementUndoCount();
incrementUndo = false;
}
if (frameCounter < INT_MAX && !inputRecordingData.WriteKeyBuffer(frameCounter, port, bufIndex, bufVal))
inputRec::consoleLog(fmt::format("Failed to write input data at frame {}", frameCounter));
}
}
}
}
}
s32 InputRecording::GetFrameCounter()
{
return frameCounter;
}
InputRecordingFile& InputRecording::GetInputRecordingData()
{
return inputRecordingData;
}
u32 InputRecording::GetStartingFrame()
{
return startingFrame;
}
void InputRecording::IncrementFrameCounter()
{
if (frameCounter < INT_MAX)
{
frameCounter++;
switch (state)
{
case InputRecordingMode::Recording:
inputRecordingData.SetTotalFrames(frameCounter);
[[fallthrough]];
case InputRecordingMode::Replaying:
if (frameCounter == inputRecordingData.GetTotalFrames())
incrementUndo = false;
}
}
}
void InputRecording::LogAndRedraw()
{
for (u8 port = 0; port < 2; port++)
{
pads[port].padData->LogPadData(port);
}
}
bool InputRecording::IsInterruptFrame()
{
return fInterruptFrame;
}
bool InputRecording::IsActive()
{
return state != InputRecordingMode::NotActive;
}
bool InputRecording::IsInitialLoad()
{
return initialLoad;
}
bool InputRecording::IsReplaying()
{
return state == InputRecordingMode::Replaying;
}
bool InputRecording::IsRecording()
{
return state == InputRecordingMode::Recording;
}
void InputRecording::SetToRecordMode()
{
state = InputRecordingMode::Recording;
inputRec::log("Record mode ON");
}
void InputRecording::SetToReplayMode()
{
state = InputRecordingMode::Replaying;
inputRec::log("Replay mode ON");
}
void InputRecording::SetFrameCounter(u32 newGFrameCount)
{
if (newGFrameCount > startingFrame + (u32)inputRecordingData.GetTotalFrames())
{
inputRec::consoleLog("Warning, you've loaded PCSX2 emulation to a point after the end of the original recording. This should be avoided.");
inputRec::consoleLog("Savestate's framecount has been ignored.");
frameCounter = inputRecordingData.GetTotalFrames();
if (state == InputRecordingMode::Replaying)
SetToRecordMode();
incrementUndo = false;
}
else
{
if (newGFrameCount < startingFrame)
{
inputRec::consoleLog("Warning, you've loaded PCSX2 emulation to a point before the start of the original recording. This should be avoided.");
if (state == InputRecordingMode::Recording)
SetToReplayMode();
}
else if (newGFrameCount == 0 && state == InputRecordingMode::Recording)
SetToReplayMode();
frameCounter = newGFrameCount - (s32)startingFrame;
incrementUndo = true;
}
}
void InputRecording::SetupInitialState(u32 newStartingFrame)
{
startingFrame = newStartingFrame;
if (state != InputRecordingMode::Replaying)
{
inputRec::log("Started new input recording");
inputRec::consoleLog(fmt::format("Filename {}", inputRecordingData.GetFilename()));
SetToRecordMode();
}
else
{
// Check if the current game matches with the one used to make the original recording
// TODO - Vaser - this should be the CRC in hindsight anyway
if (!VMManager::GetDiscPath().empty())
if (resolveGameName() != inputRecordingData.GetHeader().gameName)
inputRec::consoleLog("Input recording was possibly constructed for a different game.");
incrementUndo = true;
inputRec::log("Replaying input recording");
inputRec::consoleMultiLog({fmt::format("File: {}", inputRecordingData.GetFilename()),
fmt::format("PCSX2 Version Used: {}", std::string(inputRecordingData.GetHeader().emu)),
fmt::format("Recording File Version: {}", inputRecordingData.GetHeader().version),
fmt::format("Associated Game Name or ISO Filename: {}", std::string(inputRecordingData.GetHeader().gameName)),
fmt::format("Author: {}", inputRecordingData.GetHeader().author),
fmt::format("Total Frames: {}", inputRecordingData.GetTotalFrames()),
fmt::format("Undo Count: {}", inputRecordingData.GetUndoCount())});
SetToReplayMode();
}
if (inputRecordingData.FromSaveState())
inputRec::consoleLog(fmt::format("Internal Starting Frame: {}", startingFrame));
frameCounter = 0;
initialLoad = false;
g_InputRecordingControls.Lock(startingFrame);
}
void InputRecording::FailedSavestate()
{
inputRec::consoleLog(fmt::format("{} is not compatible with this version of PCSX2", savestate));
inputRec::consoleLog(fmt::format("Original PCSX2 version used: {}", inputRecordingData.GetHeader().emu));
inputRecordingData.Close();
initialLoad = false;
state = InputRecordingMode::NotActive;
g_InputRecordingControls.Resume();
}
void InputRecording::Stop()
{
state = InputRecordingMode::NotActive;
incrementUndo = false;
if (inputRecordingData.Close())
inputRec::log("Input recording stopped");
}
bool InputRecording::Create(const std::string_view& fileName, const bool fromSaveState, const std::string_view& authorName)
{
if (!inputRecordingData.OpenNew(fileName, fromSaveState))
return false;
initialLoad = true;
state = InputRecordingMode::Recording;
if (fromSaveState)
{
savestate = fmt::format("{}_SaveState.p2s", fileName);
if (fs::exists(savestate))
{
fs::copy_file(savestate, fmt::format("{}.bak", savestate));
}
VMManager::SaveState(savestate.c_str());
}
else
{
// Vaser - CHECK - don't need to specify a source anymore? (cdvd/etc?)
VMManager::Execute();
}
// Set emulator version
inputRecordingData.GetHeader().SetEmulatorVersion();
// Set author name
if (!authorName.empty())
inputRecordingData.GetHeader().SetAuthor(authorName);
// Set Game Name
inputRecordingData.GetHeader().SetGameName(resolveGameName());
// Write header contents
inputRecordingData.WriteHeader();
return true;
}
bool InputRecording::Play(const fs::path& filename)
{
if (!inputRecordingData.OpenExisting(filename))
return false;
// Either load the savestate, or restart the game
if (inputRecordingData.FromSaveState())
{
// TODO - Vaser - VM State is atomic, be careful.
if (VMManager::GetState() != VMState::Running && VMManager::GetState() != VMState::Paused)
{
inputRec::consoleLog("Game is not open, aborting playing input recording which starts on a save-state.");
inputRecordingData.Close();
return false;
}
savestate = fmt::format("{}_SaveState.p2s", inputRecordingData.GetFilename());
if (!fs::exists(savestate))
{
inputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}", savestate));
inputRec::log("Savestate load failed");
inputRecordingData.Close();
return false;
}
state = InputRecordingMode::Replaying;
initialLoad = true;
VMManager::LoadState(savestate.c_str());
}
else
{
state = InputRecordingMode::Replaying;
initialLoad = true;
// Vaser - CHECK - don't need to specify a source anymore? (cdvd/etc?)
VMManager::Execute();
}
return true;
}
std::string InputRecording::resolveGameName()
{
std::string gameName;
// TODO - Vaser - there is probably a way to get rid of the wx usage here i imagine
const std::string gameKey(StringUtil::wxStringToUTF8String(SysGetDiscID()));
if (!gameKey.empty())
{
auto game = GameDatabase::findGame(gameKey);
if (game)
{
gameName = game->name;
gameName += " (" + game->region + ")";
}
}
// TODO - Vaser - there is probably a way to get rid of the wx usage here i imagine
return !gameName.empty() ? gameName : VMManager::GetGameName();
}
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,7 +15,8 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
#include "Recording/InputRecordingFile.h"
#include "Recording/VirtualPad/VirtualPad.h"
@ -145,4 +146,126 @@ private:
extern InputRecording g_InputRecording;
#endif
#else
#include "Recording/InputRecordingFile.h"
class InputRecording
{
public:
enum class Type
{
POWER_ON,
FROM_SAVESTATE
};
// Save or load PCSX2's global frame counter (g_FrameCount) along with each full/fast boot
//
// This is to prevent any inaccuracy issues caused by having a different
// internal emulation frame count than what it was at the beginning of the
// original recording
void RecordingReset();
// Main handler for ingesting input data and either saving it to the recording file (recording)
// or mutating it to the contents of the recording file (replaying)
void ControllerInterrupt(u8& data, u8& port, u16& BufCount, u8 buf[]);
// The running frame counter for the input recording
s32 GetFrameCounter();
InputRecordingFile& GetInputRecordingData();
// The internal PCSX2 g_FrameCount value on the first frame of the recording
u32 GetStartingFrame();
void IncrementFrameCounter();
// DEPRECATED: Slated for removal
// If the current frame contains controller / input data
bool IsInterruptFrame();
// If there is currently an input recording being played back or actively being recorded
bool IsActive();
// Whether or not the recording's initial state has yet to be loaded or saved and
// the rest of the recording can be initialized
// This is not applicable to recordings from a "power-on" state
bool IsInitialLoad();
// If there is currently an input recording being played back
bool IsReplaying();
// If there are inputs currently being recorded to a file
bool IsRecording();
// Sets input recording to Record Mode
void SetToRecordMode();
// Sets input recording to Replay Mode
void SetToReplayMode();
// Set the running frame counter for the input recording to an arbitrary value
void SetFrameCounter(u32 newGFrameCount);
// Sets up all values and prints console logs pertaining to the start of a recording
void SetupInitialState(u32 newStartingFrame);
/// Functions called from GUI
// Create a new input recording file
bool Create(const std::string_view& filename, const bool fromSaveState, const std::string_view& authorName);
// Play an existing input recording from a file
// TODO - Vaser - Calls a file dialog if it fails to locate the default base savestate
bool Play(const fs::path& path);
// Stop the active input recording
void Stop();
// Logs the padData and redraws the virtualPad windows of active pads
void LogAndRedraw();
// Resets a recording if the base savestate could not be loaded at the start
void FailedSavestate();
private:
enum class InputRecordingMode
{
NotActive,
Recording,
Replaying,
};
static const int CONTROLLER_PORT_ONE = 0;
static const int CONTROLLER_PORT_TWO = 1;
// 0x42 is the magic number to indicate the default controller read query
// See - PAD.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/master/pcsx2/PAD/Windows/PAD.cpp#L1255
static const u8 READ_DATA_AND_VIBRATE_FIRST_BYTE = 0x42;
// 0x5A is always the second byte in the buffer when the normal READ_DATA_AND_VIBRATE (0x42) query is executed.
// See - PAD.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/master/pcsx2/PAD/Windows/PAD.cpp#L1256
static const u8 READ_DATA_AND_VIBRATE_SECOND_BYTE = 0x5A;
// DEPRECATED: Slated for removal
bool fInterruptFrame = false;
InputRecordingFile inputRecordingData;
bool initialLoad = false;
u32 startingFrame = 0;
s32 frameCounter = 0;
bool incrementUndo = false;
InputRecordingMode state = InputRecording::InputRecordingMode::NotActive;
std::string savestate;
// Array of usable pads (currently, only 2)
struct InputRecordingPad
{
// Controller Data
PadData* padData;
InputRecordingPad();
~InputRecordingPad();
} pads[2];
// Resolve the name and region of the game currently loaded using the GameDB
// If the game cannot be found in the DB, the fallback is the ISO filename
std::string resolveGameName();
};
extern InputRecording g_InputRecording;
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,7 +15,8 @@
#include "PrecompiledHeader.h"
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
#include "Counters.h"
#include "DebugTools/Debug.h"
@ -46,7 +47,7 @@ void InputRecordingControls::CheckPauseStatus()
g_InputRecording.SetToReplayMode();
switchToReplay = false;
}
if (IsFinishedReplaying() || g_InputRecording.GetFrameCounter() == INT_MAX)
{
if (!pauseEmulation)
@ -200,7 +201,7 @@ void InputRecordingControls::Lock(u32 frame)
bool InputRecordingControls::IsFinishedReplaying() const
{
return g_InputRecording.IsReplaying() &&
g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames();
g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames();
}
void InputRecordingControls::StopCapture() const
@ -214,4 +215,209 @@ void InputRecordingControls::StopCapture() const
}
}
}
#endif
#else
#include "Counters.h"
#include "DebugTools/Debug.h"
#include "MemoryTypes.h"
#include "InputRecording.h"
#include "InputRecordingControls.h"
#include "Utilities/InputRecordingLogger.h"
#include "VMManager.h"
InputRecordingControls g_InputRecordingControls;
void InputRecordingControls::CheckPauseStatus()
{
frame_advance_frame_counter++;
if (frameAdvancing && frame_advance_frame_counter >= frames_per_frame_advance)
{
frameAdvancing = false;
pauseEmulation = true;
}
if (g_InputRecording.IsActive())
{
g_InputRecording.IncrementFrameCounter();
if (switchToReplay)
{
g_InputRecording.SetToReplayMode();
switchToReplay = false;
}
if (IsFinishedReplaying() || g_InputRecording.GetFrameCounter() == INT_MAX)
{
if (!pauseEmulation)
pauseEmulation = true;
StopCapture();
}
}
g_InputRecording.LogAndRedraw();
}
void InputRecordingControls::HandlePausingAndLocking()
{
// Explicit frame locking
if (frameLock)
{
if (g_FrameCount == frameLockTracker)
{
frameLock = false;
Resume();
}
else if (!emulationCurrentlyPaused && (VMManager::GetState() == VMState::Running || VMManager::GetState() != VMState::Paused))
{
emulationCurrentlyPaused = true;
VMManager::SetPaused(true);
}
}
else if (pauseEmulation && (VMManager::GetState() == VMState::Running || VMManager::GetState() != VMState::Paused))
{
emulationCurrentlyPaused = true;
VMManager::SetPaused(true);
}
}
void InputRecordingControls::ResumeCoreThreadIfStarted()
{
if (resumeEmulation && (VMManager::GetState() == VMState::Running || VMManager::GetState() == VMState::Paused))
{
VMManager::SetPaused(false);
resumeEmulation = false;
emulationCurrentlyPaused = false;
}
}
void InputRecordingControls::FrameAdvance()
{
if (!IsFinishedReplaying())
{
frameAdvancing = true;
frame_advance_frame_counter = 0;
Resume();
}
else
{
g_InputRecording.SetToRecordMode();
}
}
void InputRecordingControls::setFrameAdvanceAmount(int amount)
{
frames_per_frame_advance = amount;
}
bool InputRecordingControls::IsFrameAdvancing()
{
return frameAdvancing;
}
bool InputRecordingControls::IsPaused()
{
return emulationCurrentlyPaused && VMManager::GetState() == VMState::Paused;
}
void InputRecordingControls::Pause()
{
pauseEmulation = true;
resumeEmulation = false;
}
void InputRecordingControls::PauseImmediately()
{
if (VMManager::GetState() != VMState::Paused)
{
Pause();
if ((VMManager::GetState() == VMState::Running || VMManager::GetState() == VMState::Paused))
{
emulationCurrentlyPaused = true;
VMManager::SetPaused(true);
}
}
}
void InputRecordingControls::Resume()
{
if (!IsFinishedReplaying())
{
pauseEmulation = false;
resumeEmulation = true;
}
else
g_InputRecording.SetToRecordMode();
}
void InputRecordingControls::ResumeImmediately()
{
if (VMManager::GetState() == VMState::Paused)
{
Resume();
if ((VMManager::GetState() == VMState::Running || VMManager::GetState() == VMState::Paused))
{
emulationCurrentlyPaused = false;
VMManager::SetPaused(false);
}
}
}
void InputRecordingControls::TogglePause()
{
if (!pauseEmulation || !IsFinishedReplaying())
{
resumeEmulation = pauseEmulation;
pauseEmulation = !pauseEmulation;
inputRec::log(pauseEmulation ? "Paused Emulation" : "Resumed Emulation");
}
else
g_InputRecording.SetToRecordMode();
}
void InputRecordingControls::RecordModeToggle()
{
if (g_InputRecording.IsReplaying())
g_InputRecording.SetToRecordMode();
else if (g_InputRecording.IsRecording())
{
if (IsPaused() || g_InputRecording.GetFrameCounter() < g_InputRecording.GetInputRecordingData().GetTotalFrames())
g_InputRecording.SetToReplayMode();
else
switchToReplay = true;
}
}
void InputRecordingControls::Lock(u32 frame)
{
frameLock = true;
frameLockTracker = frame;
frameAdvancing = false;
// Ensures that g_frameCount can be used to resume emulation after a fast/full boot
if (!g_InputRecording.GetInputRecordingData().FromSaveState())
{
g_FrameCount = frame + 1;
}
}
bool InputRecordingControls::IsFinishedReplaying() const
{
return g_InputRecording.IsReplaying() &&
g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames();
}
void InputRecordingControls::StopCapture() const
{
// TODO - Vaser - Is capturing supported in Qt yet - Check
/*if (MainEmuFrame* mainFrame = GetMainFramePtr())
{
if (mainFrame->IsCapturing())
{
mainFrame->VideoCaptureToggle();
inputRec::log("Capture completed");
}
}*/
}
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,7 +15,8 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
class InputRecordingControls
{
@ -98,4 +99,87 @@ private:
extern InputRecordingControls g_InputRecordingControls;
#else
class InputRecordingControls
{
public:
// Intended to be called at the end of each frame, but will no-op if frame lock is active
//
// Will set the pausing parameters for emulation if:
// - The InputRecordingControls::FrameAdvance was hit on the previous frame
// - Emulation was explicitly paused using InputRecordingControls::TogglePause
// - We are replaying an input recording and have hit the end
void CheckPauseStatus();
// When loading a recording file or booting with a recording active, lock will be enabled.
// Emulation will be forced into and remain in a paused state until the transition in progress
// has completed - signaled when g_framecount and frameCountTracker are equal
//
// This function also handles actually pausing emulation when told to
void HandlePausingAndLocking();
// Called much more frequently than HandleFrameAdvanceAndPausing, instead of being per frame
// this hooks into pcsx2's main App event handler as it has to be able to resume emulation
// when drawing frames has compltely stopped
//
// Resumes emulation if:
// - CoreThread is currently open and paused
// - We've signaled emulation to be resumed via TogglePause or FrameAdvancing
void ResumeCoreThreadIfStarted();
// Resume emulation (incase the emulation is currently paused) and pause after a single frame has passed
void FrameAdvance();
void setFrameAdvanceAmount(int amount);
// Returns true if emulation is currently set up to frame advance.
bool IsFrameAdvancing();
// Returns true if the input recording has been paused, which can occur:
// - After a single frame has passed after InputRecordingControls::FrameAdvance
// - Explicitly paused via an InputRecordingControls function
bool IsPaused();
// Pause emulation at the next available Vsync
void Pause();
// Pause emulation immediately, not waiting for the next Vsync
void PauseImmediately();
// Resume emulation when the next pcsx2 App event is handled
void Resume();
/**
* @brief Resumes emulation immediately, don't wait until the next VSync
*/
void ResumeImmediately();
// Alternates emulation between a paused and unpaused state
void TogglePause();
// Switches between recording and replaying the active input recording file
void RecordModeToggle();
// Enables the frame locking mechanism so that when recordings are loaded
// or when processing a reboot with a recording active that no frames are
// lost in prior emulation
void Lock(u32 frame);
private:
// Indicates if the input recording controls have explicitly paused emulation or not
bool emulationCurrentlyPaused = false;
// Indicates on the next VSync if we are frame advancing, this value
// and should be cleared once a single frame has passed
bool frameAdvancing = false;
u32 frame_advance_frame_counter = 0;
u32 frames_per_frame_advance = 1;
// Indicates if we intend to call CoreThread.PauseSelf() on the current or next available vsync
bool pauseEmulation = false;
// Indicates if we intend to call CoreThread.Resume() when the next pcsx2 App event is handled
bool resumeEmulation = false;
// Indicates to switch to replay mode after the next vsync
bool switchToReplay = false;
// Used to stop recording frames from incrementing during a reset
bool frameLock = false;
// The frame value to use as the frame lock reset point
u32 frameLockTracker = 0;
bool IsFinishedReplaying() const;
// Calls mainEmuFrame's videoCaptureToggle to end a capture if active
void StopCapture() const;
};
extern InputRecordingControls g_InputRecordingControls;
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,7 +15,8 @@
#include "PrecompiledHeader.h"
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
#include "DebugTools/Debug.h"
#include "gui/MainFrame.h"
@ -66,22 +67,22 @@ bool InputRecordingFile::Close()
return true;
}
const wxString &InputRecordingFile::GetFilename()
const wxString& InputRecordingFile::GetFilename()
{
return filename;
}
InputRecordingFileHeader &InputRecordingFile::GetHeader()
InputRecordingFileHeader& InputRecordingFile::GetHeader()
{
return header;
}
long &InputRecordingFile::GetTotalFrames()
long& InputRecordingFile::GetTotalFrames()
{
return totalFrames;
}
unsigned long &InputRecordingFile::GetUndoCount()
unsigned long& InputRecordingFile::GetUndoCount()
{
return undoCount;
}
@ -143,7 +144,7 @@ bool InputRecordingFile::OpenExisting(const wxString& path)
return open(path, false);
}
bool InputRecordingFile::ReadKeyBuffer(u8 &result, const uint &frame, const uint port, const uint bufIndex)
bool InputRecordingFile::ReadKeyBuffer(u8& result, const uint& frame, const uint port, const uint bufIndex)
{
if (recordingFile == nullptr)
{
@ -177,17 +178,14 @@ bool InputRecordingFile::WriteHeader()
return false;
}
rewind(recordingFile);
if (fwrite(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1
|| fwrite(&totalFrames, 4, 1, recordingFile) != 1
|| fwrite(&undoCount, 4, 1, recordingFile) != 1
|| fwrite(&savestate, 1, 1, recordingFile) != 1)
if (fwrite(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1 || fwrite(&totalFrames, 4, 1, recordingFile) != 1 || fwrite(&undoCount, 4, 1, recordingFile) != 1 || fwrite(&savestate, 1, 1, recordingFile) != 1)
{
return false;
}
return true;
}
bool InputRecordingFile::WriteKeyBuffer(const uint &frame, const uint port, const uint bufIndex, const u8 &buf)
bool InputRecordingFile::WriteKeyBuffer(const uint& frame, const uint port, const uint bufIndex, const u8& buf)
{
if (recordingFile == nullptr)
{
@ -205,7 +203,7 @@ bool InputRecordingFile::WriteKeyBuffer(const uint &frame, const uint port, cons
return true;
}
long InputRecordingFile::getRecordingBlockSeekPoint(const long &frame)
long InputRecordingFile::getRecordingBlockSeekPoint(const long& frame)
{
return headerSize + sizeof(bool) + frame * inputBytesPerFrame;
}
@ -218,14 +216,11 @@ bool InputRecordingFile::verifyRecordingFileHeader()
}
// Verify header contents
rewind(recordingFile);
if (fread(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1
|| fread(&totalFrames, 4, 1, recordingFile) != 1
|| fread(&undoCount, 4, 1, recordingFile) != 1
|| fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
if (fread(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1 || fread(&totalFrames, 4, 1, recordingFile) != 1 || fread(&undoCount, 4, 1, recordingFile) != 1 || fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
{
return false;
}
// Check for current verison
if (header.version != 1)
{
@ -234,4 +229,220 @@ bool InputRecordingFile::verifyRecordingFileHeader()
}
return true;
}
#endif
#else
#include "InputRecordingFile.h"
#include "Utilities/InputRecordingLogger.h"
#include "common/FileSystem.h"
#include "DebugTools/Debug.h"
#include "MemoryTypes.h"
#include <fmt/format.h>
void InputRecordingFileHeader::Init()
{
memset(author, 0, std::size(author));
memset(gameName, 0, std::size(gameName));
}
void InputRecordingFileHeader::SetEmulatorVersion()
{
std::string emuVersion = fmt::format("PCSX2-{}.{}.{}", PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo);
int max = std::size(emu) - 1;
strncpy(emu, emuVersion.c_str(), max);
emu[max] = 0;
}
void InputRecordingFileHeader::SetAuthor(const std::string_view& _author)
{
int max = std::size(author) - 1;
strncpy(author, _author.data(), max);
author[max] = 0;
}
void InputRecordingFileHeader::SetGameName(const std::string_view& _gameName)
{
int max = std::size(gameName) - 1;
strncpy(gameName, _gameName.data(), max);
gameName[max] = 0;
}
bool InputRecordingFile::Close()
{
if (recordingFile == nullptr)
{
return false;
}
fclose(recordingFile);
recordingFile = nullptr;
filename = "";
return true;
}
const std::string& InputRecordingFile::GetFilename()
{
return filename;
}
InputRecordingFileHeader& InputRecordingFile::GetHeader()
{
return header;
}
long& InputRecordingFile::GetTotalFrames()
{
return totalFrames;
}
unsigned long& InputRecordingFile::GetUndoCount()
{
return undoCount;
}
bool InputRecordingFile::FromSaveState()
{
return savestate.fromSavestate;
}
void InputRecordingFile::IncrementUndoCount()
{
undoCount++;
if (recordingFile == nullptr)
{
return;
}
fseek(recordingFile, seekpointUndoCount, SEEK_SET);
fwrite(&undoCount, 4, 1, recordingFile);
}
bool InputRecordingFile::open(const fs::path& path, bool newRecording)
{
if (newRecording)
{
if ((recordingFile = FileSystem::OpenCFile(path.string().c_str(), "wb+")) != nullptr)
{
filename = path.string();
totalFrames = 0;
undoCount = 0;
header.Init();
return true;
}
}
else if ((recordingFile = FileSystem::OpenCFile(path.string().c_str(), "rb+")) != nullptr)
{
if (verifyRecordingFileHeader())
{
filename = path.string();
return true;
}
Close();
inputRec::consoleLog("Input recording file header is invalid");
return false;
}
inputRec::consoleLog(fmt::format("Input recording file opening failed. Error - {}", strerror(errno)));
return false;
}
bool InputRecordingFile::OpenNew(const fs::path& path, bool fromSavestate)
{
if (!open(path, true))
return false;
savestate.fromSavestate = fromSavestate;
return true;
}
bool InputRecordingFile::OpenExisting(const fs::path& path)
{
return open(path, false);
}
bool InputRecordingFile::ReadKeyBuffer(u8& result, const uint& frame, const uint port, const uint bufIndex)
{
if (recordingFile == nullptr)
{
return false;
}
long seek = getRecordingBlockSeekPoint(frame) + controllerInputBytes * port + bufIndex;
if (fseek(recordingFile, seek, SEEK_SET) != 0 || fread(&result, 1, 1, recordingFile) != 1)
{
return false;
}
return true;
}
void InputRecordingFile::SetTotalFrames(long frame)
{
if (recordingFile == nullptr || totalFrames >= frame)
{
return;
}
totalFrames = frame;
fseek(recordingFile, seekpointTotalFrames, SEEK_SET);
fwrite(&totalFrames, 4, 1, recordingFile);
}
bool InputRecordingFile::WriteHeader()
{
if (recordingFile == nullptr)
{
return false;
}
rewind(recordingFile);
if (fwrite(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1 || fwrite(&totalFrames, 4, 1, recordingFile) != 1 || fwrite(&undoCount, 4, 1, recordingFile) != 1 || fwrite(&savestate, 1, 1, recordingFile) != 1)
{
return false;
}
return true;
}
bool InputRecordingFile::WriteKeyBuffer(const uint& frame, const uint port, const uint bufIndex, const u8& buf)
{
if (recordingFile == nullptr)
{
return false;
}
long seek = getRecordingBlockSeekPoint(frame) + 18 * port + bufIndex;
if (fseek(recordingFile, seek, SEEK_SET) != 0 || fwrite(&buf, 1, 1, recordingFile) != 1)
{
return false;
}
fflush(recordingFile);
return true;
}
long InputRecordingFile::getRecordingBlockSeekPoint(const long& frame)
{
return headerSize + sizeof(bool) + frame * inputBytesPerFrame;
}
bool InputRecordingFile::verifyRecordingFileHeader()
{
if (recordingFile == nullptr)
{
return false;
}
// Verify header contents
rewind(recordingFile);
if (fread(&header, sizeof(InputRecordingFileHeader), 1, recordingFile) != 1 || fread(&totalFrames, 4, 1, recordingFile) != 1 || fread(&undoCount, 4, 1, recordingFile) != 1 || fread(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
{
return false;
}
// Check for current verison
if (header.version != 1)
{
inputRec::consoleLog(fmt::format("Input recording file is not a supported version - {}", header.version));
return false;
}
return true;
}
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,10 +15,10 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
#include "System.h"
#include "PadData.h"
// NOTE / TODOs for Version 2
@ -52,18 +52,18 @@ class InputRecordingFile
public:
~InputRecordingFile() { Close(); }
// Closes the underlying input recording file, writing the header and
// Closes the underlying input recording file, writing the header and
// prepares for a possible new recording to be started
bool Close();
// Retrieve the input recording's filename (not the path)
const wxString &GetFilename();
const wxString& GetFilename();
// Retrieve the input recording's header which contains high-level metadata on the recording
InputRecordingFileHeader &GetHeader();
InputRecordingFileHeader& GetHeader();
// The maximum number of frames, or in other words, the length of the recording
long &GetTotalFrames();
long& GetTotalFrames();
// The number of times a save-state has been loaded while recording this movie
// this is also often referred to as a "re-record"
unsigned long &GetUndoCount();
unsigned long& GetUndoCount();
// Whether or not this input recording starts by loading a save-state or by booting the game fresh
bool FromSaveState();
// Increment the number of undo actions and commit it to the recording file
@ -75,13 +75,13 @@ public:
bool OpenNew(const wxString& path, bool fromSaveState);
// Reads the current frame's input data from the file in order to intercept and overwrite
// the current frame's value from the emulator
bool ReadKeyBuffer(u8 &result, const uint &frame, const uint port, const uint bufIndex);
bool ReadKeyBuffer(u8& result, const uint& frame, const uint port, const uint bufIndex);
// Updates the total frame counter and commit it to the recording file
void SetTotalFrames(long frames);
// Persist the input recording file header's current state to the file
bool WriteHeader();
// Writes the current frame's input data to the file so it can be replayed
bool WriteKeyBuffer(const uint &frame, const uint port, const uint bufIndex, const u8 &buf);
bool WriteKeyBuffer(const uint& frame, const uint port, const uint bufIndex, const u8& buf);
private:
static const int controllerPortsSupported = 2;
@ -111,4 +111,99 @@ private:
bool verifyRecordingFileHeader();
};
#endif
#else
#include "System.h"
#include "PadData.h"
// NOTE / TODOs for Version 2
// - Move fromSavestate, undoCount, and total frames into the header
struct InputRecordingFileHeader
{
u8 version = 1;
char emu[50] = "";
char author[255] = "";
char gameName[255] = "";
public:
void SetEmulatorVersion();
void Init();
void SetAuthor(const std::string_view& author);
void SetGameName(const std::string_view& cdrom);
};
// DEPRECATED / Slated for Removal
struct InputRecordingSavestate
{
// Whether we start from the savestate or from power-on
bool fromSavestate = false;
};
// Handles all operations on the input recording file
class InputRecordingFile
{
public:
~InputRecordingFile() { Close(); }
// Closes the underlying input recording file, writing the header and
// prepares for a possible new recording to be started
bool Close();
// Retrieve the input recording's filename (not the path)
const std::string& GetFilename();
// Retrieve the input recording's header which contains high-level metadata on the recording
InputRecordingFileHeader& GetHeader();
// The maximum number of frames, or in other words, the length of the recording
long& GetTotalFrames();
// The number of times a save-state has been loaded while recording this movie
// this is also often referred to as a "re-record"
unsigned long& GetUndoCount();
// Whether or not this input recording starts by loading a save-state or by booting the game fresh
bool FromSaveState();
// Increment the number of undo actions and commit it to the recording file
void IncrementUndoCount();
// Open an existing recording file
bool OpenExisting(const fs::path& path);
// Create and open a brand new input recording, either starting from a save-state or from
// booting the game
bool OpenNew(const fs::path& path, bool fromSaveState);
// Reads the current frame's input data from the file in order to intercept and overwrite
// the current frame's value from the emulator
bool ReadKeyBuffer(u8& result, const uint& frame, const uint port, const uint bufIndex);
// Updates the total frame counter and commit it to the recording file
void SetTotalFrames(long frames);
// Persist the input recording file header's current state to the file
bool WriteHeader();
// Writes the current frame's input data to the file so it can be replayed
bool WriteKeyBuffer(const uint& frame, const uint port, const uint bufIndex, const u8& buf);
private:
static const int controllerPortsSupported = 2;
static const int controllerInputBytes = 18;
static const int inputBytesPerFrame = controllerInputBytes * controllerPortsSupported;
// TODO - version 2, this could be greatly simplified if everything was in the header
// + 4 + 4 is the totalFrame and undoCount values
static const int headerSize = sizeof(InputRecordingFileHeader) + 4 + 4;
// DEPRECATED / Slated for Removal
static const int recordingSavestateHeaderSize = sizeof(bool);
static const int seekpointTotalFrames = sizeof(InputRecordingFileHeader);
static const int seekpointUndoCount = sizeof(InputRecordingFileHeader) + 4;
static const int seekpointSaveStateHeader = seekpointUndoCount + 4;
InputRecordingFileHeader header;
std::string filename = "";
FILE* recordingFile = nullptr;
InputRecordingSavestate savestate;
// An signed 32-bit frame limit is equivalent to 1.13 years of continuous 60fps footage
long totalFrames = 0;
unsigned long undoCount = 0;
// Calculates the position of the current frame in the input recording
long getRecordingBlockSeekPoint(const long& frame);
bool open(const fs::path& path, bool newRecording);
bool verifyRecordingFileHeader();
};
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -13,9 +13,10 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
// This file dies along with wxWidgets
#ifndef PCSX2_CORE
#ifndef DISABLE_RECORDING
#include "PrecompiledHeader.h"
#include "NewRecordingFrame.h"
@ -157,4 +158,4 @@ int NewRecordingFrame::GetFrom() const
{
return m_fromChoice->GetSelection();
}
#endif
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2019 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,7 +15,7 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include <wx/wx.h>
#include <wx/filepicker.h>
@ -58,4 +58,4 @@ private:
wxString m_savestate_label;
wxStaticText* m_warning_label;
};
#endif
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -14,13 +14,11 @@
*/
#include "PrecompiledHeader.h"
#ifndef DISABLE_RECORDING
#include "DebugTools/Debug.h"
#include "Recording/PadData.h"
#include <fmt/core.h>
void PadData::UpdateControllerData(u16 bufIndex, u8 const& bufVal)
{
const BufferIndex index = static_cast<BufferIndex>(bufIndex);
@ -100,7 +98,7 @@ void PadData::UpdateControllerData(u16 bufIndex, u8 const& bufVal)
u8 PadData::PollControllerData(u16 bufIndex)
{
u8 byte = 0;
BufferIndex index = static_cast<BufferIndex>(bufIndex);
const BufferIndex index = static_cast<BufferIndex>(bufIndex);
switch (index)
{
case BufferIndex::PressedFlagsGroupOne:
@ -177,6 +175,9 @@ u8 PadData::BitmaskOrZero(bool pressed, ButtonResolver buttonInfo)
return pressed ? buttonInfo.buttonBitmask : 0;
}
#ifndef PCSX2_CORE
// TODO - Vaser - kill with wxWidgets
// TODO - Vaser - replace with this something better in Qt
wxString PadData::RawPadBytesToString(int start, int end)
{
wxString str;
@ -203,4 +204,33 @@ void PadData::LogPadData(u8 const& port)
controlLog(fullLog.ToUTF8());
}
#endif
#else
std::string PadData::RawPadBytesToString(int start, int end)
{
std::string str;
for (int i = start; i < end; i++)
{
str += fmt::format("{}", PollControllerData(i));
if (i != end - 1)
str += ", ";
}
return str;
}
void PadData::LogPadData(u8 const& port)
{
std::string pressedBytes = RawPadBytesToString(0, 2);
std::string rightAnalogBytes = RawPadBytesToString(2, 4);
std::string leftAnalogBytes = RawPadBytesToString(4, 6);
std::string pressureBytes = RawPadBytesToString(6, 17);
std::string fullLog =
fmt::format("[PAD {}] Raw Bytes: Pressed = [{}]\n", port + 1, pressedBytes) +
fmt::format("[PAD {}] Raw Bytes: Right Analog = [{}]\n", port + 1, rightAnalogBytes) +
fmt::format("[PAD {}] Raw Bytes: Left Analog = [{}]\n", port + 1, leftAnalogBytes) +
fmt::format("[PAD {}] Raw Bytes: Pressure = [{}]\n", port + 1, pressureBytes);
controlLog(fullLog);
}
#endif

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2020 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -15,8 +15,6 @@
#pragma once
#ifndef DISABLE_RECORDING
class PadData
{
public:
@ -122,7 +120,9 @@ private:
bool IsButtonPressed(ButtonResolver buttonResolver, u8 const& bufVal);
u8 BitmaskOrZero(bool pressed, ButtonResolver buttonInfo);
#ifndef PCSX2_CORE
wxString RawPadBytesToString(int start, int end);
};
#else
std::string RawPadBytesToString(int start, int end);
#endif
};

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-
@ -20,8 +20,6 @@
#include "DebugTools/Debug.h"
#include "common/Console.h"
#include "GS.h" // GSosdlog
#include "gui/App.h" // GetRGBA
#include "gui/ConsoleLogger.h"
#include "Host.h"
#include <fmt/core.h>

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2022 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-

View File

@ -15,7 +15,7 @@
#include "PrecompiledHeader.h"
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include <math.h>

View File

@ -15,7 +15,7 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include <map>
#include <queue>

View File

@ -15,7 +15,7 @@
#include "PrecompiledHeader.h"
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include "Recording/VirtualPad/VirtualPadData.h"

View File

@ -15,7 +15,7 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include "common/Pcsx2Types.h"

View File

@ -15,7 +15,7 @@
#include "PrecompiledHeader.h"
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include <wx/spinctrl.h>

View File

@ -15,7 +15,7 @@
#pragma once
#ifndef DISABLE_RECORDING
#ifndef PCSX2_CORE
#include <queue>