recording: Log all PadData and draw all VirtualPads altogether once per frame

Fixes improper virtualPad behavior for games that do not check for button pressure values (ex: Sonic Mega Collection Plus)
This commit is contained in:
sonicfind 2020-12-15 11:15:51 -06:00 committed by refractionpcsx2
parent ca5d78e7a5
commit a1b6f0b76a
4 changed files with 69 additions and 50 deletions

View File

@ -97,58 +97,58 @@ void InputRecording::ControllerInterrupt(u8& data, u8& port, u16& bufCount, u8 b
if (bufCount == 1) if (bufCount == 1)
fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE; fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE;
else if (bufCount == 2 && buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE) else if (bufCount == 2)
fInterruptFrame = false; {
if (buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE)
// We do not want to record or save the first two bytes in the data returned from the PAD plugin fInterruptFrame = false;
else if (fInterruptFrame && bufCount >= 3 && frameCounter >= 0 && frameCounter < INT_MAX) }
else if (fInterruptFrame)
{ {
u8& bufVal = buf[bufCount]; u8& bufVal = buf[bufCount];
const u16 bufIndex = bufCount - 3; const u16 bufIndex = bufCount - 3;
if (state == InputRecordingMode::Replaying) if (state == InputRecordingMode::Replaying)
{ {
u8 tmp = 0; if (frameCounter >= 0 && frameCounter < INT_MAX)
if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufIndex))
{ {
// Overwrite value originally provided by the PAD plugin if (!inputRecordingData.ReadKeyBuffer(bufVal, frameCounter, port, bufIndex))
bufVal = tmp; inputRec::consoleLog(fmt::format("[REC]: Failed to read input data at frame {}", frameCounter));
// Update controller data state for future VirtualPad / logging usage.
padData[port]->UpdateControllerData(bufIndex, bufVal);
if (virtualPads[port]->IsShown())
virtualPads[port]->UpdateControllerData(bufIndex, padData[port]);
} }
} }
else
// Update controller data state for future VirtualPad / logging usage.
padData[port]->UpdateControllerData(bufIndex, bufVal);
if (virtualPads[port] &&
virtualPads[port]->IsShown() &&
virtualPads[port]->UpdateControllerData(bufIndex, padData[port]) &&
state != InputRecordingMode::Replaying)
{ {
// Update controller data state for future VirtualPad / logging usage.
padData[port]->UpdateControllerData(bufIndex, bufVal);
// Commit the byte to the movie file if we are recording
if (state == InputRecordingMode::Recording)
{
if (frameCounter >= 0)
{
// If the VirtualPad updated the PadData, we have to update the buffer
// before committing it to the recording / sending it to the game
if (virtualPads[port]->IsShown() && virtualPads[port]->UpdateControllerData(bufIndex, padData[port]))
bufVal = padData[port]->PollControllerData(bufIndex);
if (incrementUndo)
{
inputRecordingData.IncrementUndoCount();
incrementUndo = false;
}
if (frameCounter < INT_MAX && !inputRecordingData.WriteKeyBuffer(frameCounter, port, bufIndex, bufVal))
inputRec::consoleLog(fmt::format("[REC]: Failed to write input data at frame {}", frameCounter));
}
}
// If the VirtualPad updated the PadData, we have to update the buffer // If the VirtualPad updated the PadData, we have to update the buffer
// before committing it to the recording / sending it to the game // before sending it to the game
// - Do not do this if we are in replay mode! else if (virtualPads[port]->IsShown() && virtualPads[port]->UpdateControllerData(bufIndex, padData[port]))
bufVal = padData[port]->PollControllerData(bufIndex); bufVal = padData[port]->PollControllerData(bufIndex);
}
// If we have reached the end of the pad data, log it out
if (bufIndex == PadData::END_INDEX_CONTROLLER_BUFFER)
{
padData[port]->LogPadData(port);
// As well as re-render the virtual pad UI, if applicable
// - Don't render if it's minimized
if (virtualPads[port] && virtualPads[port]->IsShown() && !virtualPads[port]->IsIconized())
virtualPads[port]->Redraw();
}
// Finally, commit the byte to the movie file if we are recording
if (state == InputRecordingMode::Recording)
{
if (incrementUndo)
{
inputRecordingData.IncrementUndoCount();
incrementUndo = false;
}
inputRecordingData.WriteKeyBuffer(frameCounter, port, bufIndex, bufVal);
} }
} }
} }
@ -170,12 +170,31 @@ u32 InputRecording::GetStartingFrame()
void InputRecording::IncrementFrameCounter() void InputRecording::IncrementFrameCounter()
{ {
frameCounter++; if (frameCounter < INT_MAX)
if (state == InputRecordingMode::Recording)
{ {
GetInputRecordingData().SetTotalFrames(frameCounter); frameCounter++;
if (frameCounter == inputRecordingData.GetTotalFrames()) switch (state)
incrementUndo = false; {
case InputRecordingMode::Recording:
GetInputRecordingData().SetTotalFrames(frameCounter);
[[fallthrough]];
case InputRecordingMode::Replaying:
if (frameCounter == inputRecordingData.GetTotalFrames())
incrementUndo = false;
}
}
g_InputRecording.LogAndRedraw();
}
void InputRecording::LogAndRedraw()
{
for (u8 port = 0; port < 2; port++)
{
padData[port]->LogPadData(port);
// As well as re-render the virtual pad UI, if applicable
// - Don't render if it's minimized
if (virtualPads[port]->IsShown() && !virtualPads[port]->IsIconized())
virtualPads[port]->Redraw();
} }
} }

View File

@ -89,6 +89,8 @@ public:
void Stop(); void Stop();
// Initialze VirtualPad window // Initialze VirtualPad window
void setVirtualPadPtr(VirtualPad* ptr, int const port); void setVirtualPadPtr(VirtualPad* ptr, int const port);
// 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 // Resets a recording if the base savestate could not be loaded at the start
void FailedSavestate(); void FailedSavestate();

View File

@ -60,8 +60,7 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
else if (frameCountTracker != g_FrameCount) else if (frameCountTracker != g_FrameCount)
{ {
frameCountTracker = g_FrameCount; frameCountTracker = g_FrameCount;
if (g_InputRecording.GetFrameCounter() < INT_MAX) g_InputRecording.IncrementFrameCounter();
g_InputRecording.IncrementFrameCounter();
} }
else else
{ {

View File

@ -22,7 +22,6 @@ class PadData
public: public:
/// Constants /// Constants
static const u8 ANALOG_VECTOR_NEUTRAL = 127; static const u8 ANALOG_VECTOR_NEUTRAL = 127;
static const u16 END_INDEX_CONTROLLER_BUFFER = 17;
enum class BufferIndex enum class BufferIndex
{ {