Sources: Run clang-format on everything.
This commit is contained in:
parent
fe948af095
commit
dc8479928c
386 changed files with 19560 additions and 18080 deletions
|
@ -9,13 +9,12 @@
|
|||
#include "common/common_types.h"
|
||||
#include "common/symbols.h"
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/disassembler/arm_disasm.h"
|
||||
#include "core/core.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
|
||||
{
|
||||
CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) {
|
||||
ui.setupUi(this);
|
||||
|
||||
callstack_model = new QStandardItemModel(this);
|
||||
|
@ -27,29 +26,26 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
|
|||
ui.treeView->setModel(callstack_model);
|
||||
}
|
||||
|
||||
void CallstackWidget::OnDebugModeEntered()
|
||||
{
|
||||
void CallstackWidget::OnDebugModeEntered() {
|
||||
// Stack pointer
|
||||
const u32 sp = Core::g_app_core->GetReg(13);
|
||||
|
||||
Clear();
|
||||
|
||||
int counter = 0;
|
||||
for (u32 addr = 0x10000000; addr >= sp; addr -= 4)
|
||||
{
|
||||
for (u32 addr = 0x10000000; addr >= sp; addr -= 4) {
|
||||
if (!Memory::IsValidVirtualAddress(addr))
|
||||
break;
|
||||
|
||||
const u32 ret_addr = Memory::Read32(addr);
|
||||
const u32 call_addr = ret_addr - 4; //get call address???
|
||||
const u32 call_addr = ret_addr - 4; // get call address???
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(call_addr))
|
||||
break;
|
||||
|
||||
/* TODO (mattvail) clean me, move to debugger interface */
|
||||
u32 insn = Memory::Read32(call_addr);
|
||||
if (ARM_Disasm::Decode(insn) == OP_BL)
|
||||
{
|
||||
if (ARM_Disasm::Decode(insn) == OP_BL) {
|
||||
std::string name;
|
||||
// ripped from disasm
|
||||
u8 cond = (insn >> 28) & 0xf;
|
||||
|
@ -63,26 +59,29 @@ void CallstackWidget::OnDebugModeEntered()
|
|||
i_offset += 8;
|
||||
const u32 func_addr = call_addr + i_offset;
|
||||
|
||||
callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
|
||||
callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0'))));
|
||||
callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0'))));
|
||||
callstack_model->setItem(
|
||||
counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
|
||||
callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(
|
||||
ret_addr, 8, 16, QLatin1Char('0'))));
|
||||
callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(
|
||||
call_addr, 8, 16, QLatin1Char('0'))));
|
||||
|
||||
name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown";
|
||||
callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name))
|
||||
.arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
|
||||
callstack_model->setItem(
|
||||
counter, 3, new QStandardItem(
|
||||
QString("%1_%2")
|
||||
.arg(QString::fromStdString(name))
|
||||
.arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CallstackWidget::OnDebugModeLeft()
|
||||
{
|
||||
|
||||
void CallstackWidget::OnDebugModeLeft() {
|
||||
}
|
||||
|
||||
void CallstackWidget::Clear()
|
||||
{
|
||||
void CallstackWidget::Clear() {
|
||||
for (int row = 0; row < callstack_model->rowCount(); row++) {
|
||||
for (int column = 0; column < callstack_model->columnCount(); column++) {
|
||||
callstack_model->setItem(row, column, new QStandardItem());
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
class QStandardItemModel;
|
||||
|
||||
class CallstackWidget : public QDockWidget
|
||||
{
|
||||
class CallstackWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -5,20 +5,21 @@
|
|||
#include <QShortcut>
|
||||
|
||||
#include "citra_qt/bootmanager.h"
|
||||
#include "citra_qt/hotkeys.h"
|
||||
#include "citra_qt/debugger/disassembler.h"
|
||||
#include "citra_qt/hotkeys.h"
|
||||
#include "citra_qt/util/util.h"
|
||||
|
||||
#include "common/break_points.h"
|
||||
#include "common/symbols.h"
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/disassembler/arm_disasm.h"
|
||||
#include "core/core.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
DisassemblerModel::DisassemblerModel(QObject* parent) :
|
||||
QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {
|
||||
DisassemblerModel::DisassemblerModel(QObject* parent)
|
||||
: QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0),
|
||||
selection(QModelIndex()) {
|
||||
}
|
||||
|
||||
int DisassemblerModel::columnCount(const QModelIndex& parent) const {
|
||||
|
@ -31,62 +32,60 @@ int DisassemblerModel::rowCount(const QModelIndex& parent) const {
|
|||
|
||||
QVariant DisassemblerModel::data(const QModelIndex& index, int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
u32 address = base_address + index.row() * 4;
|
||||
u32 instr = Memory::Read32(address);
|
||||
std::string disassembly = ARM_Disasm::Disassemble(address, instr);
|
||||
case Qt::DisplayRole: {
|
||||
u32 address = base_address + index.row() * 4;
|
||||
u32 instr = Memory::Read32(address);
|
||||
std::string disassembly = ARM_Disasm::Disassemble(address, instr);
|
||||
|
||||
if (index.column() == 0) {
|
||||
return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0'));
|
||||
} else if (index.column() == 1) {
|
||||
return QString::fromStdString(disassembly);
|
||||
} else if (index.column() == 2) {
|
||||
if(Symbols::HasSymbol(address)) {
|
||||
TSymbol symbol = Symbols::GetSymbol(address);
|
||||
return QString("%1 - Size:%2").arg(QString::fromStdString(symbol.name))
|
||||
.arg(symbol.size / 4); // divide by 4 to get instruction count
|
||||
} else if (ARM_Disasm::Decode(instr) == OP_BL) {
|
||||
u32 offset = instr & 0xFFFFFF;
|
||||
if (index.column() == 0) {
|
||||
return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0'));
|
||||
} else if (index.column() == 1) {
|
||||
return QString::fromStdString(disassembly);
|
||||
} else if (index.column() == 2) {
|
||||
if (Symbols::HasSymbol(address)) {
|
||||
TSymbol symbol = Symbols::GetSymbol(address);
|
||||
return QString("%1 - Size:%2")
|
||||
.arg(QString::fromStdString(symbol.name))
|
||||
.arg(symbol.size / 4); // divide by 4 to get instruction count
|
||||
} else if (ARM_Disasm::Decode(instr) == OP_BL) {
|
||||
u32 offset = instr & 0xFFFFFF;
|
||||
|
||||
// Sign-extend the 24-bit offset
|
||||
if ((offset >> 23) & 1)
|
||||
offset |= 0xFF000000;
|
||||
// Sign-extend the 24-bit offset
|
||||
if ((offset >> 23) & 1)
|
||||
offset |= 0xFF000000;
|
||||
|
||||
// Pre-compute the left-shift and the prefetch offset
|
||||
offset <<= 2;
|
||||
offset += 8;
|
||||
// Pre-compute the left-shift and the prefetch offset
|
||||
offset <<= 2;
|
||||
offset += 8;
|
||||
|
||||
TSymbol symbol = Symbols::GetSymbol(address + offset);
|
||||
return QString(" --> %1").arg(QString::fromStdString(symbol.name));
|
||||
}
|
||||
TSymbol symbol = Symbols::GetSymbol(address + offset);
|
||||
return QString(" --> %1").arg(QString::fromStdString(symbol.name));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
unsigned int address = base_address + 4 * index.row();
|
||||
break;
|
||||
}
|
||||
|
||||
if (breakpoints.IsAddressBreakPoint(address))
|
||||
return QBrush(QColor(0xFF, 0xC0, 0xC0));
|
||||
else if (address == program_counter)
|
||||
return QBrush(QColor(0xC0, 0xC0, 0xFF));
|
||||
case Qt::BackgroundRole: {
|
||||
unsigned int address = base_address + 4 * index.row();
|
||||
|
||||
break;
|
||||
if (breakpoints.IsAddressBreakPoint(address))
|
||||
return QBrush(QColor(0xFF, 0xC0, 0xC0));
|
||||
else if (address == program_counter)
|
||||
return QBrush(QColor(0xC0, 0xC0, 0xFF));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::FontRole: {
|
||||
if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column
|
||||
return GetMonospaceFont();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
{
|
||||
if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column
|
||||
return GetMonospaceFont();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
@ -103,7 +102,7 @@ const BreakPoints& DisassemblerModel::GetBreakPoints() const {
|
|||
void DisassemblerModel::ParseFromAddress(unsigned int address) {
|
||||
|
||||
// NOTE: A too large value causes lagging when scrolling the disassembly
|
||||
const unsigned int chunk_size = 1000*500;
|
||||
const unsigned int chunk_size = 1000 * 500;
|
||||
|
||||
// If we haven't loaded anything yet, initialize base address to the parameter address
|
||||
if (code_size == 0)
|
||||
|
@ -165,23 +164,26 @@ void DisassemblerModel::SetNextInstruction(unsigned int address) {
|
|||
emit dataChanged(prev_index, prev_index);
|
||||
}
|
||||
|
||||
DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) :
|
||||
QDockWidget(parent), base_addr(0), emu_thread(emu_thread) {
|
||||
DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread)
|
||||
: QDockWidget(parent), base_addr(0), emu_thread(emu_thread) {
|
||||
|
||||
disasm_ui.setupUi(this);
|
||||
|
||||
RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut);
|
||||
RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut);
|
||||
RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut);
|
||||
RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut);
|
||||
RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9),
|
||||
Qt::ApplicationShortcut);
|
||||
|
||||
connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep()));
|
||||
connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause()));
|
||||
connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue()));
|
||||
|
||||
connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, SLOT(OnToggleStartStop()));
|
||||
connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this,
|
||||
SLOT(OnToggleStartStop()));
|
||||
connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep()));
|
||||
connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto()));
|
||||
connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this,
|
||||
SLOT(OnStepInto()));
|
||||
|
||||
setEnabled(false);
|
||||
}
|
||||
|
@ -195,7 +197,8 @@ void DisassemblerWidget::Init() {
|
|||
|
||||
QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC());
|
||||
disasm_ui.treeView->scrollTo(model_index);
|
||||
disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
disasm_ui.treeView->selectionModel()->setCurrentIndex(
|
||||
model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
void DisassemblerWidget::OnContinue() {
|
||||
|
@ -234,7 +237,8 @@ void DisassemblerWidget::OnDebugModeEntered() {
|
|||
|
||||
QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr);
|
||||
disasm_ui.treeView->scrollTo(model_index);
|
||||
disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
disasm_ui.treeView->selectionModel()->setCurrentIndex(
|
||||
model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
void DisassemblerWidget::OnDebugModeLeft() {
|
||||
|
@ -254,10 +258,12 @@ void DisassemblerWidget::OnEmulationStarting(EmuThread* emu_thread) {
|
|||
model = new DisassemblerModel(this);
|
||||
disasm_ui.treeView->setModel(model);
|
||||
|
||||
connect(disasm_ui.treeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
|
||||
model, SLOT(OnSelectionChanged(const QModelIndex&)));
|
||||
connect(disasm_ui.treeView->selectionModel(),
|
||||
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), model,
|
||||
SLOT(OnSelectionChanged(const QModelIndex&)));
|
||||
connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint()));
|
||||
connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, SLOT(OnSetOrUnsetBreakpoint()));
|
||||
connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model,
|
||||
SLOT(OnSetOrUnsetBreakpoint()));
|
||||
|
||||
Init();
|
||||
setEnabled(true);
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
class QAction;
|
||||
class EmuThread;
|
||||
|
||||
class DisassemblerModel : public QAbstractListModel
|
||||
{
|
||||
class DisassemblerModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -46,8 +45,7 @@ private:
|
|||
mutable BreakPoints breakpoints;
|
||||
};
|
||||
|
||||
class DisassemblerWidget : public QDockWidget
|
||||
{
|
||||
class DisassemblerWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -9,69 +9,62 @@
|
|||
|
||||
extern GraphicsDebugger g_debugger;
|
||||
|
||||
GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0)
|
||||
{
|
||||
GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent)
|
||||
: QAbstractListModel(parent), command_count(0) {
|
||||
connect(this, SIGNAL(GXCommandFinished(int)), this, SLOT(OnGXCommandFinishedInternal(int)));
|
||||
}
|
||||
|
||||
int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const {
|
||||
return command_count;
|
||||
}
|
||||
|
||||
QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const {
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
int command_index = index.row();
|
||||
const GSP_GPU::Command& command = GetDebugger()->ReadGXCommandHistory(command_index);
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
std::map<GSP_GPU::CommandId, const char*> command_names = {
|
||||
{ GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA" },
|
||||
{ GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST" },
|
||||
{ GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL" },
|
||||
{ GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER" },
|
||||
{ GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY" },
|
||||
{ GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH" },
|
||||
{GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA"},
|
||||
{GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST"},
|
||||
{GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL"},
|
||||
{GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER"},
|
||||
{GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY"},
|
||||
{GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH"},
|
||||
};
|
||||
const u32* command_data = reinterpret_cast<const u32*>(&command);
|
||||
QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9").arg(command_names[command.id])
|
||||
.arg(command_data[0], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[1], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[2], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[3], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[4], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[5], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[6], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[7], 8, 16, QLatin1Char('0'));
|
||||
QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9")
|
||||
.arg(command_names[command.id])
|
||||
.arg(command_data[0], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[1], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[2], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[3], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[4], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[5], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[6], 8, 16, QLatin1Char('0'))
|
||||
.arg(command_data[7], 8, 16, QLatin1Char('0'));
|
||||
return QVariant(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count)
|
||||
{
|
||||
void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count) {
|
||||
emit GXCommandFinished(total_command_count);
|
||||
}
|
||||
|
||||
void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count)
|
||||
{
|
||||
void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count) {
|
||||
if (total_command_count == 0)
|
||||
return;
|
||||
|
||||
int prev_command_count = command_count;
|
||||
command_count = total_command_count;
|
||||
emit dataChanged(index(prev_command_count,0), index(total_command_count-1,0));
|
||||
emit dataChanged(index(prev_command_count, 0), index(total_command_count - 1, 0));
|
||||
}
|
||||
|
||||
|
||||
GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) : QDockWidget(tr("Graphics Debugger"), parent)
|
||||
{
|
||||
GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent)
|
||||
: QDockWidget(tr("Graphics Debugger"), parent) {
|
||||
setObjectName("GraphicsDebugger");
|
||||
|
||||
GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#include "video_core/gpu_debugger.h"
|
||||
|
||||
class GPUCommandStreamItemModel : public QAbstractListModel, public GraphicsDebugger::DebuggerObserver
|
||||
{
|
||||
class GPUCommandStreamItemModel : public QAbstractListModel,
|
||||
public GraphicsDebugger::DebuggerObserver {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -32,8 +32,7 @@ private:
|
|||
int command_count;
|
||||
};
|
||||
|
||||
class GPUCommandStreamWidget : public QDockWidget
|
||||
{
|
||||
class GPUCommandStreamWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -8,25 +8,21 @@
|
|||
|
||||
BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context,
|
||||
const QString& title, QWidget* parent)
|
||||
: QDockWidget(title, parent), BreakPointObserver(debug_context)
|
||||
{
|
||||
: QDockWidget(title, parent), BreakPointObserver(debug_context) {
|
||||
qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event");
|
||||
|
||||
connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed()));
|
||||
|
||||
// NOTE: This signal is emitted from a non-GUI thread, but connect() takes
|
||||
// care of delaying its handling to the GUI thread.
|
||||
connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)),
|
||||
this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)),
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), this,
|
||||
SLOT(OnBreakPointHit(Pica::DebugContext::Event, void*)), Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data)
|
||||
{
|
||||
void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) {
|
||||
emit BreakPointHit(event, data);
|
||||
}
|
||||
|
||||
void BreakPointObserverDock::OnPicaResume()
|
||||
{
|
||||
void BreakPointObserverDock::OnPicaResume() {
|
||||
emit Resumed();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
* This is because the Pica breakpoint callbacks are called from a non-GUI thread, while
|
||||
* the widget usually wants to perform reactions in the GUI thread.
|
||||
*/
|
||||
class BreakPointObserverDock : public QDockWidget, protected Pica::DebugContext::BreakPointObserver {
|
||||
class BreakPointObserverDock : public QDockWidget,
|
||||
protected Pica::DebugContext::BreakPointObserver {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -16,39 +16,33 @@
|
|||
BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_context, QObject* parent)
|
||||
: QAbstractListModel(parent), context_weak(debug_context),
|
||||
at_breakpoint(debug_context->at_breakpoint),
|
||||
active_breakpoint(debug_context->active_breakpoint)
|
||||
{
|
||||
|
||||
active_breakpoint(debug_context->active_breakpoint) {
|
||||
}
|
||||
|
||||
int BreakPointModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
int BreakPointModel::columnCount(const QModelIndex& parent) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BreakPointModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
int BreakPointModel::rowCount(const QModelIndex& parent) const {
|
||||
return static_cast<int>(Pica::DebugContext::Event::NumEvents);
|
||||
}
|
||||
|
||||
QVariant BreakPointModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QVariant BreakPointModel::data(const QModelIndex& index, int role) const {
|
||||
const auto event = static_cast<Pica::DebugContext::Event>(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
case Qt::DisplayRole: {
|
||||
if (index.column() == 0) {
|
||||
static const std::map<Pica::DebugContext::Event, QString> map = {
|
||||
{ Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded") },
|
||||
{ Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") },
|
||||
{ Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") },
|
||||
{ Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") },
|
||||
{ Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation") },
|
||||
{ Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") },
|
||||
{ Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") },
|
||||
{ Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") }
|
||||
};
|
||||
{Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded")},
|
||||
{Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed")},
|
||||
{Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")},
|
||||
{Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")},
|
||||
{Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation")},
|
||||
{Pica::DebugContext::Event::IncomingDisplayTransfer,
|
||||
tr("Incoming display transfer")},
|
||||
{Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed")},
|
||||
{Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped")}};
|
||||
|
||||
DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents));
|
||||
return (map.find(event) != map.end()) ? map.at(event) : QString();
|
||||
|
@ -57,23 +51,20 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const
|
|||
break;
|
||||
}
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
{
|
||||
case Qt::CheckStateRole: {
|
||||
if (index.column() == 0)
|
||||
return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked;
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
case Qt::BackgroundRole: {
|
||||
if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) {
|
||||
return QBrush(QColor(0xE0, 0xE0, 0x10));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Role_IsEnabled:
|
||||
{
|
||||
case Role_IsEnabled: {
|
||||
auto context = context_weak.lock();
|
||||
return context && context->breakpoints[(int)event].enabled;
|
||||
}
|
||||
|
@ -84,8 +75,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags BreakPointModel::flags(const QModelIndex& index) const {
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
|
@ -95,14 +85,11 @@ Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const
|
|||
return flags;
|
||||
}
|
||||
|
||||
|
||||
bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
const auto event = static_cast<Pica::DebugContext::Event>(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::CheckStateRole:
|
||||
{
|
||||
case Qt::CheckStateRole: {
|
||||
if (index.column() != 0)
|
||||
return false;
|
||||
|
||||
|
@ -120,9 +107,7 @@ bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, i
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event)
|
||||
{
|
||||
void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) {
|
||||
auto context = context_weak.lock();
|
||||
if (!context)
|
||||
return;
|
||||
|
@ -133,8 +118,7 @@ void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event)
|
|||
createIndex(static_cast<int>(event), 0));
|
||||
}
|
||||
|
||||
void BreakPointModel::OnResumed()
|
||||
{
|
||||
void BreakPointModel::OnResumed() {
|
||||
auto context = context_weak.lock();
|
||||
if (!context)
|
||||
return;
|
||||
|
@ -145,12 +129,10 @@ void BreakPointModel::OnResumed()
|
|||
active_breakpoint = context->active_breakpoint;
|
||||
}
|
||||
|
||||
|
||||
GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context,
|
||||
QWidget* parent)
|
||||
GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(
|
||||
std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent)
|
||||
: QDockWidget(tr("Pica Breakpoints"), parent),
|
||||
Pica::DebugContext::BreakPointObserver(debug_context)
|
||||
{
|
||||
Pica::DebugContext::BreakPointObserver(debug_context) {
|
||||
setObjectName("PicaBreakPointsWidget");
|
||||
|
||||
status_text = new QLabel(tr("Emulation running"));
|
||||
|
@ -165,23 +147,21 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug
|
|||
|
||||
qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event");
|
||||
|
||||
connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)),
|
||||
this, SLOT(OnItemDoubleClicked(const QModelIndex&)));
|
||||
connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), this,
|
||||
SLOT(OnItemDoubleClicked(const QModelIndex&)));
|
||||
|
||||
connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested()));
|
||||
|
||||
connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)),
|
||||
this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)),
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), this,
|
||||
SLOT(OnBreakPointHit(Pica::DebugContext::Event, void*)), Qt::BlockingQueuedConnection);
|
||||
connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed()));
|
||||
|
||||
connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)),
|
||||
breakpoint_model, SLOT(OnBreakPointHit(Pica::DebugContext::Event)),
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), breakpoint_model,
|
||||
SLOT(OnBreakPointHit(Pica::DebugContext::Event)), Qt::BlockingQueuedConnection);
|
||||
connect(this, SIGNAL(Resumed()), breakpoint_model, SLOT(OnResumed()));
|
||||
|
||||
connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)),
|
||||
breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)));
|
||||
connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&, const QModelIndex&)),
|
||||
breakpoint_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)));
|
||||
|
||||
QWidget* main_widget = new QWidget;
|
||||
auto main_layout = new QVBoxLayout;
|
||||
|
@ -197,38 +177,32 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug
|
|||
setWidget(main_widget);
|
||||
}
|
||||
|
||||
void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data)
|
||||
{
|
||||
void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data) {
|
||||
// Process in GUI thread
|
||||
emit BreakPointHit(event, data);
|
||||
}
|
||||
|
||||
void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data)
|
||||
{
|
||||
void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) {
|
||||
status_text->setText(tr("Emulation halted at breakpoint"));
|
||||
resume_button->setEnabled(true);
|
||||
}
|
||||
|
||||
void GraphicsBreakPointsWidget::OnPicaResume()
|
||||
{
|
||||
void GraphicsBreakPointsWidget::OnPicaResume() {
|
||||
// Process in GUI thread
|
||||
emit Resumed();
|
||||
}
|
||||
|
||||
void GraphicsBreakPointsWidget::OnResumed()
|
||||
{
|
||||
void GraphicsBreakPointsWidget::OnResumed() {
|
||||
status_text->setText(tr("Emulation running"));
|
||||
resume_button->setEnabled(false);
|
||||
}
|
||||
|
||||
void GraphicsBreakPointsWidget::OnResumeRequested()
|
||||
{
|
||||
void GraphicsBreakPointsWidget::OnResumeRequested() {
|
||||
if (auto context = context_weak.lock())
|
||||
context->Resume();
|
||||
}
|
||||
|
||||
void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index)
|
||||
{
|
||||
void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) {
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#include "common/vector_math.h"
|
||||
|
||||
#include "video_core/debug_utils/debug_utils.h"
|
||||
#include "video_core/pica.h"
|
||||
#include "video_core/pica_state.h"
|
||||
#include "video_core/debug_utils/debug_utils.h"
|
||||
|
||||
QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) {
|
||||
QImage decoded_image(info.width, info.height, QImage::Format_ARGB32);
|
||||
|
@ -38,7 +38,8 @@ QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) {
|
|||
|
||||
class TextureInfoWidget : public QWidget {
|
||||
public:
|
||||
TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr) : QWidget(parent) {
|
||||
TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr)
|
||||
: QWidget(parent) {
|
||||
QLabel* image_widget = new QLabel;
|
||||
QPixmap image_pixmap = QPixmap::fromImage(LoadTexture(src, info));
|
||||
image_pixmap = image_pixmap.scaled(200, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
@ -51,7 +52,6 @@ public:
|
|||
};
|
||||
|
||||
GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) {
|
||||
|
||||
}
|
||||
|
||||
int GPUCommandListModel::rowCount(const QModelIndex& parent) const {
|
||||
|
@ -70,7 +70,7 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const {
|
|||
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString content;
|
||||
switch ( index.column() ) {
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str());
|
||||
case 1:
|
||||
|
@ -88,9 +88,8 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const {
|
|||
}
|
||||
|
||||
QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
switch(role) {
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return tr("Command Name");
|
||||
|
@ -117,14 +116,14 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&
|
|||
endResetModel();
|
||||
}
|
||||
|
||||
#define COMMAND_IN_RANGE(cmd_id, reg_name) \
|
||||
(cmd_id >= PICA_REG_INDEX(reg_name) && \
|
||||
#define COMMAND_IN_RANGE(cmd_id, reg_name) \
|
||||
(cmd_id >= PICA_REG_INDEX(reg_name) && \
|
||||
cmd_id < PICA_REG_INDEX(reg_name) + sizeof(decltype(Pica::g_state.regs.reg_name)) / 4)
|
||||
|
||||
void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
|
||||
const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
|
||||
if (COMMAND_IN_RANGE(command_id, texture0) ||
|
||||
COMMAND_IN_RANGE(command_id, texture1) ||
|
||||
const unsigned int command_id =
|
||||
list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
|
||||
if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) ||
|
||||
COMMAND_IN_RANGE(command_id, texture2)) {
|
||||
|
||||
unsigned index;
|
||||
|
@ -148,9 +147,9 @@ void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
|
|||
void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
|
||||
QWidget* new_info_widget = nullptr;
|
||||
|
||||
const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
|
||||
if (COMMAND_IN_RANGE(command_id, texture0) ||
|
||||
COMMAND_IN_RANGE(command_id, texture1) ||
|
||||
const unsigned int command_id =
|
||||
list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
|
||||
if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) ||
|
||||
COMMAND_IN_RANGE(command_id, texture2)) {
|
||||
|
||||
unsigned index;
|
||||
|
@ -179,7 +178,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
|
|||
}
|
||||
#undef COMMAND_IN_RANGE
|
||||
|
||||
GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pica Command List"), parent) {
|
||||
GPUCommandListWidget::GPUCommandListWidget(QWidget* parent)
|
||||
: QDockWidget(tr("Pica Command List"), parent) {
|
||||
setObjectName("Pica Command List");
|
||||
GPUCommandListModel* model = new GPUCommandListModel(this);
|
||||
|
||||
|
@ -191,23 +191,24 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi
|
|||
list_widget->setRootIsDecorated(false);
|
||||
list_widget->setUniformRowHeights(true);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
#else
|
||||
list_widget->header()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
#endif
|
||||
|
||||
connect(list_widget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)),
|
||||
this, SLOT(SetCommandInfo(const QModelIndex&)));
|
||||
connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)),
|
||||
this, SLOT(OnCommandDoubleClicked(const QModelIndex&)));
|
||||
connect(list_widget->selectionModel(),
|
||||
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this,
|
||||
SLOT(SetCommandInfo(const QModelIndex&)));
|
||||
connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)), this,
|
||||
SLOT(OnCommandDoubleClicked(const QModelIndex&)));
|
||||
|
||||
toggle_tracing = new QPushButton(tr("Start Tracing"));
|
||||
QPushButton* copy_all = new QPushButton(tr("Copy All"));
|
||||
|
||||
connect(toggle_tracing, SIGNAL(clicked()), this, SLOT(OnToggleTracing()));
|
||||
connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)),
|
||||
model, SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&)));
|
||||
connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)), model,
|
||||
SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&)));
|
||||
|
||||
connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard()));
|
||||
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
#include <QAbstractListModel>
|
||||
#include <QDockWidget>
|
||||
|
||||
#include "video_core/gpu_debugger.h"
|
||||
#include "video_core/debug_utils/debug_utils.h"
|
||||
#include "video_core/gpu_debugger.h"
|
||||
|
||||
class QPushButton;
|
||||
class QTreeView;
|
||||
|
||||
class GPUCommandListModel : public QAbstractListModel
|
||||
{
|
||||
class GPUCommandListModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -27,7 +26,8 @@ public:
|
|||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& trace);
|
||||
|
@ -36,8 +36,7 @@ private:
|
|||
Pica::DebugUtils::PicaTrace pica_trace;
|
||||
};
|
||||
|
||||
class GPUCommandListWidget : public QDockWidget
|
||||
{
|
||||
class GPUCommandListWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -17,18 +17,20 @@
|
|||
|
||||
#include "common/color.h"
|
||||
|
||||
#include "core/memory.h"
|
||||
#include "core/hw/gpu.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
#include "video_core/pica.h"
|
||||
#include "video_core/pica_state.h"
|
||||
#include "video_core/utils.h"
|
||||
|
||||
SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_) : QLabel(parent), surface_widget(surface_widget_) {}
|
||||
SurfacePicture::~SurfacePicture() {}
|
||||
SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_)
|
||||
: QLabel(parent), surface_widget(surface_widget_) {
|
||||
}
|
||||
SurfacePicture::~SurfacePicture() {
|
||||
}
|
||||
|
||||
void SurfacePicture::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
void SurfacePicture::mousePressEvent(QMouseEvent* event) {
|
||||
// Only do something while the left mouse button is held down
|
||||
if (!(event->buttons() & Qt::LeftButton))
|
||||
return;
|
||||
|
@ -41,18 +43,15 @@ void SurfacePicture::mousePressEvent(QMouseEvent* event)
|
|||
event->y() * pixmap()->height() / height());
|
||||
}
|
||||
|
||||
void SurfacePicture::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
void SurfacePicture::mouseMoveEvent(QMouseEvent* event) {
|
||||
// We also want to handle the event if the user moves the mouse while holding down the LMB
|
||||
mousePressEvent(event);
|
||||
}
|
||||
|
||||
|
||||
GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
|
||||
QWidget* parent)
|
||||
QWidget* parent)
|
||||
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent),
|
||||
surface_source(Source::ColorBuffer)
|
||||
{
|
||||
surface_source(Source::ColorBuffer) {
|
||||
setObjectName("PicaSurface");
|
||||
|
||||
surface_source_list = new QComboBox;
|
||||
|
@ -124,13 +123,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext>
|
|||
|
||||
// Connections
|
||||
connect(this, SIGNAL(Update()), this, SLOT(OnUpdate()));
|
||||
connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceSourceChanged(int)));
|
||||
connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this, SLOT(OnSurfaceAddressChanged(qint64)));
|
||||
connect(surface_width_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceWidthChanged(int)));
|
||||
connect(surface_height_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceHeightChanged(int)));
|
||||
connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceFormatChanged(int)));
|
||||
connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerXChanged(int)));
|
||||
connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerYChanged(int)));
|
||||
connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(OnSurfaceSourceChanged(int)));
|
||||
connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this,
|
||||
SLOT(OnSurfaceAddressChanged(qint64)));
|
||||
connect(surface_width_control, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(OnSurfaceWidthChanged(int)));
|
||||
connect(surface_height_control, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(OnSurfaceHeightChanged(int)));
|
||||
connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(OnSurfaceFormatChanged(int)));
|
||||
connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(OnSurfacePickerXChanged(int)));
|
||||
connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(OnSurfacePickerYChanged(int)));
|
||||
connect(save_surface, SIGNAL(clicked()), this, SLOT(SaveSurface()));
|
||||
|
||||
auto main_widget = new QWidget;
|
||||
|
@ -203,25 +209,21 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext>
|
|||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) {
|
||||
emit Update();
|
||||
widget()->setEnabled(true);
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnResumed()
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnResumed() {
|
||||
widget()->setEnabled(false);
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) {
|
||||
surface_source = static_cast<Source>(new_value);
|
||||
emit Update();
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) {
|
||||
if (surface_address != new_value) {
|
||||
surface_address = static_cast<unsigned>(new_value);
|
||||
|
||||
|
@ -230,8 +232,7 @@ void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value)
|
|||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) {
|
||||
if (surface_width != static_cast<unsigned>(new_value)) {
|
||||
surface_width = static_cast<unsigned>(new_value);
|
||||
|
||||
|
@ -240,8 +241,7 @@ void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value)
|
|||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) {
|
||||
if (surface_height != static_cast<unsigned>(new_value)) {
|
||||
surface_height = static_cast<unsigned>(new_value);
|
||||
|
||||
|
@ -250,8 +250,7 @@ void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value)
|
|||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) {
|
||||
if (surface_format != static_cast<Format>(new_value)) {
|
||||
surface_format = static_cast<Format>(new_value);
|
||||
|
||||
|
@ -260,24 +259,21 @@ void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value)
|
|||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) {
|
||||
if (surface_picker_x != new_value) {
|
||||
surface_picker_x = new_value;
|
||||
Pick(surface_picker_x, surface_picker_y);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value)
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) {
|
||||
if (surface_picker_y != new_value) {
|
||||
surface_picker_y = new_value;
|
||||
Pick(surface_picker_x, surface_picker_y);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::Pick(int x, int y)
|
||||
{
|
||||
void GraphicsSurfaceWidget::Pick(int x, int y) {
|
||||
surface_picker_x_control->setValue(x);
|
||||
surface_picker_y_control->setValue(y);
|
||||
|
||||
|
@ -312,74 +308,63 @@ void GraphicsSurfaceWidget::Pick(int x, int y)
|
|||
|
||||
auto GetText = [offset](Format format, const u8* pixel) {
|
||||
switch (format) {
|
||||
case Format::RGBA8:
|
||||
{
|
||||
case Format::RGBA8: {
|
||||
auto value = Color::DecodeRGBA8(pixel) / 255.0f;
|
||||
return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4")
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2))
|
||||
.arg(QString::number(value.a(), 'f', 2));
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2))
|
||||
.arg(QString::number(value.a(), 'f', 2));
|
||||
}
|
||||
case Format::RGB8:
|
||||
{
|
||||
case Format::RGB8: {
|
||||
auto value = Color::DecodeRGB8(pixel) / 255.0f;
|
||||
return QString("Red: %1, Green: %2, Blue: %3")
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2));
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2));
|
||||
}
|
||||
case Format::RGB5A1:
|
||||
{
|
||||
case Format::RGB5A1: {
|
||||
auto value = Color::DecodeRGB5A1(pixel) / 255.0f;
|
||||
return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4")
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2))
|
||||
.arg(QString::number(value.a(), 'f', 2));
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2))
|
||||
.arg(QString::number(value.a(), 'f', 2));
|
||||
}
|
||||
case Format::RGB565:
|
||||
{
|
||||
case Format::RGB565: {
|
||||
auto value = Color::DecodeRGB565(pixel) / 255.0f;
|
||||
return QString("Red: %1, Green: %2, Blue: %3")
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2));
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2));
|
||||
}
|
||||
case Format::RGBA4:
|
||||
{
|
||||
case Format::RGBA4: {
|
||||
auto value = Color::DecodeRGBA4(pixel) / 255.0f;
|
||||
return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4")
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2))
|
||||
.arg(QString::number(value.a(), 'f', 2));
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2))
|
||||
.arg(QString::number(value.b(), 'f', 2))
|
||||
.arg(QString::number(value.a(), 'f', 2));
|
||||
}
|
||||
case Format::IA8:
|
||||
return QString("Index: %1, Alpha: %2")
|
||||
.arg(pixel[0])
|
||||
.arg(pixel[1]);
|
||||
return QString("Index: %1, Alpha: %2").arg(pixel[0]).arg(pixel[1]);
|
||||
case Format::RG8: {
|
||||
auto value = Color::DecodeRG8(pixel) / 255.0f;
|
||||
return QString("Red: %1, Green: %2")
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2));
|
||||
.arg(QString::number(value.r(), 'f', 2))
|
||||
.arg(QString::number(value.g(), 'f', 2));
|
||||
}
|
||||
case Format::I8:
|
||||
return QString("Index: %1").arg(*pixel);
|
||||
case Format::A8:
|
||||
return QString("Alpha: %1").arg(QString::number(*pixel / 255.0f, 'f', 2));
|
||||
case Format::IA4:
|
||||
return QString("Index: %1, Alpha: %2")
|
||||
.arg(*pixel & 0xF)
|
||||
.arg((*pixel & 0xF0) >> 4);
|
||||
case Format::I4:
|
||||
{
|
||||
return QString("Index: %1, Alpha: %2").arg(*pixel & 0xF).arg((*pixel & 0xF0) >> 4);
|
||||
case Format::I4: {
|
||||
u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
|
||||
return QString("Index: %1").arg(i);
|
||||
}
|
||||
case Format::A4:
|
||||
{
|
||||
case Format::A4: {
|
||||
u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
|
||||
return QString("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2));
|
||||
}
|
||||
|
@ -387,21 +372,20 @@ void GraphicsSurfaceWidget::Pick(int x, int y)
|
|||
case Format::ETC1A4:
|
||||
// TODO: Display block information or channel values?
|
||||
return QString("Compressed data");
|
||||
case Format::D16:
|
||||
{
|
||||
case Format::D16: {
|
||||
auto value = Color::DecodeD16(pixel);
|
||||
return QString("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4));
|
||||
}
|
||||
case Format::D24:
|
||||
{
|
||||
case Format::D24: {
|
||||
auto value = Color::DecodeD24(pixel);
|
||||
return QString("Depth: %1").arg(QString::number(value / (float)0xFFFFFF, 'f', 4));
|
||||
}
|
||||
case Format::D24X8:
|
||||
case Format::X24S8:
|
||||
{
|
||||
case Format::X24S8: {
|
||||
auto values = Color::DecodeD24S8(pixel);
|
||||
return QString("Depth: %1, Stencil: %2").arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4)).arg(values[1]);
|
||||
return QString("Depth: %1, Stencil: %2")
|
||||
.arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4))
|
||||
.arg(values[1]);
|
||||
}
|
||||
case Format::Unknown:
|
||||
return QString("Unknown format");
|
||||
|
@ -422,18 +406,18 @@ void GraphicsSurfaceWidget::Pick(int x, int y)
|
|||
nibbles.append(QString::number(nibble, 16).toUpper());
|
||||
}
|
||||
|
||||
surface_info_label->setText(QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel)));
|
||||
surface_info_label->setText(
|
||||
QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel)));
|
||||
surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
}
|
||||
|
||||
void GraphicsSurfaceWidget::OnUpdate()
|
||||
{
|
||||
void GraphicsSurfaceWidget::OnUpdate() {
|
||||
QPixmap pixmap;
|
||||
|
||||
switch (surface_source) {
|
||||
case Source::ColorBuffer:
|
||||
{
|
||||
// TODO: Store a reference to the registers in the debug context instead of accessing them directly...
|
||||
case Source::ColorBuffer: {
|
||||
// TODO: Store a reference to the registers in the debug context instead of accessing them
|
||||
// directly...
|
||||
|
||||
const auto& framebuffer = Pica::g_state.regs.framebuffer;
|
||||
|
||||
|
@ -470,8 +454,7 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
break;
|
||||
}
|
||||
|
||||
case Source::DepthBuffer:
|
||||
{
|
||||
case Source::DepthBuffer: {
|
||||
const auto& framebuffer = Pica::g_state.regs.framebuffer;
|
||||
|
||||
surface_address = framebuffer.GetDepthBufferPhysicalAddress();
|
||||
|
@ -499,8 +482,7 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
break;
|
||||
}
|
||||
|
||||
case Source::StencilBuffer:
|
||||
{
|
||||
case Source::StencilBuffer: {
|
||||
const auto& framebuffer = Pica::g_state.regs.framebuffer;
|
||||
|
||||
surface_address = framebuffer.GetDepthBufferPhysicalAddress();
|
||||
|
@ -522,12 +504,14 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
|
||||
case Source::Texture0:
|
||||
case Source::Texture1:
|
||||
case Source::Texture2:
|
||||
{
|
||||
case Source::Texture2: {
|
||||
unsigned texture_index;
|
||||
if (surface_source == Source::Texture0) texture_index = 0;
|
||||
else if (surface_source == Source::Texture1) texture_index = 1;
|
||||
else if (surface_source == Source::Texture2) texture_index = 2;
|
||||
if (surface_source == Source::Texture0)
|
||||
texture_index = 0;
|
||||
else if (surface_source == Source::Texture1)
|
||||
texture_index = 1;
|
||||
else if (surface_source == Source::Texture2)
|
||||
texture_index = 2;
|
||||
else {
|
||||
qDebug() << "Unknown texture source " << static_cast<int>(surface_source);
|
||||
break;
|
||||
|
@ -547,8 +531,7 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
break;
|
||||
}
|
||||
|
||||
case Source::Custom:
|
||||
{
|
||||
case Source::Custom: {
|
||||
// Keep user-specified values
|
||||
break;
|
||||
}
|
||||
|
@ -613,7 +596,8 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
|
||||
} else {
|
||||
|
||||
ASSERT_MSG(nibbles_per_pixel >= 2, "Depth decoder only supports formats with at least one byte per pixel");
|
||||
ASSERT_MSG(nibbles_per_pixel >= 2,
|
||||
"Depth decoder only supports formats with at least one byte per pixel");
|
||||
unsigned bytes_per_pixel = nibbles_per_pixel / 2;
|
||||
|
||||
for (unsigned int y = 0; y < surface_height; ++y) {
|
||||
|
@ -621,34 +605,30 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
const u32 coarse_y = y & ~7;
|
||||
u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
|
||||
const u8* pixel = buffer + offset;
|
||||
Math::Vec4<u8> color = { 0, 0, 0, 0 };
|
||||
Math::Vec4<u8> color = {0, 0, 0, 0};
|
||||
|
||||
switch(surface_format) {
|
||||
case Format::D16:
|
||||
{
|
||||
switch (surface_format) {
|
||||
case Format::D16: {
|
||||
u32 data = Color::DecodeD16(pixel);
|
||||
color.r() = data & 0xFF;
|
||||
color.g() = (data >> 8) & 0xFF;
|
||||
break;
|
||||
}
|
||||
case Format::D24:
|
||||
{
|
||||
case Format::D24: {
|
||||
u32 data = Color::DecodeD24(pixel);
|
||||
color.r() = data & 0xFF;
|
||||
color.g() = (data >> 8) & 0xFF;
|
||||
color.b() = (data >> 16) & 0xFF;
|
||||
break;
|
||||
}
|
||||
case Format::D24X8:
|
||||
{
|
||||
case Format::D24X8: {
|
||||
Math::Vec2<u32> data = Color::DecodeD24S8(pixel);
|
||||
color.r() = data.x & 0xFF;
|
||||
color.g() = (data.x >> 8) & 0xFF;
|
||||
color.b() = (data.x >> 16) & 0xFF;
|
||||
break;
|
||||
}
|
||||
case Format::X24S8:
|
||||
{
|
||||
case Format::X24S8: {
|
||||
Math::Vec2<u32> data = Color::DecodeD24S8(pixel);
|
||||
color.r() = color.g() = color.b() = data.y;
|
||||
break;
|
||||
|
@ -661,7 +641,6 @@ void GraphicsSurfaceWidget::OnUpdate()
|
|||
decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), 255));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pixmap = QPixmap::fromImage(decoded_image);
|
||||
|
@ -682,8 +661,10 @@ void GraphicsSurfaceWidget::SaveSurface() {
|
|||
QString bin_filter = tr("Binary data (*.bin)");
|
||||
|
||||
QString selectedFilter;
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Save Surface"), QString("texture-0x%1.png").arg(QString::number(surface_address, 16)),
|
||||
QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter);
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
this, tr("Save Surface"),
|
||||
QString("texture-0x%1.png").arg(QString::number(surface_address, 16)),
|
||||
QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter);
|
||||
|
||||
if (filename.isEmpty()) {
|
||||
// If the user canceled the dialog, don't save anything.
|
||||
|
@ -718,19 +699,19 @@ unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Forma
|
|||
}
|
||||
|
||||
switch (format) {
|
||||
case Format::D24X8:
|
||||
case Format::X24S8:
|
||||
return 4 * 2;
|
||||
case Format::D24:
|
||||
return 3 * 2;
|
||||
case Format::D16:
|
||||
return 2 * 2;
|
||||
default:
|
||||
UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this "
|
||||
"should not be reached as this function should "
|
||||
"be given a format which is in "
|
||||
"GraphicsSurfaceWidget::Format. Instead got %i",
|
||||
static_cast<int>(format));
|
||||
return 0;
|
||||
case Format::D24X8:
|
||||
case Format::X24S8:
|
||||
return 4 * 2;
|
||||
case Format::D24:
|
||||
return 3 * 2;
|
||||
case Format::D16:
|
||||
return 2 * 2;
|
||||
default:
|
||||
UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this "
|
||||
"should not be reached as this function should "
|
||||
"be given a format which is in "
|
||||
"GraphicsSurfaceWidget::Format. Instead got %i",
|
||||
static_cast<int>(format));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,7 @@ class CSpinBox;
|
|||
|
||||
class GraphicsSurfaceWidget;
|
||||
|
||||
class SurfacePicture : public QLabel
|
||||
{
|
||||
class SurfacePicture : public QLabel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -29,7 +28,6 @@ protected slots:
|
|||
|
||||
private:
|
||||
GraphicsSurfaceWidget* surface_widget;
|
||||
|
||||
};
|
||||
|
||||
class GraphicsSurfaceWidget : public BreakPointObserverDock {
|
||||
|
@ -38,43 +36,44 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock {
|
|||
using Event = Pica::DebugContext::Event;
|
||||
|
||||
enum class Source {
|
||||
ColorBuffer = 0,
|
||||
DepthBuffer = 1,
|
||||
ColorBuffer = 0,
|
||||
DepthBuffer = 1,
|
||||
StencilBuffer = 2,
|
||||
Texture0 = 3,
|
||||
Texture1 = 4,
|
||||
Texture2 = 5,
|
||||
Custom = 6,
|
||||
Texture0 = 3,
|
||||
Texture1 = 4,
|
||||
Texture2 = 5,
|
||||
Custom = 6,
|
||||
};
|
||||
|
||||
enum class Format {
|
||||
// These must match the TextureFormat type!
|
||||
RGBA8 = 0,
|
||||
RGB8 = 1,
|
||||
RGB5A1 = 2,
|
||||
RGB565 = 3,
|
||||
RGBA4 = 4,
|
||||
IA8 = 5,
|
||||
RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
|
||||
I8 = 7,
|
||||
A8 = 8,
|
||||
IA4 = 9,
|
||||
I4 = 10,
|
||||
A4 = 11,
|
||||
ETC1 = 12, // compressed
|
||||
ETC1A4 = 13,
|
||||
RGBA8 = 0,
|
||||
RGB8 = 1,
|
||||
RGB5A1 = 2,
|
||||
RGB565 = 3,
|
||||
RGBA4 = 4,
|
||||
IA8 = 5,
|
||||
RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
|
||||
I8 = 7,
|
||||
A8 = 8,
|
||||
IA4 = 9,
|
||||
I4 = 10,
|
||||
A4 = 11,
|
||||
ETC1 = 12, // compressed
|
||||
ETC1A4 = 13,
|
||||
MaxTextureFormat = 13,
|
||||
D16 = 14,
|
||||
D24 = 15,
|
||||
D24X8 = 16,
|
||||
X24S8 = 17,
|
||||
Unknown = 18,
|
||||
D16 = 14,
|
||||
D24 = 15,
|
||||
D24X8 = 16,
|
||||
X24S8 = 17,
|
||||
Unknown = 18,
|
||||
};
|
||||
|
||||
static unsigned int NibblesPerPixel(Format format);
|
||||
|
||||
public:
|
||||
GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr);
|
||||
GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
|
||||
QWidget* parent = nullptr);
|
||||
void Pick(int x, int y);
|
||||
|
||||
public slots:
|
||||
|
@ -97,7 +96,6 @@ signals:
|
|||
void Update();
|
||||
|
||||
private:
|
||||
|
||||
QComboBox* surface_source_list;
|
||||
CSpinBox* surface_address_control;
|
||||
QSpinBox* surface_width_control;
|
||||
|
|
|
@ -35,12 +35,16 @@ GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext>
|
|||
setObjectName("CiTracing");
|
||||
|
||||
QPushButton* start_recording = new QPushButton(tr("Start Recording"));
|
||||
QPushButton* stop_recording = new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save"));
|
||||
QPushButton* stop_recording =
|
||||
new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save"));
|
||||
QPushButton* abort_recording = new QPushButton(tr("Abort Recording"));
|
||||
|
||||
connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording, SLOT(setVisible(bool)));
|
||||
connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording, SLOT(setVisible(bool)));
|
||||
connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording, SLOT(setVisible(bool)));
|
||||
connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording,
|
||||
SLOT(setVisible(bool)));
|
||||
connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording,
|
||||
SLOT(setVisible(bool)));
|
||||
connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording,
|
||||
SLOT(setVisible(bool)));
|
||||
connect(start_recording, SIGNAL(clicked()), this, SLOT(StartRecording()));
|
||||
connect(stop_recording, SIGNAL(clicked()), this, SLOT(StopRecording()));
|
||||
connect(abort_recording, SIGNAL(clicked()), this, SLOT(AbortRecording()));
|
||||
|
@ -74,26 +78,31 @@ void GraphicsTracingWidget::StartRecording() {
|
|||
std::array<u32, 4 * 16> default_attributes;
|
||||
for (unsigned i = 0; i < 16; ++i) {
|
||||
for (unsigned comp = 0; comp < 3; ++comp) {
|
||||
default_attributes[4 * i + comp] = nihstro::to_float24(Pica::g_state.vs_default_attributes[i][comp].ToFloat32());
|
||||
default_attributes[4 * i + comp] =
|
||||
nihstro::to_float24(Pica::g_state.vs_default_attributes[i][comp].ToFloat32());
|
||||
}
|
||||
}
|
||||
|
||||
std::array<u32, 4 * 96> vs_float_uniforms;
|
||||
for (unsigned i = 0; i < 96; ++i)
|
||||
for (unsigned comp = 0; comp < 3; ++comp)
|
||||
vs_float_uniforms[4 * i + comp] = nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32());
|
||||
vs_float_uniforms[4 * i + comp] =
|
||||
nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32());
|
||||
|
||||
CiTrace::Recorder::InitialState state;
|
||||
std::copy_n((u32*)&GPU::g_regs, sizeof(GPU::g_regs) / sizeof(u32), std::back_inserter(state.gpu_registers));
|
||||
std::copy_n((u32*)&LCD::g_regs, sizeof(LCD::g_regs) / sizeof(u32), std::back_inserter(state.lcd_registers));
|
||||
std::copy_n((u32*)&Pica::g_state.regs, sizeof(Pica::g_state.regs) / sizeof(u32), std::back_inserter(state.pica_registers));
|
||||
std::copy_n((u32*)&GPU::g_regs, sizeof(GPU::g_regs) / sizeof(u32),
|
||||
std::back_inserter(state.gpu_registers));
|
||||
std::copy_n((u32*)&LCD::g_regs, sizeof(LCD::g_regs) / sizeof(u32),
|
||||
std::back_inserter(state.lcd_registers));
|
||||
std::copy_n((u32*)&Pica::g_state.regs, sizeof(Pica::g_state.regs) / sizeof(u32),
|
||||
std::back_inserter(state.pica_registers));
|
||||
boost::copy(default_attributes, std::back_inserter(state.default_attributes));
|
||||
boost::copy(shader_binary, std::back_inserter(state.vs_program_binary));
|
||||
boost::copy(swizzle_data, std::back_inserter(state.vs_swizzle_data));
|
||||
boost::copy(vs_float_uniforms, std::back_inserter(state.vs_float_uniforms));
|
||||
//boost::copy(TODO: Not implemented, std::back_inserter(state.gs_program_binary));
|
||||
//boost::copy(TODO: Not implemented, std::back_inserter(state.gs_swizzle_data));
|
||||
//boost::copy(TODO: Not implemented, std::back_inserter(state.gs_float_uniforms));
|
||||
// boost::copy(TODO: Not implemented, std::back_inserter(state.gs_program_binary));
|
||||
// boost::copy(TODO: Not implemented, std::back_inserter(state.gs_swizzle_data));
|
||||
// boost::copy(TODO: Not implemented, std::back_inserter(state.gs_float_uniforms));
|
||||
|
||||
auto recorder = new CiTrace::Recorder(state);
|
||||
context->recorder = std::shared_ptr<CiTrace::Recorder>(recorder);
|
||||
|
@ -156,11 +165,12 @@ void GraphicsTracingWidget::OnEmulationStopping() {
|
|||
if (!context)
|
||||
return;
|
||||
|
||||
|
||||
if (context->recorder) {
|
||||
auto reply = QMessageBox::question(this, tr("CiTracing still active"),
|
||||
tr("A CiTrace is still being recorded. Do you want to save it? If not, all recorded data will be discarded."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
auto reply =
|
||||
QMessageBox::question(this, tr("CiTracing still active"),
|
||||
tr("A CiTrace is still being recorded. Do you want to save it? "
|
||||
"If not, all recorded data will be discarded."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
|
||||
if (reply == QMessageBox::Yes) {
|
||||
StopRecording();
|
||||
|
|
|
@ -12,7 +12,8 @@ class GraphicsTracingWidget : public BreakPointObserverDock {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr);
|
||||
GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void StartRecording();
|
||||
|
|
|
@ -28,8 +28,8 @@ using nihstro::Instruction;
|
|||
using nihstro::SourceRegister;
|
||||
using nihstro::SwizzlePattern;
|
||||
|
||||
GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent): QAbstractTableModel(parent), par(parent) {
|
||||
|
||||
GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent)
|
||||
: QAbstractTableModel(parent), par(parent) {
|
||||
}
|
||||
|
||||
int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const {
|
||||
|
@ -40,10 +40,10 @@ int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const {
|
|||
return static_cast<int>(par->info.code.size());
|
||||
}
|
||||
|
||||
QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
switch(role) {
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
if (section == 0) {
|
||||
return tr("Offset");
|
||||
} else if (section == 1) {
|
||||
|
@ -69,8 +69,8 @@ static std::string SelectorToString(u32 selector) {
|
|||
}
|
||||
|
||||
// e.g. "-c92[a0.x].xyzw"
|
||||
static void print_input(std::ostringstream& output, const SourceRegister& input,
|
||||
bool negate, const std::string& swizzle_mask, bool align = true,
|
||||
static void print_input(std::ostringstream& output, const SourceRegister& input, bool negate,
|
||||
const std::string& swizzle_mask, bool align = true,
|
||||
const std::string& address_register_name = std::string()) {
|
||||
if (align)
|
||||
output << std::setw(4) << std::right;
|
||||
|
@ -83,20 +83,18 @@ static void print_input(std::ostringstream& output, const SourceRegister& input,
|
|||
|
||||
QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
case Qt::DisplayRole: {
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
if (par->info.HasLabel(index.row()))
|
||||
return QString::fromStdString(par->info.GetLabel(index.row()));
|
||||
|
||||
return QString("%1").arg(4*index.row(), 4, 16, QLatin1Char('0'));
|
||||
return QString("%1").arg(4 * index.row(), 4, 16, QLatin1Char('0'));
|
||||
|
||||
case 1:
|
||||
return QString("%1").arg(par->info.code[index.row()].hex, 8, 16, QLatin1Char('0'));
|
||||
|
||||
case 2:
|
||||
{
|
||||
case 2: {
|
||||
std::ostringstream output;
|
||||
output.flags(std::ios::uppercase);
|
||||
|
||||
|
@ -117,8 +115,9 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
const Instruction instr = par->info.code[index.row()];
|
||||
const OpCode opcode = instr.opcode;
|
||||
const OpCode::Info opcode_info = opcode.GetInfo();
|
||||
const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd ?
|
||||
instr.mad.operand_desc_id.Value() : instr.common.operand_desc_id.Value();
|
||||
const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd
|
||||
? instr.mad.operand_desc_id.Value()
|
||||
: instr.common.operand_desc_id.Value();
|
||||
const SwizzlePattern swizzle = par->info.swizzle_info[operand_desc_id].pattern;
|
||||
|
||||
// longest known instruction name: "setemit "
|
||||
|
@ -136,15 +135,14 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
break;
|
||||
|
||||
case OpCode::Type::Arithmetic:
|
||||
case OpCode::Type::MultiplyAdd:
|
||||
{
|
||||
case OpCode::Type::MultiplyAdd: {
|
||||
// Use custom code for special instructions
|
||||
switch (opcode.EffectiveOpCode()) {
|
||||
case OpCode::Id::CMP:
|
||||
{
|
||||
case OpCode::Id::CMP: {
|
||||
AlignToColumn(kOpcodeColumnWidth);
|
||||
|
||||
// NOTE: CMP always writes both cc components, so we do not consider the dest mask here.
|
||||
// NOTE: CMP always writes both cc components, so we do not consider the dest
|
||||
// mask here.
|
||||
output << " cc.xy";
|
||||
AlignToColumn(kOutputColumnWidth);
|
||||
|
||||
|
@ -152,22 +150,29 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
SourceRegister src2 = instr.common.GetSrc2(false);
|
||||
|
||||
output << ' ';
|
||||
print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), false, instr.common.AddressRegisterName());
|
||||
output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) << ' ';
|
||||
print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(0,1), false);
|
||||
print_input(output, src1, swizzle.negate_src1,
|
||||
swizzle.SelectorToString(false).substr(0, 1), false,
|
||||
instr.common.AddressRegisterName());
|
||||
output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x)
|
||||
<< ' ';
|
||||
print_input(output, src2, swizzle.negate_src2,
|
||||
swizzle.SelectorToString(true).substr(0, 1), false);
|
||||
|
||||
output << ", ";
|
||||
|
||||
print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), false, instr.common.AddressRegisterName());
|
||||
output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) << ' ';
|
||||
print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(1,1), false);
|
||||
print_input(output, src1, swizzle.negate_src1,
|
||||
swizzle.SelectorToString(false).substr(1, 1), false,
|
||||
instr.common.AddressRegisterName());
|
||||
output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y)
|
||||
<< ' ';
|
||||
print_input(output, src2, swizzle.negate_src2,
|
||||
swizzle.SelectorToString(true).substr(1, 1), false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::Id::MAD:
|
||||
case OpCode::Id::MADI:
|
||||
{
|
||||
case OpCode::Id::MADI: {
|
||||
AlignToColumn(kOpcodeColumnWidth);
|
||||
|
||||
bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed);
|
||||
|
@ -175,34 +180,42 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
SourceRegister src2 = instr.mad.GetSrc2(src_is_inverted);
|
||||
SourceRegister src3 = instr.mad.GetSrc3(src_is_inverted);
|
||||
|
||||
output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.' << swizzle.DestMaskToString();
|
||||
output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.'
|
||||
<< swizzle.DestMaskToString();
|
||||
AlignToColumn(kOutputColumnWidth);
|
||||
print_input(output, src1, swizzle.negate_src1, SelectorToString(swizzle.src1_selector));
|
||||
print_input(output, src1, swizzle.negate_src1,
|
||||
SelectorToString(swizzle.src1_selector));
|
||||
AlignToColumn(kInputOperandColumnWidth);
|
||||
if (src_is_inverted) {
|
||||
print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector));
|
||||
print_input(output, src2, swizzle.negate_src2,
|
||||
SelectorToString(swizzle.src2_selector));
|
||||
} else {
|
||||
print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector), true, instr.mad.AddressRegisterName());
|
||||
print_input(output, src2, swizzle.negate_src2,
|
||||
SelectorToString(swizzle.src2_selector), true,
|
||||
instr.mad.AddressRegisterName());
|
||||
}
|
||||
AlignToColumn(kInputOperandColumnWidth);
|
||||
if (src_is_inverted) {
|
||||
print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector), true, instr.mad.AddressRegisterName());
|
||||
print_input(output, src3, swizzle.negate_src3,
|
||||
SelectorToString(swizzle.src3_selector), true,
|
||||
instr.mad.AddressRegisterName());
|
||||
} else {
|
||||
print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector));
|
||||
print_input(output, src3, swizzle.negate_src3,
|
||||
SelectorToString(swizzle.src3_selector));
|
||||
}
|
||||
AlignToColumn(kInputOperandColumnWidth);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
AlignToColumn(kOpcodeColumnWidth);
|
||||
|
||||
bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed);
|
||||
|
||||
if (opcode_info.subtype & OpCode::Info::Dest) {
|
||||
// e.g. "r12.xy__"
|
||||
output << std::setw(3) << std::right << instr.common.dest.Value().GetName() << '.' << swizzle.DestMaskToString();
|
||||
output << std::setw(3) << std::right << instr.common.dest.Value().GetName()
|
||||
<< '.' << swizzle.DestMaskToString();
|
||||
} else if (opcode_info.subtype == OpCode::Info::MOVA) {
|
||||
output << " a0." << swizzle.DestMaskToString();
|
||||
}
|
||||
|
@ -210,14 +223,18 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
|
||||
if (opcode_info.subtype & OpCode::Info::Src1) {
|
||||
SourceRegister src1 = instr.common.GetSrc1(src_is_inverted);
|
||||
print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), true, instr.common.AddressRegisterName());
|
||||
print_input(output, src1, swizzle.negate_src1,
|
||||
swizzle.SelectorToString(false), true,
|
||||
instr.common.AddressRegisterName());
|
||||
AlignToColumn(kInputOperandColumnWidth);
|
||||
}
|
||||
|
||||
// TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1
|
||||
// TODO: In some cases, the Address Register is used as an index for SRC2
|
||||
// instead of SRC1
|
||||
if (opcode_info.subtype & OpCode::Info::Src2) {
|
||||
SourceRegister src2 = instr.common.GetSrc2(src_is_inverted);
|
||||
print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true));
|
||||
print_input(output, src2, swizzle.negate_src2,
|
||||
swizzle.SelectorToString(true));
|
||||
AlignToColumn(kInputOperandColumnWidth);
|
||||
}
|
||||
break;
|
||||
|
@ -228,8 +245,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
}
|
||||
|
||||
case OpCode::Type::Conditional:
|
||||
case OpCode::Type::UniformFlowControl:
|
||||
{
|
||||
case OpCode::Type::UniformFlowControl: {
|
||||
output << ' ';
|
||||
|
||||
switch (opcode.EffectiveOpCode()) {
|
||||
|
@ -242,7 +258,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
output << '(';
|
||||
|
||||
if (instr.flow_control.op != instr.flow_control.JustY) {
|
||||
if (instr.flow_control.refx) output << '!';
|
||||
if (instr.flow_control.refx)
|
||||
output << '!';
|
||||
output << "cc.x";
|
||||
}
|
||||
|
||||
|
@ -253,7 +270,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
}
|
||||
|
||||
if (instr.flow_control.op != instr.flow_control.JustX) {
|
||||
if (instr.flow_control.refy) output << '!';
|
||||
if (instr.flow_control.refy)
|
||||
output << '!';
|
||||
output << "cc.y";
|
||||
}
|
||||
|
||||
|
@ -266,17 +284,23 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
u32 target_addr_else = instr.flow_control.dest_offset;
|
||||
|
||||
if (opcode_info.subtype & OpCode::Info::HasAlternative) {
|
||||
output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset);
|
||||
output << "else jump to 0x" << std::setw(4) << std::right
|
||||
<< std::setfill('0') << std::hex
|
||||
<< (4 * instr.flow_control.dest_offset);
|
||||
} else if (opcode_info.subtype & OpCode::Info::HasExplicitDest) {
|
||||
output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset);
|
||||
output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0')
|
||||
<< std::hex << (4 * instr.flow_control.dest_offset);
|
||||
} else {
|
||||
// TODO: Handle other cases
|
||||
output << "(unknown destination)";
|
||||
}
|
||||
|
||||
if (opcode_info.subtype & OpCode::Info::HasFinishPoint) {
|
||||
output << " (return on 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex
|
||||
<< (4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions) << ')';
|
||||
output << " (return on 0x" << std::setw(4) << std::right
|
||||
<< std::setfill('0') << std::hex
|
||||
<< (4 * instr.flow_control.dest_offset +
|
||||
4 * instr.flow_control.num_instructions)
|
||||
<< ')';
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -300,8 +324,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
case Qt::FontRole:
|
||||
return GetMonospaceFont();
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
case Qt::BackgroundRole: {
|
||||
// Highlight current instruction
|
||||
int current_record_index = par->cycle_index->value();
|
||||
if (current_record_index < static_cast<int>(par->debug_data.records.size())) {
|
||||
|
@ -319,10 +342,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
return QBrush(QColor(192, 192, 192));
|
||||
}
|
||||
|
||||
|
||||
// TODO: Draw arrows for each "reachable" instruction to visualize control flow
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -331,23 +352,24 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
|
|||
}
|
||||
|
||||
void GraphicsVertexShaderWidget::DumpShader() {
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Save Shader Dump"), "shader_dump.shbin",
|
||||
tr("Shader Binary (*.shbin)"));
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
this, tr("Save Shader Dump"), "shader_dump.shbin", tr("Shader Binary (*.shbin)"));
|
||||
|
||||
if (filename.isEmpty()) {
|
||||
// If the user canceled the dialog, don't dump anything.
|
||||
return;
|
||||
}
|
||||
|
||||
auto& setup = Pica::g_state.vs;
|
||||
auto& setup = Pica::g_state.vs;
|
||||
auto& config = Pica::g_state.regs.vs;
|
||||
|
||||
Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, Pica::g_state.regs.vs_output_attributes);
|
||||
Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup,
|
||||
Pica::g_state.regs.vs_output_attributes);
|
||||
}
|
||||
|
||||
GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::DebugContext > debug_context,
|
||||
QWidget* parent)
|
||||
: BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) {
|
||||
GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(
|
||||
std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent)
|
||||
: BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) {
|
||||
setObjectName("PicaVertexShader");
|
||||
|
||||
// Clear input vertex data so that it contains valid float values in case a debug shader
|
||||
|
@ -365,7 +387,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De
|
|||
input_data[i]->setValidator(new QDoubleValidator(input_data[i]));
|
||||
}
|
||||
|
||||
breakpoint_warning = new QLabel(tr("(data only available at vertex shader invocation breakpoints)"));
|
||||
breakpoint_warning =
|
||||
new QLabel(tr("(data only available at vertex shader invocation breakpoints)"));
|
||||
|
||||
// TODO: Add some button for jumping to the shader entry point
|
||||
|
||||
|
@ -442,7 +465,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De
|
|||
|
||||
// Set a minimum height so that the size of this label doesn't cause the rest of the bottom
|
||||
// part of the UI to keep jumping up and down when cycling through instructions.
|
||||
instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() * 6);
|
||||
instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() *
|
||||
6);
|
||||
instruction_description->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
main_layout->addWidget(instruction_description);
|
||||
|
||||
|
@ -471,7 +495,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d
|
|||
memcpy(&input_vertex, vertex_data, sizeof(input_vertex));
|
||||
for (unsigned attr = 0; attr < 16; ++attr) {
|
||||
for (unsigned comp = 0; comp < 4; ++comp) {
|
||||
input_data[4 * attr + comp]->setText(QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32()));
|
||||
input_data[4 * attr + comp]->setText(
|
||||
QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32()));
|
||||
}
|
||||
}
|
||||
breakpoint_warning->hide();
|
||||
|
@ -498,10 +523,11 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d
|
|||
info.swizzle_info.push_back({pattern});
|
||||
|
||||
u32 entry_point = Pica::g_state.regs.vs.main_offset;
|
||||
info.labels.insert({ entry_point, "main" });
|
||||
info.labels.insert({entry_point, "main"});
|
||||
|
||||
// Generate debug information
|
||||
debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config, shader_setup);
|
||||
debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config,
|
||||
shader_setup);
|
||||
|
||||
// Reload widget state
|
||||
for (int attr = 0; attr < num_attributes; ++attr) {
|
||||
|
@ -537,29 +563,60 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) {
|
|||
|
||||
auto& record = debug_data.records[index];
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::SRC1)
|
||||
text += tr("SRC1: %1, %2, %3, %4\n").arg(record.src1.x.ToFloat32()).arg(record.src1.y.ToFloat32()).arg(record.src1.z.ToFloat32()).arg(record.src1.w.ToFloat32());
|
||||
text += tr("SRC1: %1, %2, %3, %4\n")
|
||||
.arg(record.src1.x.ToFloat32())
|
||||
.arg(record.src1.y.ToFloat32())
|
||||
.arg(record.src1.z.ToFloat32())
|
||||
.arg(record.src1.w.ToFloat32());
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::SRC2)
|
||||
text += tr("SRC2: %1, %2, %3, %4\n").arg(record.src2.x.ToFloat32()).arg(record.src2.y.ToFloat32()).arg(record.src2.z.ToFloat32()).arg(record.src2.w.ToFloat32());
|
||||
text += tr("SRC2: %1, %2, %3, %4\n")
|
||||
.arg(record.src2.x.ToFloat32())
|
||||
.arg(record.src2.y.ToFloat32())
|
||||
.arg(record.src2.z.ToFloat32())
|
||||
.arg(record.src2.w.ToFloat32());
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::SRC3)
|
||||
text += tr("SRC3: %1, %2, %3, %4\n").arg(record.src3.x.ToFloat32()).arg(record.src3.y.ToFloat32()).arg(record.src3.z.ToFloat32()).arg(record.src3.w.ToFloat32());
|
||||
text += tr("SRC3: %1, %2, %3, %4\n")
|
||||
.arg(record.src3.x.ToFloat32())
|
||||
.arg(record.src3.y.ToFloat32())
|
||||
.arg(record.src3.z.ToFloat32())
|
||||
.arg(record.src3.w.ToFloat32());
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::DEST_IN)
|
||||
text += tr("DEST_IN: %1, %2, %3, %4\n").arg(record.dest_in.x.ToFloat32()).arg(record.dest_in.y.ToFloat32()).arg(record.dest_in.z.ToFloat32()).arg(record.dest_in.w.ToFloat32());
|
||||
text += tr("DEST_IN: %1, %2, %3, %4\n")
|
||||
.arg(record.dest_in.x.ToFloat32())
|
||||
.arg(record.dest_in.y.ToFloat32())
|
||||
.arg(record.dest_in.z.ToFloat32())
|
||||
.arg(record.dest_in.w.ToFloat32());
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::DEST_OUT)
|
||||
text += tr("DEST_OUT: %1, %2, %3, %4\n").arg(record.dest_out.x.ToFloat32()).arg(record.dest_out.y.ToFloat32()).arg(record.dest_out.z.ToFloat32()).arg(record.dest_out.w.ToFloat32());
|
||||
text += tr("DEST_OUT: %1, %2, %3, %4\n")
|
||||
.arg(record.dest_out.x.ToFloat32())
|
||||
.arg(record.dest_out.y.ToFloat32())
|
||||
.arg(record.dest_out.z.ToFloat32())
|
||||
.arg(record.dest_out.w.ToFloat32());
|
||||
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::ADDR_REG_OUT)
|
||||
text += tr("Addres Registers: %1, %2\n").arg(record.address_registers[0]).arg(record.address_registers[1]);
|
||||
text += tr("Addres Registers: %1, %2\n")
|
||||
.arg(record.address_registers[0])
|
||||
.arg(record.address_registers[1]);
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::CMP_RESULT)
|
||||
text += tr("Compare Result: %1, %2\n").arg(record.conditional_code[0] ? "true" : "false").arg(record.conditional_code[1] ? "true" : "false");
|
||||
text += tr("Compare Result: %1, %2\n")
|
||||
.arg(record.conditional_code[0] ? "true" : "false")
|
||||
.arg(record.conditional_code[1] ? "true" : "false");
|
||||
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::COND_BOOL_IN)
|
||||
text += tr("Static Condition: %1\n").arg(record.cond_bool ? "true" : "false");
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::COND_CMP_IN)
|
||||
text += tr("Dynamic Conditions: %1, %2\n").arg(record.cond_cmp[0] ? "true" : "false").arg(record.cond_cmp[1] ? "true" : "false");
|
||||
text += tr("Dynamic Conditions: %1, %2\n")
|
||||
.arg(record.cond_cmp[0] ? "true" : "false")
|
||||
.arg(record.cond_cmp[1] ? "true" : "false");
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::LOOP_INT_IN)
|
||||
text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n").arg(record.loop_int.x).arg(record.loop_int.y).arg(record.loop_int.z).arg(record.loop_int.w);
|
||||
text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n")
|
||||
.arg(record.loop_int.x)
|
||||
.arg(record.loop_int.y)
|
||||
.arg(record.loop_int.z)
|
||||
.arg(record.loop_int.w);
|
||||
|
||||
text += tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0'));
|
||||
text +=
|
||||
tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0'));
|
||||
if (record.mask & Pica::Shader::DebugDataRecord::NEXT_INSTR) {
|
||||
text += tr(" -> 0x%2").arg(4 * record.next_instruction, 4, 16, QLatin1Char('0'));
|
||||
} else {
|
||||
|
@ -570,6 +627,7 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) {
|
|||
|
||||
// Emit model update notification and scroll to current instruction
|
||||
QModelIndex instr_index = model->index(record.instruction_offset, 0);
|
||||
emit model->dataChanged(instr_index, model->index(record.instruction_offset, model->columnCount()));
|
||||
emit model->dataChanged(instr_index,
|
||||
model->index(record.instruction_offset, model->columnCount()));
|
||||
binary_list->scrollTo(instr_index, QAbstractItemView::EnsureVisible);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ public:
|
|||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
GraphicsVertexShaderWidget* par;
|
||||
|
@ -56,7 +57,9 @@ private slots:
|
|||
/**
|
||||
* Reload widget based on the current PICA200 state
|
||||
* @param replace_vertex_data If true, invalidate all current vertex data
|
||||
* @param vertex_data New vertex data to use, as passed to OnBreakPointHit. May be nullptr to specify that no valid vertex data can be retrieved currently. Only used if replace_vertex_data is true.
|
||||
* @param vertex_data New vertex data to use, as passed to OnBreakPointHit. May be nullptr to
|
||||
* specify that no valid vertex data can be retrieved currently. Only used if
|
||||
* replace_vertex_data is true.
|
||||
*/
|
||||
void Reload(bool replace_vertex_data = false, void* vertex_data = nullptr);
|
||||
|
||||
|
@ -66,9 +69,12 @@ private:
|
|||
GraphicsVertexShaderModel* model;
|
||||
|
||||
/// TODO: Move these into a single struct
|
||||
std::array<QLineEdit*, 4*16> input_data; // A text box for each of the 4 components of up to 16 vertex attributes
|
||||
std::array<QWidget*, 16> input_data_container; // QWidget containing the QLayout containing each vertex attribute
|
||||
std::array<QLabel*, 16> input_data_mapping; // A QLabel denoting the shader input attribute which the vertex attribute maps to
|
||||
std::array<QLineEdit*, 4 * 16>
|
||||
input_data; // A text box for each of the 4 components of up to 16 vertex attributes
|
||||
std::array<QWidget*, 16>
|
||||
input_data_container; // QWidget containing the QLayout containing each vertex attribute
|
||||
std::array<QLabel*, 16> input_data_mapping; // A QLabel denoting the shader input attribute
|
||||
// which the vertex attribute maps to
|
||||
|
||||
// Text to be shown when input vertex data is not retrievable
|
||||
QLabel* breakpoint_warning;
|
||||
|
|
|
@ -22,57 +22,58 @@
|
|||
|
||||
using namespace Common::Profiling;
|
||||
|
||||
static QVariant GetDataForColumn(int col, const AggregatedDuration& duration)
|
||||
{
|
||||
static QVariant GetDataForColumn(int col, const AggregatedDuration& duration) {
|
||||
static auto duration_to_float = [](Duration dur) -> float {
|
||||
using FloatMs = std::chrono::duration<float, std::chrono::milliseconds::period>;
|
||||
return std::chrono::duration_cast<FloatMs>(dur).count();
|
||||
};
|
||||
|
||||
switch (col) {
|
||||
case 1: return duration_to_float(duration.avg);
|
||||
case 2: return duration_to_float(duration.min);
|
||||
case 3: return duration_to_float(duration.max);
|
||||
default: return QVariant();
|
||||
case 1:
|
||||
return duration_to_float(duration.avg);
|
||||
case 2:
|
||||
return duration_to_float(duration.min);
|
||||
case 3:
|
||||
return duration_to_float(duration.max);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent)
|
||||
{
|
||||
ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent) {
|
||||
updateProfilingInfo();
|
||||
}
|
||||
|
||||
QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case 0: return tr("Category");
|
||||
case 1: return tr("Avg");
|
||||
case 2: return tr("Min");
|
||||
case 3: return tr("Max");
|
||||
case 0:
|
||||
return tr("Category");
|
||||
case 1:
|
||||
return tr("Avg");
|
||||
case 2:
|
||||
return tr("Min");
|
||||
case 3:
|
||||
return tr("Max");
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const {
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
QModelIndex ProfilerModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
QModelIndex ProfilerModel::parent(const QModelIndex& child) const {
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int ProfilerModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
int ProfilerModel::columnCount(const QModelIndex& parent) const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
int ProfilerModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
int ProfilerModel::rowCount(const QModelIndex& parent) const {
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -80,8 +81,7 @@ int ProfilerModel::rowCount(const QModelIndex& parent) const
|
|||
}
|
||||
}
|
||||
|
||||
QVariant ProfilerModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QVariant ProfilerModel::data(const QModelIndex& index, int role) const {
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (index.row() == 0) {
|
||||
if (index.column() == 0) {
|
||||
|
@ -101,14 +101,12 @@ QVariant ProfilerModel::data(const QModelIndex& index, int role) const
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
void ProfilerModel::updateProfilingInfo()
|
||||
{
|
||||
void ProfilerModel::updateProfilingInfo() {
|
||||
results = GetTimingResultsAggregator()->GetAggregatedResults();
|
||||
emit dataChanged(createIndex(0, 1), createIndex(rowCount() - 1, 3));
|
||||
}
|
||||
|
||||
ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent)
|
||||
{
|
||||
ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) {
|
||||
ui.setupUi(this);
|
||||
|
||||
model = new ProfilerModel(this);
|
||||
|
@ -118,8 +116,7 @@ ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent)
|
|||
connect(&update_timer, SIGNAL(timeout()), model, SLOT(updateProfilingInfo()));
|
||||
}
|
||||
|
||||
void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable)
|
||||
{
|
||||
void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) {
|
||||
if (enable) {
|
||||
update_timer.start(100);
|
||||
model->updateProfilingInfo();
|
||||
|
@ -157,9 +154,7 @@ private:
|
|||
|
||||
#endif
|
||||
|
||||
MicroProfileDialog::MicroProfileDialog(QWidget* parent)
|
||||
: QWidget(parent, Qt::Dialog)
|
||||
{
|
||||
MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
|
||||
setObjectName("MicroProfile");
|
||||
setWindowTitle(tr("MicroProfile"));
|
||||
resize(1000, 600);
|
||||
|
@ -175,7 +170,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent)
|
|||
layout->addWidget(widget);
|
||||
setLayout(layout);
|
||||
|
||||
// Configure focus so that widget is focusable and the dialog automatically forwards focus to it.
|
||||
// Configure focus so that widget is focusable and the dialog automatically forwards focus to
|
||||
// it.
|
||||
setFocusProxy(widget);
|
||||
widget->setFocusPolicy(Qt::StrongFocus);
|
||||
widget->setFocus();
|
||||
|
@ -207,7 +203,6 @@ void MicroProfileDialog::hideEvent(QHideEvent* ev) {
|
|||
QWidget::hideEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
#if MICROPROFILE_ENABLED
|
||||
|
||||
/// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the
|
||||
|
@ -308,7 +303,8 @@ void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 tex
|
|||
}
|
||||
}
|
||||
|
||||
void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, MicroProfileBoxType type) {
|
||||
void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color,
|
||||
MicroProfileBoxType type) {
|
||||
QColor color = QColor::fromRgba(hex_color);
|
||||
QBrush brush = color;
|
||||
if (type == MicroProfileBoxTypeBar) {
|
||||
|
@ -326,7 +322,7 @@ void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color)
|
|||
static std::vector<QPointF> point_buf;
|
||||
|
||||
for (u32 i = 0; i < vertices_length; ++i) {
|
||||
point_buf.emplace_back(vertices[i*2 + 0], vertices[i*2 + 1]);
|
||||
point_buf.emplace_back(vertices[i * 2 + 0], vertices[i * 2 + 1]);
|
||||
}
|
||||
|
||||
// hex_color does not include an alpha, so it must be assumed to be 255
|
||||
|
|
|
@ -13,15 +13,16 @@
|
|||
#include "common/microprofile.h"
|
||||
#include "common/profiler_reporting.h"
|
||||
|
||||
class ProfilerModel : public QAbstractItemModel
|
||||
{
|
||||
class ProfilerModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ProfilerModel(QObject* parent);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex& parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex& child) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
@ -34,8 +35,7 @@ private:
|
|||
Common::Profiling::AggregatedFrameResult results;
|
||||
};
|
||||
|
||||
class ProfilerWidget : public QDockWidget
|
||||
{
|
||||
class ProfilerWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -51,7 +51,6 @@ private:
|
|||
QTimer update_timer;
|
||||
};
|
||||
|
||||
|
||||
class MicroProfileDialog : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
|
||||
#include "citra_qt/debugger/ramview.h"
|
||||
|
||||
GRamView::GRamView(QWidget* parent) : QHexEdit(parent)
|
||||
{
|
||||
GRamView::GRamView(QWidget* parent) : QHexEdit(parent) {
|
||||
}
|
||||
|
||||
void GRamView::OnCPUStepped()
|
||||
{
|
||||
void GRamView::OnCPUStepped() {
|
||||
// TODO: QHexEdit doesn't show vertical scroll bars for > 10MB data streams...
|
||||
//setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8));
|
||||
// setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8));
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
#include "qhexedit.h"
|
||||
|
||||
class GRamView : public QHexEdit
|
||||
{
|
||||
class GRamView : public QHexEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include "citra_qt/debugger/registers.h"
|
||||
#include "citra_qt/util/util.h"
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
|
||||
RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) {
|
||||
cpu_regs_ui.setupUi(this);
|
||||
|
@ -16,7 +16,8 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) {
|
|||
tree = cpu_regs_ui.treeWidget;
|
||||
tree->addTopLevelItem(core_registers = new QTreeWidgetItem(QStringList(tr("Registers"))));
|
||||
tree->addTopLevelItem(vfp_registers = new QTreeWidgetItem(QStringList(tr("VFP Registers"))));
|
||||
tree->addTopLevelItem(vfp_system_registers = new QTreeWidgetItem(QStringList(tr("VFP System Registers"))));
|
||||
tree->addTopLevelItem(vfp_system_registers =
|
||||
new QTreeWidgetItem(QStringList(tr("VFP System Registers"))));
|
||||
tree->addTopLevelItem(cpsr = new QTreeWidgetItem(QStringList("CPSR")));
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
|
@ -63,10 +64,12 @@ void RegistersWidget::OnDebugModeEntered() {
|
|||
return;
|
||||
|
||||
for (int i = 0; i < core_registers->childCount(); ++i)
|
||||
core_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0')));
|
||||
core_registers->child(i)->setText(
|
||||
1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0')));
|
||||
|
||||
for (int i = 0; i < vfp_registers->childCount(); ++i)
|
||||
vfp_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0')));
|
||||
vfp_registers->child(i)->setText(
|
||||
1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0')));
|
||||
|
||||
UpdateCPSRValues();
|
||||
UpdateVFPSystemRegisterValues();
|
||||
|
@ -130,21 +133,24 @@ void RegistersWidget::UpdateCPSRValues() {
|
|||
const u32 cpsr_val = Core::g_app_core->GetCPSR();
|
||||
|
||||
cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
||||
cpsr->child(0)->setText(1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode
|
||||
cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1)); // T - State
|
||||
cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1)); // F - FIQ disable
|
||||
cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1)); // I - IRQ disable
|
||||
cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1)); // A - Imprecise abort
|
||||
cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1)); // E - Data endianess
|
||||
cpsr->child(6)->setText(1, QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM)
|
||||
cpsr->child(7)->setText(1, QString::number((cpsr_val >> 16) & 0xF)); // GE - Greater-than-or-Equal
|
||||
cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF)); // DNM - Do not modify
|
||||
cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1)); // J - Jazelle
|
||||
cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1)); // Q - Saturation
|
||||
cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1)); // V - Overflow
|
||||
cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1)); // C - Carry/Borrow/Extend
|
||||
cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1)); // Z - Zero
|
||||
cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1)); // N - Negative/Less than
|
||||
cpsr->child(0)->setText(
|
||||
1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode
|
||||
cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1)); // T - State
|
||||
cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1)); // F - FIQ disable
|
||||
cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1)); // I - IRQ disable
|
||||
cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1)); // A - Imprecise abort
|
||||
cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1)); // E - Data endianess
|
||||
cpsr->child(6)->setText(1,
|
||||
QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM)
|
||||
cpsr->child(7)->setText(1,
|
||||
QString::number((cpsr_val >> 16) & 0xF)); // GE - Greater-than-or-Equal
|
||||
cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF)); // DNM - Do not modify
|
||||
cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1)); // J - Jazelle
|
||||
cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1)); // Q - Saturation
|
||||
cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1)); // V - Overflow
|
||||
cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1)); // C - Carry/Borrow/Extend
|
||||
cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1)); // Z - Zero
|
||||
cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1)); // N - Negative/Less than
|
||||
}
|
||||
|
||||
void RegistersWidget::CreateVFPSystemRegisterChildren() {
|
||||
|
@ -188,9 +194,9 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
|
|||
}
|
||||
|
||||
void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
||||
const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR);
|
||||
const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC);
|
||||
const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST);
|
||||
const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR);
|
||||
const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC);
|
||||
const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST);
|
||||
const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2);
|
||||
|
||||
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
|
||||
|
@ -228,6 +234,8 @@ void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
|||
fpexc->child(6)->setText(1, QString::number((fpexc_val >> 30) & 1));
|
||||
fpexc->child(7)->setText(1, QString::number((fpexc_val >> 31) & 1));
|
||||
|
||||
vfp_system_registers->child(2)->setText(1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0')));
|
||||
vfp_system_registers->child(3)->setText(1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0')));
|
||||
vfp_system_registers->child(2)->setText(
|
||||
1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0')));
|
||||
vfp_system_registers->child(3)->setText(
|
||||
1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0')));
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ class QTreeWidget;
|
|||
class QTreeWidgetItem;
|
||||
class EmuThread;
|
||||
|
||||
class RegistersWidget : public QDockWidget
|
||||
{
|
||||
class RegistersWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue