input-rec: Add very basic file viewer to assist with debugging

This commit is contained in:
Tyler Wilding 2022-06-15 20:44:14 -04:00 committed by refractionpcsx2
parent 0a8f5e97e4
commit 8f5458f3ae
10 changed files with 293 additions and 21 deletions

View File

@ -120,6 +120,9 @@ target_sources(pcsx2-qt PRIVATE
Tools/InputRecording/NewInputRecordingDlg.cpp
Tools/InputRecording/NewInputRecordingDlg.h
Tools/InputRecording/NewInputRecordingDlg.ui
Tools/InputRecording/InputRecordingViewer.cpp
Tools/InputRecording/InputRecordingViewer.h
Tools/InputRecording/InputRecordingViewer.ui
resources/resources.qrc
)

View File

@ -37,6 +37,7 @@
#include "pcsx2/HostSettings.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/Recording/InputRecording.h"
#include "pcsx2/Recording/InputRecordingControls.h"
#include "AboutDialog.h"
#include "AutoUpdaterDialog.h"
@ -52,6 +53,7 @@
#include "Settings/InterfaceSettingsWidget.h"
#include "SettingWidgetBinder.h"
#include "svnrev.h"
#include "Tools/InputRecording/InputRecordingViewer.h"
#include "Tools/InputRecording/NewInputRecordingDlg.h"
#ifdef _WIN32
@ -386,6 +388,8 @@ void MainWindow::connectSignals()
connect(m_ui.actionInputRecStop, &QAction::triggered, this, &MainWindow::onInputRecStopActionTriggered);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionInputRecConsoleLogs, "Logging", "EnableInputRecordingLogs", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionInputRecControllerLogs, "Logging", "EnableControllerLogs", false);
connect(m_ui.actionInputRecControllerLogs, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
connect(m_ui.actionInputRecOpenViewer, &QAction::triggered, this, &MainWindow::onInputRecOpenViewer);
// These need to be queued connections to stop crashing due to menus opening/closing and switching focus.
connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress);
@ -1643,11 +1647,13 @@ void MainWindow::onInputRecNewActionTriggered()
if (result == QDialog::Accepted)
{
if (g_InputRecording.Create(
if (g_InputRecording.create(
dlg.getFilePath(),
dlg.getInputRecType() == InputRecording::Type::FROM_SAVESTATE,
dlg.getAuthorName()))
{
m_ui.actionInputRecNew->setEnabled(false);
m_ui.actionInputRecStop->setEnabled(true);
return;
}
}
@ -1658,14 +1664,14 @@ void MainWindow::onInputRecNewActionTriggered()
}
}
#include "pcsx2/Recording/InputRecordingControls.h"
void MainWindow::onInputRecPlayActionTriggered()
{
const bool wasPaused = s_vm_paused;
if (!wasPaused)
g_InputRecordingControls.PauseImmediately();
{
VMManager::SetPaused(true);
}
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::ExistingFile);
@ -1676,30 +1682,37 @@ void MainWindow::onInputRecPlayActionTriggered()
{
fileNames = dialog.selectedFiles();
}
if (fileNames.length() > 0)
else
{
if (g_InputRecording.IsActive())
{
g_InputRecording.Stop();
}
if (g_InputRecording.Play(fileNames.first().toStdString()))
if (!wasPaused)
{
VMManager::SetPaused(false);
return;
}
}
if (!wasPaused)
if (fileNames.length() > 0)
{
g_InputRecordingControls.Resume();
if (g_InputRecording.isActive())
{
g_InputRecording.stop();
m_ui.actionInputRecStop->setEnabled(false);
}
if (g_InputRecording.play(fileNames.first().toStdString()))
{
m_ui.actionInputRecStop->setEnabled(true);
return;
}
}
}
void MainWindow::onInputRecStopActionTriggered()
{
if (g_InputRecording.IsActive())
if (g_InputRecording.isActive())
{
g_InputRecording.Stop();
g_InputRecording.stop();
m_ui.actionInputRecNew->setEnabled(true);
m_ui.actionInputRecStop->setEnabled(false);
}
}
@ -1708,6 +1721,32 @@ void MainWindow::onInputRecOpenSettingsTriggered()
// TODO - Vaser - Implement
}
InputRecordingViewer* MainWindow::getInputRecordingViewer()
{
if (!m_input_recording_viewer)
{
m_input_recording_viewer = new InputRecordingViewer(this);
}
return m_input_recording_viewer;
}
void MainWindow::updateInputRecordingActions(bool started)
{
m_ui.actionInputRecNew->setEnabled(started);
m_ui.actionInputRecPlay->setEnabled(started);
}
void MainWindow::onInputRecOpenViewer()
{
InputRecordingViewer* viewer = getInputRecordingViewer();
if (!viewer->isVisible())
{
viewer->show();
}
}
void MainWindow::onVMStarting()
{
s_vm_valid = true;
@ -1725,6 +1764,7 @@ void MainWindow::onVMStarted()
updateEmulationActions(true, true);
updateWindowTitle();
updateStatusBarWidgetVisibility();
updateInputRecordingActions(true);
}
void MainWindow::onVMPaused()
@ -1778,6 +1818,7 @@ void MainWindow::onVMStopped()
updateWindowTitle();
updateWindowState();
updateStatusBarWidgetVisibility();
updateInputRecordingActions(false);
if (m_display_widget)
{

View File

@ -22,6 +22,7 @@
#include <functional>
#include <optional>
#include "Tools/InputRecording/InputRecordingViewer.h"
#include "Settings/ControllerSettingsDialog.h"
#include "Settings/SettingsDialog.h"
#include "ui_MainWindow.h"
@ -163,6 +164,7 @@ private Q_SLOTS:
void onInputRecPlayActionTriggered();
void onInputRecStopActionTriggered();
void onInputRecOpenSettingsTriggered();
void onInputRecOpenViewer();
void onVMStarting();
void onVMStarted();
@ -224,6 +226,9 @@ private:
SettingsDialog* getSettingsDialog();
void doSettings(const char* category = nullptr);
InputRecordingViewer* getInputRecordingViewer();
void updateInputRecordingActions(bool started);
ControllerSettingsDialog* getControllerSettingsDialog();
void doControllerSettings(ControllerSettingsDialog::Category category = ControllerSettingsDialog::Category::Count);
@ -250,6 +255,7 @@ private:
DisplayContainer* m_display_container = nullptr;
SettingsDialog* m_settings_dialog = nullptr;
InputRecordingViewer* m_input_recording_viewer = nullptr;
ControllerSettingsDialog* m_controller_settings_dialog = nullptr;
AutoUpdaterDialog* m_auto_updater_dialog = nullptr;

View File

@ -176,6 +176,7 @@
<addaction name="actionInputRecPlay"/>
<addaction name="actionInputRecStop"/>
<addaction name="separator"/>
<addaction name="actionInputRecOpenViewer"/>
<addaction name="actionInputRecOpenSettings"/>
<addaction name="separator"/>
<addaction name="actionInputRecConsoleLogs"/>
@ -864,6 +865,11 @@
<string>Show Advanced Settings</string>
</property>
</action>
<action name="actionInputRecOpenViewer">
<property name="text">
<string>Recording Viewer</string>
</property>
</action>
</widget>
<resources>
<include location="resources/resources.qrc"/>

View File

@ -0,0 +1,91 @@
/* PCSX2 - PS2 Emulator for PCs
* 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-
* 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 "InputRecordingViewer.h"
#include "QtUtils.h"
#include <QtCore/QString>
#include <QtWidgets/QDialog>
#include <QtWidgets/qfiledialog.h>
// TODO - for now this uses a very naive implementation that fills the entire table
// this needs to be replaced with a lazy-loading QTableView implementation
//
// For now, especially for just debugging input recording issues, its good enough!
InputRecordingViewer::InputRecordingViewer(QWidget* parent)
: QMainWindow(parent)
{
m_ui.setupUi(this);
m_ui.tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
connect(m_ui.actionOpen, &QAction::triggered, this, &InputRecordingViewer::openFile);
}
void InputRecordingViewer::loadTable()
{
// TODO - only port 1 for now
auto data = m_file.bulkReadPadData(0, m_file.getTotalFrames(), 0);
m_ui.tableWidget->setRowCount(data.size());
auto headers = QStringList({"Left Analog", "Right Analog", "Cross", "Square", "Triangle", "Circle", "L1", "R1", "L2", "R2", "⬇️", "➡️", "⬆️", "⬅️", "L3", "R3", "Select", "Start"});
m_ui.tableWidget->setColumnCount(headers.length());
m_ui.tableWidget->setHorizontalHeaderLabels(headers);
int frameNum = 0;
for (auto& const frame : data)
{
// TODO - disgusting, clean it up
m_ui.tableWidget->setItem(frameNum, 0, new QTableWidgetItem(tr("%1 %2").arg(frame.leftAnalogX).arg(frame.leftAnalogY)));
m_ui.tableWidget->setItem(frameNum, 1, new QTableWidgetItem(tr("%1 %2").arg(frame.rightAnalogX).arg(frame.rightAnalogY)));
m_ui.tableWidget->setItem(frameNum, 2, new QTableWidgetItem(tr("%1 [%2]").arg(frame.crossPressed).arg(frame.crossPressure)));
m_ui.tableWidget->setItem(frameNum, 3, new QTableWidgetItem(tr("%1 [%2]").arg(frame.squarePressed).arg(frame.squarePressure)));
m_ui.tableWidget->setItem(frameNum, 4, new QTableWidgetItem(tr("%1 [%2]").arg(frame.trianglePressed).arg(frame.trianglePressure)));
m_ui.tableWidget->setItem(frameNum, 5, new QTableWidgetItem(tr("%1 [%2]").arg(frame.circlePressed).arg(frame.circlePressure)));
m_ui.tableWidget->setItem(frameNum, 6, new QTableWidgetItem(tr("%1 [%2]").arg(frame.l1Pressed).arg(frame.l1Pressure)));
m_ui.tableWidget->setItem(frameNum, 7, new QTableWidgetItem(tr("%1 [%2]").arg(frame.l2Pressed).arg(frame.l2Pressure)));
m_ui.tableWidget->setItem(frameNum, 8, new QTableWidgetItem(tr("%1 [%2]").arg(frame.r1Pressed).arg(frame.r1Pressure)));
m_ui.tableWidget->setItem(frameNum, 9, new QTableWidgetItem(tr("%1 [%2]").arg(frame.r1Pressed).arg(frame.r2Pressure)));
m_ui.tableWidget->setItem(frameNum, 10, new QTableWidgetItem(tr("%1 [%2]").arg(frame.downPressed).arg(frame.downPressure)));
m_ui.tableWidget->setItem(frameNum, 11, new QTableWidgetItem(tr("%1 [%2]").arg(frame.rightPressed).arg(frame.rightPressure)));
m_ui.tableWidget->setItem(frameNum, 12, new QTableWidgetItem(tr("%1 [%2]").arg(frame.upPressed).arg(frame.upPressure)));
m_ui.tableWidget->setItem(frameNum, 13, new QTableWidgetItem(tr("%1 [%2]").arg(frame.leftPressed).arg(frame.leftPressure)));
m_ui.tableWidget->setItem(frameNum, 14, new QTableWidgetItem(tr("%1").arg(frame.l3)));
m_ui.tableWidget->setItem(frameNum, 15, new QTableWidgetItem(tr("%1").arg(frame.r3)));
m_ui.tableWidget->setItem(frameNum, 16, new QTableWidgetItem(tr("%1").arg(frame.select)));
m_ui.tableWidget->setItem(frameNum, 17, new QTableWidgetItem(tr("%1").arg(frame.start)));
frameNum++;
}
}
void InputRecordingViewer::openFile() {
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setWindowTitle("Select a File");
dialog.setNameFilter(tr("Input Recording Files (*.p2m2)"));
QStringList fileNames;
if (dialog.exec())
{
fileNames = dialog.selectedFiles();
}
if (!fileNames.isEmpty())
{
std::string fileName = fileNames.first().toStdString();
m_file.OpenExisting(fileName);
loadTable();
}
}

View File

@ -0,0 +1,39 @@
/* PCSX2 - PS2 Emulator for PCs
* 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-
* 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
#include "ui_InputRecordingViewer.h"
#include "pcsx2/Recording/InputRecordingFile.h"
class InputRecordingViewer final : public QMainWindow
{
Q_OBJECT
public:
explicit InputRecordingViewer(QWidget* parent = nullptr);
~InputRecordingViewer() = default;
private Q_SLOTS:
void openFile();
private:
Ui::InputRecordingViewer m_ui;
InputRecordingFile m_file;
void loadTable();
};

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InputRecordingViewer</class>
<widget class="QMainWindow" name="InputRecordingViewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Input Recording Viewer</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="enabled">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="tableWidget"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionOpen"/>
</widget>
<widget class="QMenu" name="menuTest">
<property name="title">
<string>Edit</string>
</property>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuTest"/>
<addaction name="menuView"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="9"/>
<resources/>
<connections/>
</ui>

View File

@ -137,6 +137,7 @@
<ClCompile Include="QtProgressCallback.cpp" />
<ClCompile Include="Settings\FolderSettingsWidget.cpp" />
<ClCompile Include="Settings\MemoryCardConvertWorker.cpp" />
<ClCompile Include="Tools\InputRecording\InputRecordingViewer.cpp" />
<ClCompile Include="Tools\InputRecording\NewInputRecordingDlg.cpp" />
<ClCompile Include="Settings\BIOSSettingsWidget.cpp" />
<ClCompile Include="Settings\ControllerBindingWidgets.cpp" />
@ -209,6 +210,7 @@
<QtMoc Include="GameList\GameListWidget.h" />
<QtMoc Include="GameList\GameListRefreshThread.h" />
<QtMoc Include="Tools\InputRecording\NewInputRecordingDlg.h" />
<QtMoc Include="Tools\InputRecording\InputRecordingViewer.h" />
<ClInclude Include="QtUtils.h" />
<QtMoc Include="Settings\ControllerBindingWidgets.h" />
<QtMoc Include="Settings\ControllerGlobalSettingsWidget.h" />
@ -264,6 +266,7 @@
<ClCompile Include="$(IntDir)moc_QtHost.cpp" />
<ClCompile Include="$(IntDir)moc_QtProgressCallback.cpp" />
<ClCompile Include="$(IntDir)Tools\InputRecording\moc_NewInputRecordingDlg.cpp" />
<ClCompile Include="$(IntDir)Tools\InputRecording\moc_InputRecordingViewer.cpp" />
<ClCompile Include="$(IntDir)qrc_resources.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@ -353,6 +356,9 @@
<QtUi Include="Settings\AchievementSettingsWidget.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Tools\InputRecording\InputRecordingViewer.ui">
<FileType>Document</FileType>
</QtUi>
</ItemGroup>
<ItemGroup>
<QtUi Include="Settings\ControllerMacroEditWidget.ui">

View File

@ -211,6 +211,9 @@
<ClCompile Include="$(IntDir)Tools\InputRecording\moc_NewInputRecordingDlg.cpp">
<Filter>moc</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)Tools\InputRecording\moc_InputRecordingViewer.cpp">
<Filter>moc</Filter>
</ClCompile>
<ClCompile Include="Tools\InputRecording\NewInputRecordingDlg.cpp">
<Filter>Tools\Input Recording</Filter>
</ClCompile>
@ -244,6 +247,9 @@
<ClCompile Include="Settings\MemoryCardConvertWorker.cpp">
<Filter>Settings</Filter>
</ClCompile>
<ClCompile Include="Tools\InputRecording\InputRecordingViewer.cpp">
<Filter>Tools\Input Recording</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Manifest Include="..\pcsx2\windows\PCSX2.manifest">
@ -263,6 +269,9 @@
<ClInclude Include="Settings\MemoryCardConvertWorker.h">
<Filter>Settings</Filter>
</ClInclude>
<ClInclude Include="Tools\InputRecording\InputRecordingViewer.h">
<Filter>Tools\Input Recording</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtMoc Include="MainWindow.h" />
@ -450,6 +459,9 @@
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="CoverDownloadDialog.ui" />
<QtUi Include="Tools\InputRecording\InputRecordingViewer.ui">
<Filter>Tools\Input Recording</Filter>
</QtUi>
</ItemGroup>
<ItemGroup>
<None Include="Settings\FolderSettingsWidget.ui">

View File

@ -238,6 +238,9 @@
<Filter Include="Tools\Input Recording">
<UniqueIdentifier>{03ba2aa7-2cd9-48cb-93c6-fc93d5bdc938}</UniqueIdentifier>
</Filter>
<Filter Include="Tools\Input Recording\Utilities">
<UniqueIdentifier>{78c9db9c-9c7c-4385-90e7-9fa71b922f60}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="Utilities\folderdesc.txt">
@ -1263,12 +1266,12 @@
<ClCompile Include="Recording\InputRecordingFile.cpp">
<Filter>Tools\Input Recording</Filter>
</ClCompile>
<ClCompile Include="Recording\Utilities\InputRecordingLogger.cpp">
<Filter>Tools\Input Recording</Filter>
</ClCompile>
<ClCompile Include="Recording\PadData.cpp">
<Filter>Tools\Input Recording</Filter>
</ClCompile>
<ClCompile Include="Recording\Utilities\InputRecordingLogger.cpp">
<Filter>Tools\Input Recording\Utilities</Filter>
</ClCompile>
<ClCompile Include="Frontend\LogSink.cpp">
<Filter>Host</Filter>
</ClCompile>
@ -2128,12 +2131,12 @@
<ClInclude Include="Recording\InputRecordingFile.h">
<Filter>Tools\Input Recording</Filter>
</ClInclude>
<ClInclude Include="Recording\Utilities\InputRecordingLogger.h">
<Filter>Tools\Input Recording</Filter>
</ClInclude>
<ClInclude Include="Recording\PadData.h">
<Filter>Tools\Input Recording</Filter>
</ClInclude>
<ClInclude Include="Recording\Utilities\InputRecordingLogger.h">
<Filter>Tools\Input Recording\Utilities</Filter>
</ClInclude>
<ClInclude Include="Frontend\LogSink.h">
<Filter>Host</Filter>
</ClInclude>