mirror of https://github.com/PCSX2/pcsx2.git
recording: Recording controls rename and refactor to attempt to simplify
* RecordingControls - > InputRecordingControls (+ function refactors & simplifications) * Avoid mutating g_FrameCount - now use isolated frameCounter & startingFrame variables for input recordings * Pause or resume emulation preemptively based on GUI actions * Exclusively handle GS window title updates in FrameForGS
This commit is contained in:
parent
fa894d9d48
commit
6c80e6b93f
|
@ -463,10 +463,10 @@ set(pcsx2RDebugHeaders
|
||||||
# Recording sources
|
# Recording sources
|
||||||
set(pcsx2RecordingSources
|
set(pcsx2RecordingSources
|
||||||
Recording/InputRecording.cpp
|
Recording/InputRecording.cpp
|
||||||
|
Recording/InputRecordingControls.cpp
|
||||||
Recording/InputRecordingFile.cpp
|
Recording/InputRecordingFile.cpp
|
||||||
Recording/NewRecordingFrame.cpp
|
Recording/NewRecordingFrame.cpp
|
||||||
Recording/PadData.cpp
|
Recording/PadData.cpp
|
||||||
Recording/RecordingControls.cpp
|
|
||||||
Recording/RecordingInputManager.cpp
|
Recording/RecordingInputManager.cpp
|
||||||
Recording/VirtualPad.cpp
|
Recording/VirtualPad.cpp
|
||||||
)
|
)
|
||||||
|
@ -474,10 +474,10 @@ set(pcsx2RecordingSources
|
||||||
# Recording headers
|
# Recording headers
|
||||||
set(pcsx2RecordingHeaders
|
set(pcsx2RecordingHeaders
|
||||||
Recording/InputRecording.h
|
Recording/InputRecording.h
|
||||||
|
Recording/InputRecordingControls.h
|
||||||
Recording/InputRecordingFile.h
|
Recording/InputRecordingFile.h
|
||||||
Recording/NewRecordingFrame.h
|
Recording/NewRecordingFrame.h
|
||||||
Recording/PadData.h
|
Recording/PadData.h
|
||||||
Recording/RecordingControls.h
|
|
||||||
Recording/RecordingInputManager.h
|
Recording/RecordingInputManager.h
|
||||||
Recording/VirtualPad.h
|
Recording/VirtualPad.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include "Sio.h"
|
#include "Sio.h"
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
# include "Recording/RecordingControls.h"
|
# include "Recording/InputRecordingControls.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Threading;
|
using namespace Threading;
|
||||||
|
@ -588,7 +588,7 @@ __fi void rcntUpdate_vSync()
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
g_RecordingControls.HandleFrameAdvanceAndStop();
|
g_InputRecordingControls.HandleFrameAdvanceAndPausing();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
VSyncStart(vsyncCounter.sCycle);
|
VSyncStart(vsyncCounter.sCycle);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2019 PCSX2 Dev Team
|
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* 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-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
@ -23,30 +23,50 @@
|
||||||
#include "SaveState.h"
|
#include "SaveState.h"
|
||||||
|
|
||||||
#include "InputRecording.h"
|
#include "InputRecording.h"
|
||||||
#include "Recording/RecordingControls.h"
|
#include "InputRecordingControls.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
// Tag and save framecount along with savestate
|
// Save or load PCSX2's global frame counter (g_FrameCount) along with each savestate
|
||||||
|
//
|
||||||
|
// 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 SaveStateBase::InputRecordingFreeze()
|
void SaveStateBase::InputRecordingFreeze()
|
||||||
{
|
{
|
||||||
FreezeTag("InputRecording");
|
FreezeTag("InputRecording");
|
||||||
Freeze(g_FrameCount);
|
Freeze(g_FrameCount);
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_FrameCount > 0 && IsLoading())
|
// Explicitly set the frame change tracking variable as to not
|
||||||
|
// detect loading a savestate as a frame being drawn
|
||||||
|
g_InputRecordingControls.SetFrameCountTracker(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.
|
||||||
|
// TODO - get rid of the -1
|
||||||
|
if (g_InputRecording.GetStartingFrame() == -1 && g_InputRecording.GetInputRecordingData().FromSaveState()) {
|
||||||
|
g_InputRecording.SetStartingFrame(g_FrameCount);
|
||||||
|
// TODO - make a function of my own to simplify working with the logging macros
|
||||||
|
recordingConLog(wxString::Format(L"[REC]: Internal Starting Frame: %d\n", g_InputRecording.GetStartingFrame()));
|
||||||
|
}
|
||||||
|
// Otherwise the starting savestate has been loaded and if loaded a save-state while recording the movie
|
||||||
|
// it is an undo operation that needs to be tracked.
|
||||||
|
else if (g_InputRecording.RecordingActive() && IsLoading())
|
||||||
{
|
{
|
||||||
g_InputRecordingData.IncrementUndoCount();
|
g_InputRecording.GetInputRecordingData().IncrementUndoCount();
|
||||||
|
// Reloading a save-state means the internal recording frame counter may need to be adjusted
|
||||||
|
// Since we persist the g_FrameCount of the beginning of the movie, we can use it to recalculate it
|
||||||
|
g_InputRecording.SetFrameCounter(g_FrameCount - (g_InputRecording.GetStartingFrame()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
InputRecording g_InputRecording;
|
InputRecording g_InputRecording;
|
||||||
|
|
||||||
// Main func for handling controller input data
|
|
||||||
// - Called by Sio.cpp::sioWriteController
|
|
||||||
void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 buf[])
|
void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 buf[])
|
||||||
{
|
{
|
||||||
// TODO - Multi-Tap Support
|
// TODO - Multi-Tap Support
|
||||||
|
@ -82,127 +102,195 @@ void InputRecording::ControllerInterrupt(u8& data, u8& port, u16& bufCount, u8 b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fInterruptFrame || state == INPUT_RECORDING_MODE_NONE
|
// We do not want to record or save the first two bytes in the data returned from the PAD plugin
|
||||||
// We do not want to record or save the first two
|
if (!fInterruptFrame || state == InputRecordingMode::NoneActive || bufCount < 3)
|
||||||
// bytes in the data returned from LilyPad
|
|
||||||
|| bufCount < 3)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read or Write
|
// Read or Write
|
||||||
const u8 &nowBuf = buf[bufCount];
|
const u8 &nowBuf = buf[bufCount];
|
||||||
if (state == INPUT_RECORDING_MODE_RECORD)
|
if (state == InputRecordingMode::Recording)
|
||||||
{
|
{
|
||||||
InputRecordingData.SetTotalFrames(g_FrameCount);
|
inputRecordingData.WriteKeyBuffer(frameCounter, port, bufCount - 3, nowBuf);
|
||||||
InputRecordingData.WriteKeyBuffer(g_FrameCount, port, bufCount - 3, nowBuf);
|
|
||||||
}
|
}
|
||||||
else if (state == INPUT_RECORDING_MODE_REPLAY)
|
else if (state == InputRecordingMode::Replaying)
|
||||||
{
|
{
|
||||||
if (InputRecordingData.GetTotalFrames() <= g_FrameCount)
|
|
||||||
{
|
|
||||||
// Pause the emulation but the movie is not closed
|
|
||||||
g_RecordingControls.Pause();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
u8 tmp = 0;
|
u8 tmp = 0;
|
||||||
if (InputRecordingData.ReadKeyBuffer(tmp, g_FrameCount, port, bufCount - 3))
|
if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufCount - 3))
|
||||||
{
|
{
|
||||||
buf[bufCount] = tmp;
|
buf[bufCount] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 InputRecording::GetFrameCounter()
|
||||||
|
{
|
||||||
|
return frameCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputRecordingFile &InputRecording::GetInputRecordingData()
|
||||||
|
{
|
||||||
|
return inputRecordingData;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 InputRecording::GetStartingFrame()
|
||||||
|
{
|
||||||
|
return startingFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecording::IncrementFrameCounter()
|
||||||
|
{
|
||||||
|
frameCounter++;
|
||||||
|
if (state == InputRecordingMode::Recording) {
|
||||||
|
GetInputRecordingData().SetTotalFrames(frameCounter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputRecording::IsInterruptFrame()
|
||||||
|
{
|
||||||
|
return fInterruptFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputRecording::IsRecordingReplaying()
|
||||||
|
{
|
||||||
|
return RecordingActive() && state == InputRecordingMode::Replaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputRecording::RecordingActive()
|
||||||
|
{
|
||||||
|
return state != InputRecordingMode::NoneActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString InputRecording::RecordingModeTitleSegment()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case InputRecordingMode::Recording:
|
||||||
|
return wxString("Recording");
|
||||||
|
break;
|
||||||
|
case InputRecordingMode::Replaying:
|
||||||
|
return wxString("Replaying");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return wxString("No Movie");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecording::RecordModeToggle()
|
||||||
|
{
|
||||||
|
if (state == InputRecordingMode::Replaying)
|
||||||
|
{
|
||||||
|
state = InputRecordingMode::Recording;
|
||||||
|
recordingConLog("[REC]: Record mode ON.\n");
|
||||||
|
}
|
||||||
|
else if (state == InputRecordingMode::Recording)
|
||||||
|
{
|
||||||
|
state = InputRecordingMode::Replaying;
|
||||||
|
recordingConLog("[REC]: Replay mode ON.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecording::SetFrameCounter(u32 newFrameCounter)
|
||||||
|
{
|
||||||
|
frameCounter = newFrameCounter;
|
||||||
|
if (state == InputRecordingMode::Recording)
|
||||||
|
{
|
||||||
|
GetInputRecordingData().SetTotalFrames(frameCounter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecording::SetStartingFrame(u32 newStartingFrame)
|
||||||
|
{
|
||||||
|
startingFrame = newStartingFrame;
|
||||||
|
}
|
||||||
|
|
||||||
// GUI Handler - Stop recording
|
|
||||||
void InputRecording::Stop()
|
void InputRecording::Stop()
|
||||||
{
|
{
|
||||||
state = INPUT_RECORDING_MODE_NONE;
|
// Reset the frame counter when starting a new recording
|
||||||
if (InputRecordingData.Close())
|
frameCounter = 0;
|
||||||
|
startingFrame = -1;
|
||||||
|
state = InputRecordingMode::NoneActive;
|
||||||
|
if (inputRecordingData.Close())
|
||||||
{
|
{
|
||||||
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
|
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GUI Handler - Start recording
|
|
||||||
bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
|
bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
|
||||||
{
|
{
|
||||||
if (!InputRecordingData.OpenNew(FileName, fromSaveState))
|
if (!inputRecordingData.OpenNew(FileName, fromSaveState))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Set emulator version
|
// Set emulator version
|
||||||
InputRecordingData.GetHeader().SetEmulatorVersion();
|
inputRecordingData.GetHeader().SetEmulatorVersion();
|
||||||
|
|
||||||
// Set author name
|
// Set author name
|
||||||
if (!authorName.IsEmpty())
|
if (!authorName.IsEmpty())
|
||||||
{
|
{
|
||||||
InputRecordingData.GetHeader().SetAuthor(authorName);
|
inputRecordingData.GetHeader().SetAuthor(authorName);
|
||||||
}
|
}
|
||||||
// Set Game Name
|
// Set Game Name
|
||||||
InputRecordingData.GetHeader().SetGameName(resolveGameName());
|
inputRecordingData.GetHeader().SetGameName(resolveGameName());
|
||||||
// Write header contents
|
// Write header contents
|
||||||
InputRecordingData.WriteHeader();
|
inputRecordingData.WriteHeader();
|
||||||
state = INPUT_RECORDING_MODE_RECORD;
|
state = InputRecordingMode::Recording;
|
||||||
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
|
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
|
||||||
|
|
||||||
// In every case, we reset the g_FrameCount
|
|
||||||
g_FrameCount = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GUI Handler - Play a recording
|
|
||||||
bool InputRecording::Play(wxString fileName)
|
bool InputRecording::Play(wxString fileName)
|
||||||
{
|
{
|
||||||
if (state != INPUT_RECORDING_MODE_NONE)
|
if (RecordingActive())
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
// Open the file and verify if it can be played
|
if (!inputRecordingData.OpenExisting(fileName))
|
||||||
if (!InputRecordingData.OpenExisting(fileName))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Either load the savestate, or restart the game
|
// Either load the savestate, or restart the game
|
||||||
if (InputRecordingData.FromSaveState())
|
if (inputRecordingData.FromSaveState())
|
||||||
{
|
{
|
||||||
if (!CoreThread.IsOpen())
|
if (!CoreThread.IsOpen())
|
||||||
{
|
{
|
||||||
recordingConLog(L"[REC]: Game is not open, aborting playing input recording which starts on a save-state.\n");
|
recordingConLog(L"[REC]: Game is not open, aborting playing input recording which starts on a save-state.\n");
|
||||||
InputRecordingData.Close();
|
inputRecordingData.Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
FILE* ssFileCheck = wxFopen(InputRecordingData.GetFilename() + "_SaveState.p2s", "r");
|
FILE* ssFileCheck = wxFopen(inputRecordingData.GetFilename() + "_SaveState.p2s", "r");
|
||||||
if (ssFileCheck == NULL)
|
if (ssFileCheck == NULL)
|
||||||
{
|
{
|
||||||
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n", InputRecordingData.GetFilename()));
|
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n", inputRecordingData.GetFilename()));
|
||||||
InputRecordingData.Close();
|
inputRecordingData.Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose(ssFileCheck);
|
fclose(ssFileCheck);
|
||||||
StateCopy_LoadFromFile(InputRecordingData.GetFilename() + "_SaveState.p2s");
|
StateCopy_LoadFromFile(inputRecordingData.GetFilename() + "_SaveState.p2s");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
sApp.SysExecute();
|
sApp.SysExecute();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the current game matches with the one used to make the original recording
|
// Check if the current game matches with the one used to make the original recording
|
||||||
if (!g_Conf->CurrentIso.IsEmpty())
|
if (!g_Conf->CurrentIso.IsEmpty())
|
||||||
{
|
{
|
||||||
if (resolveGameName() != InputRecordingData.GetHeader().gameName)
|
if (resolveGameName() != inputRecordingData.GetHeader().gameName)
|
||||||
{
|
{
|
||||||
recordingConLog(L"[REC]: Recording was possibly constructed for a different game.\n");
|
recordingConLog(L"[REC]: Recording was possibly constructed for a different game.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = INPUT_RECORDING_MODE_REPLAY;
|
state = InputRecordingMode::Replaying;
|
||||||
recordingConLog(wxString::Format(L"[REC]: Replaying input recording - [%s]\n", InputRecordingData.GetFilename()));
|
recordingConLog(wxString::Format(L"[REC]: Replaying input recording - [%s]\n", inputRecordingData.GetFilename()));
|
||||||
recordingConLog(wxString::Format(L"[REC]: PCSX2 Version Used: %s\n", InputRecordingData.GetHeader().emu));
|
recordingConLog(wxString::Format(L"[REC]: PCSX2 Version Used: %s\n", inputRecordingData.GetHeader().emu));
|
||||||
recordingConLog(wxString::Format(L"[REC]: Recording File Version: %d\n", InputRecordingData.GetHeader().version));
|
recordingConLog(wxString::Format(L"[REC]: Recording File Version: %d\n", inputRecordingData.GetHeader().version));
|
||||||
recordingConLog(wxString::Format(L"[REC]: Associated Game Name or ISO Filename: %s\n", InputRecordingData.GetHeader().gameName));
|
recordingConLog(wxString::Format(L"[REC]: Associated Game Name or ISO Filename: %s\n", inputRecordingData.GetHeader().gameName));
|
||||||
recordingConLog(wxString::Format(L"[REC]: Author: %s\n", InputRecordingData.GetHeader().author));
|
recordingConLog(wxString::Format(L"[REC]: Author: %s\n", inputRecordingData.GetHeader().author));
|
||||||
recordingConLog(wxString::Format(L"[REC]: Total Frames: %d\n", InputRecordingData.GetTotalFrames()));
|
recordingConLog(wxString::Format(L"[REC]: Total Frames: %d\n", inputRecordingData.GetTotalFrames()));
|
||||||
recordingConLog(wxString::Format(L"[REC]: Undo Count: %d\n", InputRecordingData.GetUndoCount()));
|
recordingConLog(wxString::Format(L"[REC]: Undo Count: %d\n", inputRecordingData.GetUndoCount()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,33 +314,4 @@ wxString InputRecording::resolveGameName()
|
||||||
return !gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso);
|
return !gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keybind Handler - Toggle between recording input and not
|
|
||||||
void InputRecording::RecordModeToggle()
|
|
||||||
{
|
|
||||||
if (state == INPUT_RECORDING_MODE_REPLAY)
|
|
||||||
{
|
|
||||||
state = INPUT_RECORDING_MODE_RECORD;
|
|
||||||
recordingConLog("[REC]: Record mode ON.\n");
|
|
||||||
}
|
|
||||||
else if (state == INPUT_RECORDING_MODE_RECORD)
|
|
||||||
{
|
|
||||||
state = INPUT_RECORDING_MODE_REPLAY;
|
|
||||||
recordingConLog("[REC]: Replay mode ON.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INPUT_RECORDING_MODE InputRecording::GetModeState()
|
|
||||||
{
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputRecordingFile& InputRecording::GetInputRecordingData()
|
|
||||||
{
|
|
||||||
return InputRecordingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputRecording::IsInterruptFrame()
|
|
||||||
{
|
|
||||||
return fInterruptFrame;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2019 PCSX2 Dev Team
|
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* 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-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
@ -19,41 +19,69 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
enum INPUT_RECORDING_MODE
|
|
||||||
{
|
|
||||||
INPUT_RECORDING_MODE_NONE,
|
|
||||||
INPUT_RECORDING_MODE_RECORD,
|
|
||||||
INPUT_RECORDING_MODE_REPLAY,
|
|
||||||
};
|
|
||||||
|
|
||||||
class InputRecording
|
class InputRecording
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputRecording() {}
|
// Main handler for ingesting input data and either saving it to the recording file (recording)
|
||||||
~InputRecording() {}
|
// or mutating it to the contents of the recording file (replaying)
|
||||||
|
|
||||||
void ControllerInterrupt(u8 &data, u8 &port, u16 &BufCount, u8 buf[]);
|
void ControllerInterrupt(u8 &data, u8 &port, u16 &BufCount, u8 buf[]);
|
||||||
|
|
||||||
void RecordModeToggle();
|
// The running frame counter for the input recording
|
||||||
|
u32 GetFrameCounter();
|
||||||
|
|
||||||
INPUT_RECORDING_MODE GetModeState();
|
|
||||||
InputRecordingFile &GetInputRecordingData();
|
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();
|
bool IsInterruptFrame();
|
||||||
|
|
||||||
void Stop();
|
// If there is currently an input recording being played back or actively being recorded
|
||||||
|
bool RecordingActive();
|
||||||
|
bool IsRecordingReplaying();
|
||||||
|
|
||||||
|
// String representation of the current recording mode to be interpolated into the title
|
||||||
|
wxString RecordingModeTitleSegment();
|
||||||
|
|
||||||
|
// Switches between recording and replaying the active input recording file
|
||||||
|
void RecordModeToggle();
|
||||||
|
|
||||||
|
// Set the running frame counter for the input recording to an arbitrary value
|
||||||
|
void SetFrameCounter(u32 newFrameCounter);
|
||||||
|
// Store the starting internal PCSX2 g_FrameCount value
|
||||||
|
void SetStartingFrame(u32 newStartingFrame);
|
||||||
|
|
||||||
|
/// Functions called from GUI
|
||||||
|
|
||||||
|
// Create a new input recording file
|
||||||
bool Create(wxString filename, bool fromSaveState, wxString authorName);
|
bool Create(wxString filename, bool fromSaveState, wxString authorName);
|
||||||
|
// Play an existing input recording from a file
|
||||||
bool Play(wxString filename);
|
bool Play(wxString filename);
|
||||||
|
// Stop the active input recording
|
||||||
|
void Stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InputRecordingFile InputRecordingData;
|
enum class InputRecordingMode {
|
||||||
INPUT_RECORDING_MODE state = INPUT_RECORDING_MODE_NONE;
|
NoneActive,
|
||||||
|
Recording,
|
||||||
|
Replaying,
|
||||||
|
};
|
||||||
|
|
||||||
bool fInterruptFrame = false;
|
bool fInterruptFrame = false;
|
||||||
|
|
||||||
|
InputRecordingFile inputRecordingData;
|
||||||
|
InputRecordingMode state = InputRecording::InputRecordingMode::NoneActive;
|
||||||
|
u32 frameCounter = 0;
|
||||||
|
u32 startingFrame = -1;
|
||||||
|
|
||||||
// Resolve the name and region of the game currently loaded using the GameDB
|
// 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
|
// If the game cannot be found in the DB, the fallback is the ISO filename
|
||||||
wxString resolveGameName();
|
wxString resolveGameName();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern InputRecording g_InputRecording;
|
extern InputRecording g_InputRecording;
|
||||||
static InputRecordingFile& g_InputRecordingData = g_InputRecording.GetInputRecordingData();
|
|
||||||
static InputRecordingFileHeader& g_InputRecordingHeader = g_InputRecording.GetInputRecordingData().GetHeader();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2020 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 "App.h"
|
||||||
|
#include "Counters.h"
|
||||||
|
#include "DebugTools/Debug.h"
|
||||||
|
#include "GSFrame.h"
|
||||||
|
#include "MemoryTypes.h"
|
||||||
|
|
||||||
|
#include "InputRecording.h"
|
||||||
|
#include "InputRecordingControls.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
|
InputRecordingControls g_InputRecordingControls;
|
||||||
|
|
||||||
|
|
||||||
|
void InputRecordingControls::HandleFrameAdvanceAndPausing()
|
||||||
|
{
|
||||||
|
// This function can be called multiple times per frame via Counters::rcntUpdate_vSync,
|
||||||
|
// often this is twice per frame but this may vary as Counters.cpp mentions the
|
||||||
|
// vsync timing can change.
|
||||||
|
//
|
||||||
|
// As a safeguard, use the global g_FrameCount to know when the frame counter has truly changed.
|
||||||
|
//
|
||||||
|
// NOTE - Do not mutate g_FrameCount or use it's value to set the input recording's internal frame counter
|
||||||
|
if (frameCountTracker != g_FrameCount) {
|
||||||
|
frameCountTracker = g_FrameCount;
|
||||||
|
g_InputRecording.IncrementFrameCounter();
|
||||||
|
} else {
|
||||||
|
if (pauseEmulation) {
|
||||||
|
emulationCurrentlyPaused = true;
|
||||||
|
CoreThread.PauseSelf();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames()) {
|
||||||
|
pauseEmulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we havn't yet advanced atleast a single frame from when we paused, setup things to be paused
|
||||||
|
if (frameAdvancing && frameAdvanceMarker < g_InputRecording.GetFrameCounter())
|
||||||
|
{
|
||||||
|
frameAdvancing = false;
|
||||||
|
pauseEmulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pause emulation if we need to (either due to frame advancing, or pause has been explicitly toggled on)
|
||||||
|
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning()) {
|
||||||
|
emulationCurrentlyPaused = true;
|
||||||
|
CoreThread.PauseSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::ResumeCoreThreadIfStarted()
|
||||||
|
{
|
||||||
|
if (resumeEmulation && CoreThread.IsOpen() && CoreThread.IsPaused()) {
|
||||||
|
CoreThread.Resume();
|
||||||
|
resumeEmulation = false;
|
||||||
|
emulationCurrentlyPaused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::FrameAdvance()
|
||||||
|
{
|
||||||
|
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
||||||
|
{
|
||||||
|
g_InputRecording.RecordModeToggle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
frameAdvanceMarker = g_InputRecording.GetFrameCounter();
|
||||||
|
frameAdvancing = true;
|
||||||
|
Resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputRecordingControls::IsRecordingPaused()
|
||||||
|
{
|
||||||
|
return (emulationCurrentlyPaused && CoreThread.IsOpen() && CoreThread.IsPaused());
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::Pause()
|
||||||
|
{
|
||||||
|
pauseEmulation = true;
|
||||||
|
resumeEmulation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::PauseImmediately()
|
||||||
|
{
|
||||||
|
if (CoreThread.IsPaused()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Pause();
|
||||||
|
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning()) {
|
||||||
|
emulationCurrentlyPaused = true;
|
||||||
|
CoreThread.PauseSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::Resume()
|
||||||
|
{
|
||||||
|
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames()) {
|
||||||
|
g_InputRecording.RecordModeToggle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pauseEmulation = false;
|
||||||
|
resumeEmulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::SetFrameCountTracker(u32 newFrame)
|
||||||
|
{
|
||||||
|
frameCountTracker = newFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputRecordingControls::TogglePause()
|
||||||
|
{
|
||||||
|
if (pauseEmulation && g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames()) {
|
||||||
|
g_InputRecording.RecordModeToggle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pauseEmulation = !pauseEmulation;
|
||||||
|
resumeEmulation = !pauseEmulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2020 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
class InputRecordingControls
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Intended to be called at the end of each frame, but will no-op if the frame count has not
|
||||||
|
// truly incremented
|
||||||
|
//
|
||||||
|
// Increments the input recording's frame counter and will pause 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 HandleFrameAdvanceAndPausing();
|
||||||
|
// 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();
|
||||||
|
// Returns true if the input recording has been paused, which can occur:
|
||||||
|
// - After a single frame has passed after InputRecordingControls::FrameAdvance
|
||||||
|
// - Explicitly paused via InputRecordingControls::TogglePause
|
||||||
|
bool IsRecordingPaused();
|
||||||
|
// 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();
|
||||||
|
void SetFrameCountTracker(u32 newFrame);
|
||||||
|
// Alternates emulation between a paused and unpaused state
|
||||||
|
void TogglePause();
|
||||||
|
|
||||||
|
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;
|
||||||
|
// The input recording frame that frame advancing began on
|
||||||
|
u32 frameAdvanceMarker = 0;
|
||||||
|
// Used to detect if the internal PCSX2 g_FrameCount has changed
|
||||||
|
u32 frameCountTracker = -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern InputRecordingControls g_InputRecordingControls;
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2019 PCSX2 Dev Team
|
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* 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-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
@ -260,19 +260,4 @@ bool InputRecordingFile::verifyRecordingFileHeader()
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputRecordingFile::writeSaveState() {
|
|
||||||
if (recordingFile == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(recordingFile, seekpointSaveStateHeader, SEEK_SET);
|
|
||||||
if (fwrite(&savestate.fromSavestate, sizeof(bool), 1, recordingFile) != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2019 PCSX2 Dev Team
|
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* 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-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
@ -82,6 +82,8 @@ public:
|
||||||
// Writes the current frame's input data to the file so it can be replayed
|
// 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);
|
||||||
|
|
||||||
|
unsigned long recordingFrameCounter = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int controllerPortsSupported = 2;
|
static const int controllerPortsSupported = 2;
|
||||||
static const int controllerInputBytes = 18;
|
static const int controllerInputBytes = 18;
|
||||||
|
@ -99,6 +101,8 @@ private:
|
||||||
wxString filename = "";
|
wxString filename = "";
|
||||||
FILE * recordingFile = NULL;
|
FILE * recordingFile = NULL;
|
||||||
InputRecordingSavestate savestate;
|
InputRecordingSavestate savestate;
|
||||||
|
|
||||||
|
// An unsigned 32-bit frame limit is equivalent to 2.25 years of continuous 60fps footage
|
||||||
unsigned long totalFrames = 0;
|
unsigned long totalFrames = 0;
|
||||||
unsigned long undoCount = 0;
|
unsigned long undoCount = 0;
|
||||||
|
|
||||||
|
@ -106,6 +110,5 @@ private:
|
||||||
long getRecordingBlockSeekPoint(const long& frame);
|
long getRecordingBlockSeekPoint(const long& frame);
|
||||||
bool open(const wxString path, bool newRecording);
|
bool open(const wxString path, bool newRecording);
|
||||||
bool verifyRecordingFileHeader();
|
bool verifyRecordingFileHeader();
|
||||||
bool writeSaveState();
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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 "App.h"
|
|
||||||
#include "Counters.h"
|
|
||||||
#include "Common.h"
|
|
||||||
#include "GSFrame.h"
|
|
||||||
#include "MemoryTypes.h"
|
|
||||||
|
|
||||||
#include "RecordingControls.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
|
||||||
RecordingControls g_RecordingControls;
|
|
||||||
|
|
||||||
//-----------------------------------------------
|
|
||||||
// Current recording status, returns true if:
|
|
||||||
// - Recording is Paused
|
|
||||||
// - GSFrame CoreThread is both running AND paused
|
|
||||||
//-----------------------------------------------
|
|
||||||
bool RecordingControls::IsEmulationAndRecordingPaused()
|
|
||||||
{
|
|
||||||
return fPauseState && CoreThread.IsOpen() && CoreThread.IsPaused();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------
|
|
||||||
// Called after inputs are recorded for that frame, places lock on input recording, effectively releasing resources and resuming CoreThread.
|
|
||||||
//-----------------------------------------------
|
|
||||||
void RecordingControls::ResumeCoreThreadIfStarted()
|
|
||||||
{
|
|
||||||
if (fStart && CoreThread.IsOpen() && CoreThread.IsPaused())
|
|
||||||
{
|
|
||||||
CoreThread.Resume();
|
|
||||||
fStart = false;
|
|
||||||
fPauseState = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------
|
|
||||||
// Called at VSYNC End / VRender Begin, updates everything recording related for the next frame,
|
|
||||||
// toggles RecordingControl flags back to enable input recording for the next frame.
|
|
||||||
//-----------------------------------------------
|
|
||||||
void RecordingControls::HandleFrameAdvanceAndStop()
|
|
||||||
{
|
|
||||||
if (fFrameAdvance)
|
|
||||||
{
|
|
||||||
if (stopFrameCount < g_FrameCount)
|
|
||||||
{
|
|
||||||
fFrameAdvance = false;
|
|
||||||
fStop = true;
|
|
||||||
stopFrameCount = g_FrameCount;
|
|
||||||
|
|
||||||
// We force the frame counter in the title bar to change
|
|
||||||
wxString oldTitle = wxGetApp().GetGsFrame().GetTitle();
|
|
||||||
wxString title = g_Conf->Templates.RecordingTemplate;
|
|
||||||
wxString frameCount = wxString::Format("%d", g_FrameCount);
|
|
||||||
|
|
||||||
title.Replace(L"${frame}", frameCount);
|
|
||||||
int frameIndex = title.find(wxString::Format(L"%d", g_FrameCount));
|
|
||||||
frameIndex += frameCount.length();
|
|
||||||
|
|
||||||
title.replace(frameIndex, oldTitle.length() - frameIndex, oldTitle.c_str().AsChar() + frameIndex);
|
|
||||||
|
|
||||||
wxGetApp().GetGsFrame().SetTitle(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fStop && CoreThread.IsOpen() && CoreThread.IsRunning())
|
|
||||||
{
|
|
||||||
fPauseState = true;
|
|
||||||
CoreThread.PauseSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RecordingControls::GetStopFlag()
|
|
||||||
{
|
|
||||||
return (fStop || fFrameAdvance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordingControls::FrameAdvance()
|
|
||||||
{
|
|
||||||
stopFrameCount = g_FrameCount;
|
|
||||||
fFrameAdvance = true;
|
|
||||||
fStop = false;
|
|
||||||
fStart = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordingControls::TogglePause()
|
|
||||||
{
|
|
||||||
fStop = !fStop;
|
|
||||||
if (fStop == false)
|
|
||||||
{
|
|
||||||
fStart = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordingControls::Pause()
|
|
||||||
{
|
|
||||||
fStop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordingControls::Unpause()
|
|
||||||
{
|
|
||||||
fStop = false;
|
|
||||||
fStart = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2020 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
|
||||||
class RecordingControls
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Movie controls main functions
|
|
||||||
bool IsEmulationAndRecordingPaused();
|
|
||||||
void ResumeCoreThreadIfStarted();
|
|
||||||
void HandleFrameAdvanceAndStop();
|
|
||||||
|
|
||||||
// Shortcut Keys
|
|
||||||
void FrameAdvance();
|
|
||||||
void TogglePause();
|
|
||||||
|
|
||||||
// Setters
|
|
||||||
void Pause();
|
|
||||||
void Unpause();
|
|
||||||
|
|
||||||
// Getters
|
|
||||||
bool GetStopFlag();
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint stopFrameCount = false;
|
|
||||||
|
|
||||||
bool fStop = false;
|
|
||||||
bool fStart = false;
|
|
||||||
bool fFrameAdvance = false;
|
|
||||||
bool fPauseState = false;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
extern RecordingControls g_RecordingControls;
|
|
||||||
#endif
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "Debugger/DisassemblyDialog.h"
|
#include "Debugger/DisassemblyDialog.h"
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
# include "Recording/RecordingControls.h"
|
# include "Recording/InputRecordingControls.h"
|
||||||
# include "Recording/InputRecording.h"
|
# include "Recording/InputRecording.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
if (g_RecordingControls.IsEmulationAndRecordingPaused())
|
if (g_InputRecordingControls.IsRecordingPaused())
|
||||||
{
|
{
|
||||||
// When the GSFrame CoreThread is paused, so is the logical VSync
|
// When the GSFrame CoreThread is paused, so is the logical VSync
|
||||||
// Meaning that we have to grab the user-input through here to potentially
|
// Meaning that we have to grab the user-input through here to potentially
|
||||||
|
@ -633,7 +633,7 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_RecordingControls.ResumeCoreThreadIfStarted();
|
g_InputRecordingControls.ResumeCoreThreadIfStarted();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
(handler->*func)(event);
|
(handler->*func)(event);
|
||||||
|
@ -1059,7 +1059,7 @@ void Pcsx2App::OnProgramLogClosed( wxWindowID id )
|
||||||
void Pcsx2App::OnMainFrameClosed( wxWindowID id )
|
void Pcsx2App::OnMainFrameClosed( wxWindowID id )
|
||||||
{
|
{
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
if (g_InputRecording.GetModeState() == INPUT_RECORDING_MODE_NONE)
|
if (g_InputRecording.RecordingActive())
|
||||||
{
|
{
|
||||||
g_InputRecording.Stop();
|
g_InputRecording.Stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -732,25 +732,15 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
wxString title;
|
wxString title;
|
||||||
wxString movieMode;
|
wxString movieMode;
|
||||||
switch (g_InputRecording.GetModeState())
|
if (g_InputRecording.RecordingActive())
|
||||||
{
|
{
|
||||||
case INPUT_RECORDING_MODE_RECORD:
|
|
||||||
movieMode = "Recording";
|
|
||||||
title = templates.RecordingTemplate;
|
title = templates.RecordingTemplate;
|
||||||
break;
|
title.Replace(L"${frame}", pxsFmt(L"%d", g_InputRecording.GetFrameCounter()));
|
||||||
case INPUT_RECORDING_MODE_REPLAY:
|
|
||||||
movieMode = "Replaying";
|
|
||||||
title = templates.RecordingTemplate;
|
|
||||||
break;
|
|
||||||
case INPUT_RECORDING_MODE_NONE:
|
|
||||||
movieMode = "No movie";
|
|
||||||
title = templates.TitleTemplate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
title.Replace(L"${frame}", pxsFmt(L"%d", g_FrameCount));
|
|
||||||
title.Replace(L"${maxFrame}", pxsFmt(L"%d", g_InputRecording.GetInputRecordingData().GetTotalFrames()));
|
title.Replace(L"${maxFrame}", pxsFmt(L"%d", g_InputRecording.GetInputRecordingData().GetTotalFrames()));
|
||||||
title.Replace(L"${mode}", movieMode);
|
title.Replace(L"${mode}", g_InputRecording.RecordingModeTitleSegment());
|
||||||
|
} else {
|
||||||
|
title = templates.TitleTemplate;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
wxString title = templates.TitleTemplate;
|
wxString title = templates.TitleTemplate;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "AppSaveStates.h"
|
#include "AppSaveStates.h"
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
# include "Recording/RecordingControls.h"
|
# include "Recording/InputRecordingControls.h"
|
||||||
# include "Recording/InputRecording.h"
|
# include "Recording/InputRecording.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -473,7 +473,7 @@ namespace Implementations
|
||||||
{
|
{
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
g_RecordingControls.FrameAdvance();
|
g_InputRecordingControls.FrameAdvance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +481,7 @@ namespace Implementations
|
||||||
{
|
{
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools)
|
if (g_Conf->EmuOptions.EnableRecordingTools)
|
||||||
{
|
{
|
||||||
g_RecordingControls.TogglePause();
|
g_InputRecordingControls.TogglePause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,8 @@
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
# include "Recording/InputRecording.h"
|
# include "Recording/InputRecording.h"
|
||||||
# include "Recording/RecordingControls.h"
|
# include "Recording/InputRecordingControls.h"
|
||||||
# include "Recording/VirtualPad.h"
|
# include "Recording/VirtualPad.h"
|
||||||
# include "Recording/RecordingControls.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -531,7 +530,7 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Properly close any currently loaded recording file before disabling
|
//Properly close any currently loaded recording file before disabling
|
||||||
if (g_InputRecording.GetModeState() != INPUT_RECORDING_MODE_NONE)
|
if (g_InputRecording.RecordingActive())
|
||||||
Menu_Recording_Stop_Click(event);
|
Menu_Recording_Stop_Click(event);
|
||||||
GetMenuBar()->Remove(TopLevelMenu_InputRecording);
|
GetMenuBar()->Remove(TopLevelMenu_InputRecording);
|
||||||
// Always turn controller logs off, but never turn it on by default
|
// Always turn controller logs off, but never turn it on by default
|
||||||
|
@ -544,8 +543,8 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
|
||||||
viewport->InitDefaultAccelerators();
|
viewport->InitDefaultAccelerators();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (g_RecordingControls.IsEmulationAndRecordingPaused())
|
if (g_InputRecordingControls.IsRecordingPaused())
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Conf->EmuOptions.EnableRecordingTools = checked;
|
g_Conf->EmuOptions.EnableRecordingTools = checked;
|
||||||
|
@ -690,11 +689,11 @@ void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent& event)
|
||||||
// If the CoreThread is paused prior to opening the PAD plugin settings then when the settings
|
// If the CoreThread is paused prior to opening the PAD plugin settings then when the settings
|
||||||
// are closed the PAD will not re-open. To avoid this, we resume emulation prior to the plugins
|
// are closed the PAD will not re-open. To avoid this, we resume emulation prior to the plugins
|
||||||
// configuration handler doing so.
|
// configuration handler doing so.
|
||||||
if (g_Conf->EmuOptions.EnableRecordingTools && g_RecordingControls.IsEmulationAndRecordingPaused())
|
if (g_Conf->EmuOptions.EnableRecordingTools && g_InputRecordingControls.IsRecordingPaused())
|
||||||
{
|
{
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
GetCorePlugins().Configure(pid);
|
GetCorePlugins().Configure(pid);
|
||||||
g_RecordingControls.Pause();
|
g_InputRecordingControls.Pause();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GetCorePlugins().Configure(pid);
|
GetCorePlugins().Configure(pid);
|
||||||
|
@ -874,53 +873,53 @@ void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent & eve
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event)
|
void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event)
|
||||||
{
|
{
|
||||||
const bool initiallyPaused = g_RecordingControls.IsEmulationAndRecordingPaused();
|
const bool initiallyPaused = g_InputRecordingControls.IsRecordingPaused();
|
||||||
if (!initiallyPaused)
|
if (!initiallyPaused)
|
||||||
g_RecordingControls.Pause();
|
g_InputRecordingControls.PauseImmediately();
|
||||||
NewRecordingFrame* NewRecordingFrame = wxGetApp().GetNewRecordingFramePtr();
|
NewRecordingFrame* NewRecordingFrame = wxGetApp().GetNewRecordingFramePtr();
|
||||||
if (NewRecordingFrame)
|
if (NewRecordingFrame)
|
||||||
{
|
{
|
||||||
if (NewRecordingFrame->ShowModal() == wxID_CANCEL)
|
if (NewRecordingFrame->ShowModal() == wxID_CANCEL)
|
||||||
{
|
{
|
||||||
if (!initiallyPaused)
|
if (!initiallyPaused)
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!g_InputRecording.Create(NewRecordingFrame->GetFile(), !NewRecordingFrame->GetFrom(), NewRecordingFrame->GetAuthor()))
|
if (!g_InputRecording.Create(NewRecordingFrame->GetFile(), !NewRecordingFrame->GetFrom(), NewRecordingFrame->GetAuthor()))
|
||||||
{
|
{
|
||||||
if (!initiallyPaused)
|
if (!initiallyPaused)
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true);
|
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true);
|
||||||
if (!g_InputRecordingData.FromSaveState())
|
if (!g_InputRecording.GetInputRecordingData().FromSaveState())
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
|
void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
|
||||||
{
|
{
|
||||||
const bool initiallyPaused = g_RecordingControls.IsEmulationAndRecordingPaused();
|
const bool initiallyPaused = g_InputRecordingControls.IsRecordingPaused();
|
||||||
if (!initiallyPaused)
|
if (!initiallyPaused)
|
||||||
g_RecordingControls.Pause();
|
g_InputRecordingControls.PauseImmediately();
|
||||||
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
|
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
|
||||||
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
|
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
|
||||||
if (openFileDialog.ShowModal() == wxID_CANCEL)
|
if (openFileDialog.ShowModal() == wxID_CANCEL)
|
||||||
{
|
{
|
||||||
if (!initiallyPaused)
|
if (!initiallyPaused)
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString path = openFileDialog.GetPath();
|
wxString path = openFileDialog.GetPath();
|
||||||
const bool recordingLoaded = g_InputRecording.GetModeState() != INPUT_RECORDING_MODE_NONE;
|
const bool recordingLoaded = g_InputRecording.RecordingActive();
|
||||||
if (!g_InputRecording.Play(path))
|
if (!g_InputRecording.Play(path))
|
||||||
{
|
{
|
||||||
if (recordingLoaded)
|
if (recordingLoaded)
|
||||||
Menu_Recording_Stop_Click(event);
|
Menu_Recording_Stop_Click(event);
|
||||||
if (!initiallyPaused)
|
if (!initiallyPaused)
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!recordingLoaded)
|
if (!recordingLoaded)
|
||||||
|
@ -928,7 +927,7 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
|
||||||
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true);
|
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true);
|
||||||
}
|
}
|
||||||
g_RecordingControls.Unpause();
|
g_InputRecordingControls.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent &event)
|
void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent &event)
|
||||||
|
|
|
@ -192,12 +192,12 @@
|
||||||
<ClCompile Include="..\..\ps2\Iop\PsxBios.cpp" />
|
<ClCompile Include="..\..\ps2\Iop\PsxBios.cpp" />
|
||||||
<ClCompile Include="..\..\ps2\LegacyDmac.cpp" />
|
<ClCompile Include="..\..\ps2\LegacyDmac.cpp" />
|
||||||
<ClCompile Include="..\..\ps2\pgif.cpp" />
|
<ClCompile Include="..\..\ps2\pgif.cpp" />
|
||||||
|
<ClCompile Include="..\..\Recording\InputRecordingControls.cpp" />
|
||||||
<ClCompile Include="..\..\ShiftJisToUnicode.cpp" />
|
<ClCompile Include="..\..\ShiftJisToUnicode.cpp" />
|
||||||
<ClCompile Include="..\..\sif2.cpp" />
|
<ClCompile Include="..\..\sif2.cpp" />
|
||||||
<ClCompile Include="..\..\Recording\InputRecording.cpp" />
|
<ClCompile Include="..\..\Recording\InputRecording.cpp" />
|
||||||
<ClCompile Include="..\..\Recording\NewRecordingFrame.cpp" />
|
<ClCompile Include="..\..\Recording\NewRecordingFrame.cpp" />
|
||||||
<ClCompile Include="..\..\Recording\InputRecordingFile.cpp" />
|
<ClCompile Include="..\..\Recording\InputRecordingFile.cpp" />
|
||||||
<ClCompile Include="..\..\Recording\RecordingControls.cpp" />
|
|
||||||
<ClCompile Include="..\..\Recording\PadData.cpp" />
|
<ClCompile Include="..\..\Recording\PadData.cpp" />
|
||||||
<ClCompile Include="..\..\Recording\RecordingInputManager.cpp" />
|
<ClCompile Include="..\..\Recording\RecordingInputManager.cpp" />
|
||||||
<ClCompile Include="..\..\Recording\VirtualPad.cpp" />
|
<ClCompile Include="..\..\Recording\VirtualPad.cpp" />
|
||||||
|
@ -430,9 +430,9 @@
|
||||||
<ClInclude Include="..\..\PrecompiledHeader.h" />
|
<ClInclude Include="..\..\PrecompiledHeader.h" />
|
||||||
<ClInclude Include="..\..\ps2\pgif.h" />
|
<ClInclude Include="..\..\ps2\pgif.h" />
|
||||||
<ClInclude Include="..\..\Recording\InputRecording.h" />
|
<ClInclude Include="..\..\Recording\InputRecording.h" />
|
||||||
|
<ClInclude Include="..\..\Recording\InputRecordingControls.h" />
|
||||||
<ClInclude Include="..\..\Recording\NewRecordingFrame.h" />
|
<ClInclude Include="..\..\Recording\NewRecordingFrame.h" />
|
||||||
<ClInclude Include="..\..\Recording\InputRecordingFile.h" />
|
<ClInclude Include="..\..\Recording\InputRecordingFile.h" />
|
||||||
<ClInclude Include="..\..\Recording\RecordingControls.h" />
|
|
||||||
<ClInclude Include="..\..\Recording\PadData.h" />
|
<ClInclude Include="..\..\Recording\PadData.h" />
|
||||||
<ClInclude Include="..\..\Recording\RecordingInputManager.h" />
|
<ClInclude Include="..\..\Recording\RecordingInputManager.h" />
|
||||||
<ClInclude Include="..\..\Recording\VirtualPad.h" />
|
<ClInclude Include="..\..\Recording\VirtualPad.h" />
|
||||||
|
|
|
@ -847,9 +847,6 @@
|
||||||
<ClCompile Include="..\..\Recording\PadData.cpp">
|
<ClCompile Include="..\..\Recording\PadData.cpp">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\Recording\RecordingControls.cpp">
|
|
||||||
<Filter>Recording</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\Recording\RecordingInputManager.cpp">
|
<ClCompile Include="..\..\Recording\RecordingInputManager.cpp">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -862,6 +859,9 @@
|
||||||
<ClCompile Include="..\..\IPU\IPUdither.cpp">
|
<ClCompile Include="..\..\IPU\IPUdither.cpp">
|
||||||
<Filter>System\Ps2\IPU</Filter>
|
<Filter>System\Ps2\IPU</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\Recording\InputRecordingControls.cpp">
|
||||||
|
<Filter>Recording</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\Patch.h">
|
<ClInclude Include="..\..\Patch.h">
|
||||||
|
@ -1299,9 +1299,6 @@
|
||||||
<ClInclude Include="..\..\Recording\PadData.h">
|
<ClInclude Include="..\..\Recording\PadData.h">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\Recording\RecordingControls.h">
|
|
||||||
<Filter>Recording</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\Recording\RecordingInputManager.h">
|
<ClInclude Include="..\..\Recording\RecordingInputManager.h">
|
||||||
<Filter>Recording</Filter>
|
<Filter>Recording</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1311,6 +1308,9 @@
|
||||||
<ClInclude Include="..\..\Recording\VirtualPad.h">
|
<ClInclude Include="..\..\Recording\VirtualPad.h">
|
||||||
<Filter>Recording\gui</Filter>
|
<Filter>Recording\gui</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\Recording\InputRecordingControls.h">
|
||||||
|
<Filter>Recording</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\wxResources.rc">
|
<ResourceCompile Include="..\wxResources.rc">
|
||||||
|
|
Loading…
Reference in New Issue