diff options
| author | 2016-09-21 11:29:48 -0700 | |
|---|---|---|
| committer | 2016-09-21 11:29:48 -0700 | |
| commit | d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a (patch) | |
| tree | 8a22ca73ff838f3f0090b29a548ae81087fc90ed /src/citra_qt/debugger | |
| parent | README: Specify master branch for Travis CI badge (diff) | |
| parent | Fix Travis clang-format check (diff) | |
| download | yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.tar.gz yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.tar.xz yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.zip | |
Merge pull request #2086 from linkmauve/clang-format
Add clang-format as part of our {commit,travis}-time checks
Diffstat (limited to 'src/citra_qt/debugger')
25 files changed, 592 insertions, 630 deletions
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 1a3077495..c66f2b96a 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp | |||
| @@ -3,19 +3,15 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QStandardItemModel> | 5 | #include <QStandardItemModel> |
| 6 | |||
| 7 | #include "citra_qt/debugger/callstack.h" | 6 | #include "citra_qt/debugger/callstack.h" |
| 8 | |||
| 9 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 10 | #include "common/symbols.h" | 8 | #include "common/symbols.h" |
| 11 | |||
| 12 | #include "core/core.h" | ||
| 13 | #include "core/memory.h" | ||
| 14 | #include "core/arm/arm_interface.h" | 9 | #include "core/arm/arm_interface.h" |
| 15 | #include "core/arm/disassembler/arm_disasm.h" | 10 | #include "core/arm/disassembler/arm_disasm.h" |
| 11 | #include "core/core.h" | ||
| 12 | #include "core/memory.h" | ||
| 16 | 13 | ||
| 17 | CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent) | 14 | CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) { |
| 18 | { | ||
| 19 | ui.setupUi(this); | 15 | ui.setupUi(this); |
| 20 | 16 | ||
| 21 | callstack_model = new QStandardItemModel(this); | 17 | callstack_model = new QStandardItemModel(this); |
| @@ -27,29 +23,26 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent) | |||
| 27 | ui.treeView->setModel(callstack_model); | 23 | ui.treeView->setModel(callstack_model); |
| 28 | } | 24 | } |
| 29 | 25 | ||
| 30 | void CallstackWidget::OnDebugModeEntered() | 26 | void CallstackWidget::OnDebugModeEntered() { |
| 31 | { | ||
| 32 | // Stack pointer | 27 | // Stack pointer |
| 33 | const u32 sp = Core::g_app_core->GetReg(13); | 28 | const u32 sp = Core::g_app_core->GetReg(13); |
| 34 | 29 | ||
| 35 | Clear(); | 30 | Clear(); |
| 36 | 31 | ||
| 37 | int counter = 0; | 32 | int counter = 0; |
| 38 | for (u32 addr = 0x10000000; addr >= sp; addr -= 4) | 33 | for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { |
| 39 | { | ||
| 40 | if (!Memory::IsValidVirtualAddress(addr)) | 34 | if (!Memory::IsValidVirtualAddress(addr)) |
| 41 | break; | 35 | break; |
| 42 | 36 | ||
| 43 | const u32 ret_addr = Memory::Read32(addr); | 37 | const u32 ret_addr = Memory::Read32(addr); |
| 44 | const u32 call_addr = ret_addr - 4; //get call address??? | 38 | const u32 call_addr = ret_addr - 4; // get call address??? |
| 45 | 39 | ||
| 46 | if (!Memory::IsValidVirtualAddress(call_addr)) | 40 | if (!Memory::IsValidVirtualAddress(call_addr)) |
| 47 | break; | 41 | break; |
| 48 | 42 | ||
| 49 | /* TODO (mattvail) clean me, move to debugger interface */ | 43 | /* TODO (mattvail) clean me, move to debugger interface */ |
| 50 | u32 insn = Memory::Read32(call_addr); | 44 | u32 insn = Memory::Read32(call_addr); |
| 51 | if (ARM_Disasm::Decode(insn) == OP_BL) | 45 | if (ARM_Disasm::Decode(insn) == OP_BL) { |
| 52 | { | ||
| 53 | std::string name; | 46 | std::string name; |
| 54 | // ripped from disasm | 47 | // ripped from disasm |
| 55 | u8 cond = (insn >> 28) & 0xf; | 48 | u8 cond = (insn >> 28) & 0xf; |
| @@ -63,26 +56,28 @@ void CallstackWidget::OnDebugModeEntered() | |||
| 63 | i_offset += 8; | 56 | i_offset += 8; |
| 64 | const u32 func_addr = call_addr + i_offset; | 57 | const u32 func_addr = call_addr + i_offset; |
| 65 | 58 | ||
| 66 | callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); | 59 | callstack_model->setItem( |
| 67 | callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0')))); | 60 | counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); |
| 68 | callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0')))); | 61 | callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg( |
| 62 | ret_addr, 8, 16, QLatin1Char('0')))); | ||
| 63 | callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg( | ||
| 64 | call_addr, 8, 16, QLatin1Char('0')))); | ||
| 69 | 65 | ||
| 70 | name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; | 66 | name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown"; |
| 71 | callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name)) | 67 | callstack_model->setItem( |
| 72 | .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); | 68 | counter, 3, new QStandardItem( |
| 69 | QString("%1_%2") | ||
| 70 | .arg(QString::fromStdString(name)) | ||
| 71 | .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0'))))); | ||
| 73 | 72 | ||
| 74 | counter++; | 73 | counter++; |
| 75 | } | 74 | } |
| 76 | } | 75 | } |
| 77 | } | 76 | } |
| 78 | 77 | ||
| 79 | void CallstackWidget::OnDebugModeLeft() | 78 | void CallstackWidget::OnDebugModeLeft() {} |
| 80 | { | ||
| 81 | |||
| 82 | } | ||
| 83 | 79 | ||
| 84 | void CallstackWidget::Clear() | 80 | void CallstackWidget::Clear() { |
| 85 | { | ||
| 86 | for (int row = 0; row < callstack_model->rowCount(); row++) { | 81 | for (int row = 0; row < callstack_model->rowCount(); row++) { |
| 87 | for (int column = 0; column < callstack_model->columnCount(); column++) { | 82 | for (int column = 0; column < callstack_model->columnCount(); column++) { |
| 88 | callstack_model->setItem(row, column, new QStandardItem()); | 83 | callstack_model->setItem(row, column, new QStandardItem()); |
diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h index 7aa83db1e..765757986 100644 --- a/src/citra_qt/debugger/callstack.h +++ b/src/citra_qt/debugger/callstack.h | |||
| @@ -7,8 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | class QStandardItemModel; | 8 | class QStandardItemModel; |
| 9 | 9 | ||
| 10 | class CallstackWidget : public QDockWidget | 10 | class CallstackWidget : public QDockWidget { |
| 11 | { | ||
| 12 | Q_OBJECT | 11 | Q_OBJECT |
| 13 | 12 | ||
| 14 | public: | 13 | public: |
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index d4f72809d..1ee6bbd6a 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp | |||
| @@ -3,23 +3,20 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QShortcut> | 5 | #include <QShortcut> |
| 6 | |||
| 7 | #include "citra_qt/bootmanager.h" | 6 | #include "citra_qt/bootmanager.h" |
| 8 | #include "citra_qt/hotkeys.h" | ||
| 9 | #include "citra_qt/debugger/disassembler.h" | 7 | #include "citra_qt/debugger/disassembler.h" |
| 8 | #include "citra_qt/hotkeys.h" | ||
| 10 | #include "citra_qt/util/util.h" | 9 | #include "citra_qt/util/util.h" |
| 11 | |||
| 12 | #include "common/break_points.h" | 10 | #include "common/break_points.h" |
| 13 | #include "common/symbols.h" | 11 | #include "common/symbols.h" |
| 14 | |||
| 15 | #include "core/core.h" | ||
| 16 | #include "core/memory.h" | ||
| 17 | #include "core/arm/arm_interface.h" | 12 | #include "core/arm/arm_interface.h" |
| 18 | #include "core/arm/disassembler/arm_disasm.h" | 13 | #include "core/arm/disassembler/arm_disasm.h" |
| 14 | #include "core/core.h" | ||
| 15 | #include "core/memory.h" | ||
| 19 | 16 | ||
| 20 | DisassemblerModel::DisassemblerModel(QObject* parent) : | 17 | DisassemblerModel::DisassemblerModel(QObject* parent) |
| 21 | QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) { | 18 | : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), |
| 22 | } | 19 | selection(QModelIndex()) {} |
| 23 | 20 | ||
| 24 | int DisassemblerModel::columnCount(const QModelIndex& parent) const { | 21 | int DisassemblerModel::columnCount(const QModelIndex& parent) const { |
| 25 | return 3; | 22 | return 3; |
| @@ -31,62 +28,60 @@ int DisassemblerModel::rowCount(const QModelIndex& parent) const { | |||
| 31 | 28 | ||
| 32 | QVariant DisassemblerModel::data(const QModelIndex& index, int role) const { | 29 | QVariant DisassemblerModel::data(const QModelIndex& index, int role) const { |
| 33 | switch (role) { | 30 | switch (role) { |
| 34 | case Qt::DisplayRole: | 31 | case Qt::DisplayRole: { |
| 35 | { | 32 | u32 address = base_address + index.row() * 4; |
| 36 | u32 address = base_address + index.row() * 4; | 33 | u32 instr = Memory::Read32(address); |
| 37 | u32 instr = Memory::Read32(address); | 34 | std::string disassembly = ARM_Disasm::Disassemble(address, instr); |
| 38 | std::string disassembly = ARM_Disasm::Disassemble(address, instr); | 35 | |
| 39 | 36 | if (index.column() == 0) { | |
| 40 | if (index.column() == 0) { | 37 | return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0')); |
| 41 | return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0')); | 38 | } else if (index.column() == 1) { |
| 42 | } else if (index.column() == 1) { | 39 | return QString::fromStdString(disassembly); |
| 43 | return QString::fromStdString(disassembly); | 40 | } else if (index.column() == 2) { |
| 44 | } else if (index.column() == 2) { | 41 | if (Symbols::HasSymbol(address)) { |
| 45 | if(Symbols::HasSymbol(address)) { | 42 | TSymbol symbol = Symbols::GetSymbol(address); |
| 46 | TSymbol symbol = Symbols::GetSymbol(address); | 43 | return QString("%1 - Size:%2") |
| 47 | return QString("%1 - Size:%2").arg(QString::fromStdString(symbol.name)) | 44 | .arg(QString::fromStdString(symbol.name)) |
| 48 | .arg(symbol.size / 4); // divide by 4 to get instruction count | 45 | .arg(symbol.size / 4); // divide by 4 to get instruction count |
| 49 | } else if (ARM_Disasm::Decode(instr) == OP_BL) { | 46 | } else if (ARM_Disasm::Decode(instr) == OP_BL) { |
| 50 | u32 offset = instr & 0xFFFFFF; | 47 | u32 offset = instr & 0xFFFFFF; |
| 51 | 48 | ||
| 52 | // Sign-extend the 24-bit offset | 49 | // Sign-extend the 24-bit offset |
| 53 | if ((offset >> 23) & 1) | 50 | if ((offset >> 23) & 1) |
| 54 | offset |= 0xFF000000; | 51 | offset |= 0xFF000000; |
| 55 | 52 | ||
| 56 | // Pre-compute the left-shift and the prefetch offset | 53 | // Pre-compute the left-shift and the prefetch offset |
| 57 | offset <<= 2; | 54 | offset <<= 2; |
| 58 | offset += 8; | 55 | offset += 8; |
| 59 | 56 | ||
| 60 | TSymbol symbol = Symbols::GetSymbol(address + offset); | 57 | TSymbol symbol = Symbols::GetSymbol(address + offset); |
| 61 | return QString(" --> %1").arg(QString::fromStdString(symbol.name)); | 58 | return QString(" --> %1").arg(QString::fromStdString(symbol.name)); |
| 62 | } | ||
| 63 | } | 59 | } |
| 64 | |||
| 65 | break; | ||
| 66 | } | 60 | } |
| 67 | 61 | ||
| 68 | case Qt::BackgroundRole: | 62 | break; |
| 69 | { | 63 | } |
| 70 | unsigned int address = base_address + 4 * index.row(); | ||
| 71 | 64 | ||
| 72 | if (breakpoints.IsAddressBreakPoint(address)) | 65 | case Qt::BackgroundRole: { |
| 73 | return QBrush(QColor(0xFF, 0xC0, 0xC0)); | 66 | unsigned int address = base_address + 4 * index.row(); |
| 74 | else if (address == program_counter) | ||
| 75 | return QBrush(QColor(0xC0, 0xC0, 0xFF)); | ||
| 76 | 67 | ||
| 77 | break; | 68 | if (breakpoints.IsAddressBreakPoint(address)) |
| 78 | } | 69 | return QBrush(QColor(0xFF, 0xC0, 0xC0)); |
| 70 | else if (address == program_counter) | ||
| 71 | return QBrush(QColor(0xC0, 0xC0, 0xFF)); | ||
| 79 | 72 | ||
| 80 | case Qt::FontRole: | 73 | break; |
| 81 | { | 74 | } |
| 82 | if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column | 75 | |
| 83 | return GetMonospaceFont(); | 76 | case Qt::FontRole: { |
| 84 | } | 77 | if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column |
| 85 | break; | 78 | return GetMonospaceFont(); |
| 86 | } | 79 | } |
| 80 | break; | ||
| 81 | } | ||
| 87 | 82 | ||
| 88 | default: | 83 | default: |
| 89 | break; | 84 | break; |
| 90 | } | 85 | } |
| 91 | 86 | ||
| 92 | return QVariant(); | 87 | return QVariant(); |
| @@ -103,7 +98,7 @@ const BreakPoints& DisassemblerModel::GetBreakPoints() const { | |||
| 103 | void DisassemblerModel::ParseFromAddress(unsigned int address) { | 98 | void DisassemblerModel::ParseFromAddress(unsigned int address) { |
| 104 | 99 | ||
| 105 | // NOTE: A too large value causes lagging when scrolling the disassembly | 100 | // NOTE: A too large value causes lagging when scrolling the disassembly |
| 106 | const unsigned int chunk_size = 1000*500; | 101 | const unsigned int chunk_size = 1000 * 500; |
| 107 | 102 | ||
| 108 | // If we haven't loaded anything yet, initialize base address to the parameter address | 103 | // If we haven't loaded anything yet, initialize base address to the parameter address |
| 109 | if (code_size == 0) | 104 | if (code_size == 0) |
| @@ -165,23 +160,26 @@ void DisassemblerModel::SetNextInstruction(unsigned int address) { | |||
| 165 | emit dataChanged(prev_index, prev_index); | 160 | emit dataChanged(prev_index, prev_index); |
| 166 | } | 161 | } |
| 167 | 162 | ||
| 168 | DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) : | 163 | DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) |
| 169 | QDockWidget(parent), base_addr(0), emu_thread(emu_thread) { | 164 | : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) { |
| 170 | 165 | ||
| 171 | disasm_ui.setupUi(this); | 166 | disasm_ui.setupUi(this); |
| 172 | 167 | ||
| 173 | RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); | 168 | RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); |
| 174 | RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); | 169 | RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); |
| 175 | RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); | 170 | RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); |
| 176 | RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut); | 171 | RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), |
| 172 | Qt::ApplicationShortcut); | ||
| 177 | 173 | ||
| 178 | connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); | 174 | connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); |
| 179 | connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); | 175 | connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); |
| 180 | connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); | 176 | connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); |
| 181 | 177 | ||
| 182 | connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, SLOT(OnToggleStartStop())); | 178 | connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, |
| 179 | SLOT(OnToggleStartStop())); | ||
| 183 | connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); | 180 | connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); |
| 184 | connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto())); | 181 | connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, |
| 182 | SLOT(OnStepInto())); | ||
| 185 | 183 | ||
| 186 | setEnabled(false); | 184 | setEnabled(false); |
| 187 | } | 185 | } |
| @@ -195,7 +193,8 @@ void DisassemblerWidget::Init() { | |||
| 195 | 193 | ||
| 196 | QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC()); | 194 | QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC()); |
| 197 | disasm_ui.treeView->scrollTo(model_index); | 195 | disasm_ui.treeView->scrollTo(model_index); |
| 198 | disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | 196 | disasm_ui.treeView->selectionModel()->setCurrentIndex( |
| 197 | model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||
| 199 | } | 198 | } |
| 200 | 199 | ||
| 201 | void DisassemblerWidget::OnContinue() { | 200 | void DisassemblerWidget::OnContinue() { |
| @@ -234,11 +233,11 @@ void DisassemblerWidget::OnDebugModeEntered() { | |||
| 234 | 233 | ||
| 235 | QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr); | 234 | QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr); |
| 236 | disasm_ui.treeView->scrollTo(model_index); | 235 | disasm_ui.treeView->scrollTo(model_index); |
| 237 | disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | 236 | disasm_ui.treeView->selectionModel()->setCurrentIndex( |
| 237 | model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | void DisassemblerWidget::OnDebugModeLeft() { | 240 | void DisassemblerWidget::OnDebugModeLeft() {} |
| 241 | } | ||
| 242 | 241 | ||
| 243 | int DisassemblerWidget::SelectedRow() { | 242 | int DisassemblerWidget::SelectedRow() { |
| 244 | QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex(); | 243 | QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex(); |
| @@ -254,10 +253,12 @@ void DisassemblerWidget::OnEmulationStarting(EmuThread* emu_thread) { | |||
| 254 | model = new DisassemblerModel(this); | 253 | model = new DisassemblerModel(this); |
| 255 | disasm_ui.treeView->setModel(model); | 254 | disasm_ui.treeView->setModel(model); |
| 256 | 255 | ||
| 257 | connect(disasm_ui.treeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), | 256 | connect(disasm_ui.treeView->selectionModel(), |
| 258 | model, SLOT(OnSelectionChanged(const QModelIndex&))); | 257 | SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), model, |
| 258 | SLOT(OnSelectionChanged(const QModelIndex&))); | ||
| 259 | connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint())); | 259 | connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint())); |
| 260 | connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, SLOT(OnSetOrUnsetBreakpoint())); | 260 | connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model, |
| 261 | SLOT(OnSetOrUnsetBreakpoint())); | ||
| 261 | 262 | ||
| 262 | Init(); | 263 | Init(); |
| 263 | setEnabled(true); | 264 | setEnabled(true); |
diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h index 340fb9936..2ca6c2bd4 100644 --- a/src/citra_qt/debugger/disassembler.h +++ b/src/citra_qt/debugger/disassembler.h | |||
| @@ -6,17 +6,14 @@ | |||
| 6 | 6 | ||
| 7 | #include <QAbstractListModel> | 7 | #include <QAbstractListModel> |
| 8 | #include <QDockWidget> | 8 | #include <QDockWidget> |
| 9 | |||
| 10 | #include "ui_disassembler.h" | ||
| 11 | |||
| 12 | #include "common/break_points.h" | 9 | #include "common/break_points.h" |
| 13 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "ui_disassembler.h" | ||
| 14 | 12 | ||
| 15 | class QAction; | 13 | class QAction; |
| 16 | class EmuThread; | 14 | class EmuThread; |
| 17 | 15 | ||
| 18 | class DisassemblerModel : public QAbstractListModel | 16 | class DisassemblerModel : public QAbstractListModel { |
| 19 | { | ||
| 20 | Q_OBJECT | 17 | Q_OBJECT |
| 21 | 18 | ||
| 22 | public: | 19 | public: |
| @@ -46,8 +43,7 @@ private: | |||
| 46 | mutable BreakPoints breakpoints; | 43 | mutable BreakPoints breakpoints; |
| 47 | }; | 44 | }; |
| 48 | 45 | ||
| 49 | class DisassemblerWidget : public QDockWidget | 46 | class DisassemblerWidget : public QDockWidget { |
| 50 | { | ||
| 51 | Q_OBJECT | 47 | Q_OBJECT |
| 52 | 48 | ||
| 53 | public: | 49 | public: |
diff --git a/src/citra_qt/debugger/graphics.cpp b/src/citra_qt/debugger/graphics.cpp index eccd619ba..ef6712bfa 100644 --- a/src/citra_qt/debugger/graphics.cpp +++ b/src/citra_qt/debugger/graphics.cpp | |||
| @@ -3,75 +3,67 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QListView> | 5 | #include <QListView> |
| 6 | |||
| 7 | #include "citra_qt/debugger/graphics.h" | 6 | #include "citra_qt/debugger/graphics.h" |
| 8 | #include "citra_qt/util/util.h" | 7 | #include "citra_qt/util/util.h" |
| 9 | 8 | ||
| 10 | extern GraphicsDebugger g_debugger; | 9 | extern GraphicsDebugger g_debugger; |
| 11 | 10 | ||
| 12 | GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0) | 11 | GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) |
| 13 | { | 12 | : QAbstractListModel(parent), command_count(0) { |
| 14 | connect(this, SIGNAL(GXCommandFinished(int)), this, SLOT(OnGXCommandFinishedInternal(int))); | 13 | connect(this, SIGNAL(GXCommandFinished(int)), this, SLOT(OnGXCommandFinishedInternal(int))); |
| 15 | } | 14 | } |
| 16 | 15 | ||
| 17 | int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const | 16 | int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const { |
| 18 | { | ||
| 19 | return command_count; | 17 | return command_count; |
| 20 | } | 18 | } |
| 21 | 19 | ||
| 22 | QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const | 20 | QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const { |
| 23 | { | ||
| 24 | if (!index.isValid()) | 21 | if (!index.isValid()) |
| 25 | return QVariant(); | 22 | return QVariant(); |
| 26 | 23 | ||
| 27 | int command_index = index.row(); | 24 | int command_index = index.row(); |
| 28 | const GSP_GPU::Command& command = GetDebugger()->ReadGXCommandHistory(command_index); | 25 | const GSP_GPU::Command& command = GetDebugger()->ReadGXCommandHistory(command_index); |
| 29 | if (role == Qt::DisplayRole) | 26 | if (role == Qt::DisplayRole) { |
| 30 | { | ||
| 31 | std::map<GSP_GPU::CommandId, const char*> command_names = { | 27 | std::map<GSP_GPU::CommandId, const char*> command_names = { |
| 32 | { GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA" }, | 28 | {GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA"}, |
| 33 | { GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST" }, | 29 | {GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST"}, |
| 34 | { GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL" }, | 30 | {GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL"}, |
| 35 | { GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER" }, | 31 | {GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER"}, |
| 36 | { GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY" }, | 32 | {GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY"}, |
| 37 | { GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH" }, | 33 | {GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH"}, |
| 38 | }; | 34 | }; |
| 39 | const u32* command_data = reinterpret_cast<const u32*>(&command); | 35 | const u32* command_data = reinterpret_cast<const u32*>(&command); |
| 40 | QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9").arg(command_names[command.id]) | 36 | QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9") |
| 41 | .arg(command_data[0], 8, 16, QLatin1Char('0')) | 37 | .arg(command_names[command.id]) |
| 42 | .arg(command_data[1], 8, 16, QLatin1Char('0')) | 38 | .arg(command_data[0], 8, 16, QLatin1Char('0')) |
| 43 | .arg(command_data[2], 8, 16, QLatin1Char('0')) | 39 | .arg(command_data[1], 8, 16, QLatin1Char('0')) |
| 44 | .arg(command_data[3], 8, 16, QLatin1Char('0')) | 40 | .arg(command_data[2], 8, 16, QLatin1Char('0')) |
| 45 | .arg(command_data[4], 8, 16, QLatin1Char('0')) | 41 | .arg(command_data[3], 8, 16, QLatin1Char('0')) |
| 46 | .arg(command_data[5], 8, 16, QLatin1Char('0')) | 42 | .arg(command_data[4], 8, 16, QLatin1Char('0')) |
| 47 | .arg(command_data[6], 8, 16, QLatin1Char('0')) | 43 | .arg(command_data[5], 8, 16, QLatin1Char('0')) |
| 48 | .arg(command_data[7], 8, 16, QLatin1Char('0')); | 44 | .arg(command_data[6], 8, 16, QLatin1Char('0')) |
| 45 | .arg(command_data[7], 8, 16, QLatin1Char('0')); | ||
| 49 | return QVariant(str); | 46 | return QVariant(str); |
| 50 | } | 47 | } else { |
| 51 | else | ||
| 52 | { | ||
| 53 | return QVariant(); | 48 | return QVariant(); |
| 54 | } | 49 | } |
| 55 | } | 50 | } |
| 56 | 51 | ||
| 57 | void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count) | 52 | void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count) { |
| 58 | { | ||
| 59 | emit GXCommandFinished(total_command_count); | 53 | emit GXCommandFinished(total_command_count); |
| 60 | } | 54 | } |
| 61 | 55 | ||
| 62 | void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count) | 56 | void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count) { |
| 63 | { | ||
| 64 | if (total_command_count == 0) | 57 | if (total_command_count == 0) |
| 65 | return; | 58 | return; |
| 66 | 59 | ||
| 67 | int prev_command_count = command_count; | 60 | int prev_command_count = command_count; |
| 68 | command_count = total_command_count; | 61 | command_count = total_command_count; |
| 69 | emit dataChanged(index(prev_command_count,0), index(total_command_count-1,0)); | 62 | emit dataChanged(index(prev_command_count, 0), index(total_command_count - 1, 0)); |
| 70 | } | 63 | } |
| 71 | 64 | ||
| 72 | 65 | GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) | |
| 73 | GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) : QDockWidget(tr("Graphics Debugger"), parent) | 66 | : QDockWidget(tr("Graphics Debugger"), parent) { |
| 74 | { | ||
| 75 | setObjectName("GraphicsDebugger"); | 67 | setObjectName("GraphicsDebugger"); |
| 76 | 68 | ||
| 77 | GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this); | 69 | GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this); |
diff --git a/src/citra_qt/debugger/graphics.h b/src/citra_qt/debugger/graphics.h index 36b25b81d..bedf3e596 100644 --- a/src/citra_qt/debugger/graphics.h +++ b/src/citra_qt/debugger/graphics.h | |||
| @@ -6,11 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | #include <QAbstractListModel> | 7 | #include <QAbstractListModel> |
| 8 | #include <QDockWidget> | 8 | #include <QDockWidget> |
| 9 | |||
| 10 | #include "video_core/gpu_debugger.h" | 9 | #include "video_core/gpu_debugger.h" |
| 11 | 10 | ||
| 12 | class GPUCommandStreamItemModel : public QAbstractListModel, public GraphicsDebugger::DebuggerObserver | 11 | class GPUCommandStreamItemModel : public QAbstractListModel, |
| 13 | { | 12 | public GraphicsDebugger::DebuggerObserver { |
| 14 | Q_OBJECT | 13 | Q_OBJECT |
| 15 | 14 | ||
| 16 | public: | 15 | public: |
| @@ -32,8 +31,7 @@ private: | |||
| 32 | int command_count; | 31 | int command_count; |
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | class GPUCommandStreamWidget : public QDockWidget | 34 | class GPUCommandStreamWidget : public QDockWidget { |
| 36 | { | ||
| 37 | Q_OBJECT | 35 | Q_OBJECT |
| 38 | 36 | ||
| 39 | public: | 37 | public: |
diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.cpp b/src/citra_qt/debugger/graphics_breakpoint_observer.cpp index f134eef63..e01d3440e 100644 --- a/src/citra_qt/debugger/graphics_breakpoint_observer.cpp +++ b/src/citra_qt/debugger/graphics_breakpoint_observer.cpp | |||
| @@ -3,30 +3,25 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QMetaType> | 5 | #include <QMetaType> |
| 6 | |||
| 7 | #include "citra_qt/debugger/graphics_breakpoint_observer.h" | 6 | #include "citra_qt/debugger/graphics_breakpoint_observer.h" |
| 8 | 7 | ||
| 9 | BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, | 8 | BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, |
| 10 | const QString& title, QWidget* parent) | 9 | const QString& title, QWidget* parent) |
| 11 | : QDockWidget(title, parent), BreakPointObserver(debug_context) | 10 | : QDockWidget(title, parent), BreakPointObserver(debug_context) { |
| 12 | { | ||
| 13 | qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); | 11 | qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); |
| 14 | 12 | ||
| 15 | connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); | 13 | connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); |
| 16 | 14 | ||
| 17 | // NOTE: This signal is emitted from a non-GUI thread, but connect() takes | 15 | // NOTE: This signal is emitted from a non-GUI thread, but connect() takes |
| 18 | // care of delaying its handling to the GUI thread. | 16 | // care of delaying its handling to the GUI thread. |
| 19 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | 17 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), this, |
| 20 | this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), | 18 | SLOT(OnBreakPointHit(Pica::DebugContext::Event, void*)), Qt::BlockingQueuedConnection); |
| 21 | Qt::BlockingQueuedConnection); | ||
| 22 | } | 19 | } |
| 23 | 20 | ||
| 24 | void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) | 21 | void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) { |
| 25 | { | ||
| 26 | emit BreakPointHit(event, data); | 22 | emit BreakPointHit(event, data); |
| 27 | } | 23 | } |
| 28 | 24 | ||
| 29 | void BreakPointObserverDock::OnPicaResume() | 25 | void BreakPointObserverDock::OnPicaResume() { |
| 30 | { | ||
| 31 | emit Resumed(); | 26 | emit Resumed(); |
| 32 | } | 27 | } |
diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.h b/src/citra_qt/debugger/graphics_breakpoint_observer.h index 02a0f4f4f..e77df4f5b 100644 --- a/src/citra_qt/debugger/graphics_breakpoint_observer.h +++ b/src/citra_qt/debugger/graphics_breakpoint_observer.h | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <QDockWidget> | 7 | #include <QDockWidget> |
| 8 | |||
| 9 | #include "video_core/debug_utils/debug_utils.h" | 8 | #include "video_core/debug_utils/debug_utils.h" |
| 10 | 9 | ||
| 11 | /** | 10 | /** |
| @@ -13,7 +12,8 @@ | |||
| 13 | * This is because the Pica breakpoint callbacks are called from a non-GUI thread, while | 12 | * This is because the Pica breakpoint callbacks are called from a non-GUI thread, while |
| 14 | * the widget usually wants to perform reactions in the GUI thread. | 13 | * the widget usually wants to perform reactions in the GUI thread. |
| 15 | */ | 14 | */ |
| 16 | class BreakPointObserverDock : public QDockWidget, protected Pica::DebugContext::BreakPointObserver { | 15 | class BreakPointObserverDock : public QDockWidget, |
| 16 | protected Pica::DebugContext::BreakPointObserver { | ||
| 17 | Q_OBJECT | 17 | Q_OBJECT |
| 18 | 18 | ||
| 19 | public: | 19 | public: |
diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index fe66918a8..d2a036dfa 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp | |||
| @@ -7,47 +7,39 @@ | |||
| 7 | #include <QPushButton> | 7 | #include <QPushButton> |
| 8 | #include <QTreeView> | 8 | #include <QTreeView> |
| 9 | #include <QVBoxLayout> | 9 | #include <QVBoxLayout> |
| 10 | |||
| 11 | #include "citra_qt/debugger/graphics_breakpoints.h" | 10 | #include "citra_qt/debugger/graphics_breakpoints.h" |
| 12 | #include "citra_qt/debugger/graphics_breakpoints_p.h" | 11 | #include "citra_qt/debugger/graphics_breakpoints_p.h" |
| 13 | |||
| 14 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 15 | 13 | ||
| 16 | BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_context, QObject* parent) | 14 | BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_context, QObject* parent) |
| 17 | : QAbstractListModel(parent), context_weak(debug_context), | 15 | : QAbstractListModel(parent), context_weak(debug_context), |
| 18 | at_breakpoint(debug_context->at_breakpoint), | 16 | at_breakpoint(debug_context->at_breakpoint), |
| 19 | active_breakpoint(debug_context->active_breakpoint) | 17 | active_breakpoint(debug_context->active_breakpoint) {} |
| 20 | { | ||
| 21 | |||
| 22 | } | ||
| 23 | 18 | ||
| 24 | int BreakPointModel::columnCount(const QModelIndex& parent) const | 19 | int BreakPointModel::columnCount(const QModelIndex& parent) const { |
| 25 | { | ||
| 26 | return 1; | 20 | return 1; |
| 27 | } | 21 | } |
| 28 | 22 | ||
| 29 | int BreakPointModel::rowCount(const QModelIndex& parent) const | 23 | int BreakPointModel::rowCount(const QModelIndex& parent) const { |
| 30 | { | ||
| 31 | return static_cast<int>(Pica::DebugContext::Event::NumEvents); | 24 | return static_cast<int>(Pica::DebugContext::Event::NumEvents); |
| 32 | } | 25 | } |
| 33 | 26 | ||
| 34 | QVariant BreakPointModel::data(const QModelIndex& index, int role) const | 27 | QVariant BreakPointModel::data(const QModelIndex& index, int role) const { |
| 35 | { | ||
| 36 | const auto event = static_cast<Pica::DebugContext::Event>(index.row()); | 28 | const auto event = static_cast<Pica::DebugContext::Event>(index.row()); |
| 37 | 29 | ||
| 38 | switch (role) { | 30 | switch (role) { |
| 39 | case Qt::DisplayRole: | 31 | case Qt::DisplayRole: { |
| 40 | { | ||
| 41 | if (index.column() == 0) { | 32 | if (index.column() == 0) { |
| 42 | static const std::map<Pica::DebugContext::Event, QString> map = { | 33 | static const std::map<Pica::DebugContext::Event, QString> map = { |
| 43 | { Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded") }, | 34 | {Pica::DebugContext::Event::PicaCommandLoaded, tr("Pica command loaded")}, |
| 44 | { Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") }, | 35 | {Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed")}, |
| 45 | { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, | 36 | {Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}, |
| 46 | { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, | 37 | {Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}, |
| 47 | { Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation") }, | 38 | {Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation")}, |
| 48 | { Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") }, | 39 | {Pica::DebugContext::Event::IncomingDisplayTransfer, |
| 49 | { Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") }, | 40 | tr("Incoming display transfer")}, |
| 50 | { Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") } | 41 | {Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed")}, |
| 42 | {Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped")}, | ||
| 51 | }; | 43 | }; |
| 52 | 44 | ||
| 53 | DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); | 45 | DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); |
| @@ -57,23 +49,20 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const | |||
| 57 | break; | 49 | break; |
| 58 | } | 50 | } |
| 59 | 51 | ||
| 60 | case Qt::CheckStateRole: | 52 | case Qt::CheckStateRole: { |
| 61 | { | ||
| 62 | if (index.column() == 0) | 53 | if (index.column() == 0) |
| 63 | return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked; | 54 | return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked; |
| 64 | break; | 55 | break; |
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | case Qt::BackgroundRole: | 58 | case Qt::BackgroundRole: { |
| 68 | { | ||
| 69 | if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) { | 59 | if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) { |
| 70 | return QBrush(QColor(0xE0, 0xE0, 0x10)); | 60 | return QBrush(QColor(0xE0, 0xE0, 0x10)); |
| 71 | } | 61 | } |
| 72 | break; | 62 | break; |
| 73 | } | 63 | } |
| 74 | 64 | ||
| 75 | case Role_IsEnabled: | 65 | case Role_IsEnabled: { |
| 76 | { | ||
| 77 | auto context = context_weak.lock(); | 66 | auto context = context_weak.lock(); |
| 78 | return context && context->breakpoints[(int)event].enabled; | 67 | return context && context->breakpoints[(int)event].enabled; |
| 79 | } | 68 | } |
| @@ -84,8 +73,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const | |||
| 84 | return QVariant(); | 73 | return QVariant(); |
| 85 | } | 74 | } |
| 86 | 75 | ||
| 87 | Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const | 76 | Qt::ItemFlags BreakPointModel::flags(const QModelIndex& index) const { |
| 88 | { | ||
| 89 | if (!index.isValid()) | 77 | if (!index.isValid()) |
| 90 | return 0; | 78 | return 0; |
| 91 | 79 | ||
| @@ -95,14 +83,11 @@ Qt::ItemFlags BreakPointModel::flags(const QModelIndex &index) const | |||
| 95 | return flags; | 83 | return flags; |
| 96 | } | 84 | } |
| 97 | 85 | ||
| 98 | 86 | bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) { | |
| 99 | bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) | ||
| 100 | { | ||
| 101 | const auto event = static_cast<Pica::DebugContext::Event>(index.row()); | 87 | const auto event = static_cast<Pica::DebugContext::Event>(index.row()); |
| 102 | 88 | ||
| 103 | switch (role) { | 89 | switch (role) { |
| 104 | case Qt::CheckStateRole: | 90 | case Qt::CheckStateRole: { |
| 105 | { | ||
| 106 | if (index.column() != 0) | 91 | if (index.column() != 0) |
| 107 | return false; | 92 | return false; |
| 108 | 93 | ||
| @@ -120,9 +105,7 @@ bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, i | |||
| 120 | return false; | 105 | return false; |
| 121 | } | 106 | } |
| 122 | 107 | ||
| 123 | 108 | void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) { | |
| 124 | void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) | ||
| 125 | { | ||
| 126 | auto context = context_weak.lock(); | 109 | auto context = context_weak.lock(); |
| 127 | if (!context) | 110 | if (!context) |
| 128 | return; | 111 | return; |
| @@ -133,8 +116,7 @@ void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) | |||
| 133 | createIndex(static_cast<int>(event), 0)); | 116 | createIndex(static_cast<int>(event), 0)); |
| 134 | } | 117 | } |
| 135 | 118 | ||
| 136 | void BreakPointModel::OnResumed() | 119 | void BreakPointModel::OnResumed() { |
| 137 | { | ||
| 138 | auto context = context_weak.lock(); | 120 | auto context = context_weak.lock(); |
| 139 | if (!context) | 121 | if (!context) |
| 140 | return; | 122 | return; |
| @@ -145,12 +127,10 @@ void BreakPointModel::OnResumed() | |||
| 145 | active_breakpoint = context->active_breakpoint; | 127 | active_breakpoint = context->active_breakpoint; |
| 146 | } | 128 | } |
| 147 | 129 | ||
| 148 | 130 | GraphicsBreakPointsWidget::GraphicsBreakPointsWidget( | |
| 149 | GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context, | 131 | std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent) |
| 150 | QWidget* parent) | ||
| 151 | : QDockWidget(tr("Pica Breakpoints"), parent), | 132 | : QDockWidget(tr("Pica Breakpoints"), parent), |
| 152 | Pica::DebugContext::BreakPointObserver(debug_context) | 133 | Pica::DebugContext::BreakPointObserver(debug_context) { |
| 153 | { | ||
| 154 | setObjectName("PicaBreakPointsWidget"); | 134 | setObjectName("PicaBreakPointsWidget"); |
| 155 | 135 | ||
| 156 | status_text = new QLabel(tr("Emulation running")); | 136 | status_text = new QLabel(tr("Emulation running")); |
| @@ -165,23 +145,21 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
| 165 | 145 | ||
| 166 | qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); | 146 | qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); |
| 167 | 147 | ||
| 168 | connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), | 148 | connect(breakpoint_list, SIGNAL(doubleClicked(const QModelIndex&)), this, |
| 169 | this, SLOT(OnItemDoubleClicked(const QModelIndex&))); | 149 | SLOT(OnItemDoubleClicked(const QModelIndex&))); |
| 170 | 150 | ||
| 171 | connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); | 151 | connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); |
| 172 | 152 | ||
| 173 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | 153 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), this, |
| 174 | this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), | 154 | SLOT(OnBreakPointHit(Pica::DebugContext::Event, void*)), Qt::BlockingQueuedConnection); |
| 175 | Qt::BlockingQueuedConnection); | ||
| 176 | connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); | 155 | connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); |
| 177 | 156 | ||
| 178 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), | 157 | connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event, void*)), breakpoint_model, |
| 179 | breakpoint_model, SLOT(OnBreakPointHit(Pica::DebugContext::Event)), | 158 | SLOT(OnBreakPointHit(Pica::DebugContext::Event)), Qt::BlockingQueuedConnection); |
| 180 | Qt::BlockingQueuedConnection); | ||
| 181 | connect(this, SIGNAL(Resumed()), breakpoint_model, SLOT(OnResumed())); | 159 | connect(this, SIGNAL(Resumed()), breakpoint_model, SLOT(OnResumed())); |
| 182 | 160 | ||
| 183 | connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)), | 161 | connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&, const QModelIndex&)), |
| 184 | breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))); | 162 | breakpoint_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&))); |
| 185 | 163 | ||
| 186 | QWidget* main_widget = new QWidget; | 164 | QWidget* main_widget = new QWidget; |
| 187 | auto main_layout = new QVBoxLayout; | 165 | auto main_layout = new QVBoxLayout; |
| @@ -197,38 +175,32 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::Debug | |||
| 197 | setWidget(main_widget); | 175 | setWidget(main_widget); |
| 198 | } | 176 | } |
| 199 | 177 | ||
| 200 | void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data) | 178 | void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data) { |
| 201 | { | ||
| 202 | // Process in GUI thread | 179 | // Process in GUI thread |
| 203 | emit BreakPointHit(event, data); | 180 | emit BreakPointHit(event, data); |
| 204 | } | 181 | } |
| 205 | 182 | ||
| 206 | void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) | 183 | void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) { |
| 207 | { | ||
| 208 | status_text->setText(tr("Emulation halted at breakpoint")); | 184 | status_text->setText(tr("Emulation halted at breakpoint")); |
| 209 | resume_button->setEnabled(true); | 185 | resume_button->setEnabled(true); |
| 210 | } | 186 | } |
| 211 | 187 | ||
| 212 | void GraphicsBreakPointsWidget::OnPicaResume() | 188 | void GraphicsBreakPointsWidget::OnPicaResume() { |
| 213 | { | ||
| 214 | // Process in GUI thread | 189 | // Process in GUI thread |
| 215 | emit Resumed(); | 190 | emit Resumed(); |
| 216 | } | 191 | } |
| 217 | 192 | ||
| 218 | void GraphicsBreakPointsWidget::OnResumed() | 193 | void GraphicsBreakPointsWidget::OnResumed() { |
| 219 | { | ||
| 220 | status_text->setText(tr("Emulation running")); | 194 | status_text->setText(tr("Emulation running")); |
| 221 | resume_button->setEnabled(false); | 195 | resume_button->setEnabled(false); |
| 222 | } | 196 | } |
| 223 | 197 | ||
| 224 | void GraphicsBreakPointsWidget::OnResumeRequested() | 198 | void GraphicsBreakPointsWidget::OnResumeRequested() { |
| 225 | { | ||
| 226 | if (auto context = context_weak.lock()) | 199 | if (auto context = context_weak.lock()) |
| 227 | context->Resume(); | 200 | context->Resume(); |
| 228 | } | 201 | } |
| 229 | 202 | ||
| 230 | void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) | 203 | void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) { |
| 231 | { | ||
| 232 | if (!index.isValid()) | 204 | if (!index.isValid()) |
| 233 | return; | 205 | return; |
| 234 | 206 | ||
diff --git a/src/citra_qt/debugger/graphics_breakpoints.h b/src/citra_qt/debugger/graphics_breakpoints.h index 2371b0e39..5fc40c916 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.h +++ b/src/citra_qt/debugger/graphics_breakpoints.h | |||
| @@ -5,9 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | |||
| 9 | #include <QDockWidget> | 8 | #include <QDockWidget> |
| 10 | |||
| 11 | #include "video_core/debug_utils/debug_utils.h" | 9 | #include "video_core/debug_utils/debug_utils.h" |
| 12 | 10 | ||
| 13 | class QLabel; | 11 | class QLabel; |
diff --git a/src/citra_qt/debugger/graphics_breakpoints_p.h b/src/citra_qt/debugger/graphics_breakpoints_p.h index 251114d06..dc64706bd 100644 --- a/src/citra_qt/debugger/graphics_breakpoints_p.h +++ b/src/citra_qt/debugger/graphics_breakpoints_p.h | |||
| @@ -5,9 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | |||
| 9 | #include <QAbstractListModel> | 8 | #include <QAbstractListModel> |
| 10 | |||
| 11 | #include "video_core/debug_utils/debug_utils.h" | 9 | #include "video_core/debug_utils/debug_utils.h" |
| 12 | 10 | ||
| 13 | class BreakPointModel : public QAbstractListModel { | 11 | class BreakPointModel : public QAbstractListModel { |
| @@ -23,7 +21,7 @@ public: | |||
| 23 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; | 21 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; |
| 24 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; | 22 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
| 25 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | 23 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
| 26 | Qt::ItemFlags flags(const QModelIndex &index) const override; | 24 | Qt::ItemFlags flags(const QModelIndex& index) const override; |
| 27 | 25 | ||
| 28 | bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; | 26 | bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; |
| 29 | 27 | ||
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index 3e0a0a145..8a784d108 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp | |||
| @@ -13,16 +13,13 @@ | |||
| 13 | #include <QSpinBox> | 13 | #include <QSpinBox> |
| 14 | #include <QTreeView> | 14 | #include <QTreeView> |
| 15 | #include <QVBoxLayout> | 15 | #include <QVBoxLayout> |
| 16 | |||
| 17 | #include "citra_qt/debugger/graphics_cmdlists.h" | 16 | #include "citra_qt/debugger/graphics_cmdlists.h" |
| 18 | #include "citra_qt/util/spinbox.h" | 17 | #include "citra_qt/util/spinbox.h" |
| 19 | #include "citra_qt/util/util.h" | 18 | #include "citra_qt/util/util.h" |
| 20 | |||
| 21 | #include "common/vector_math.h" | 19 | #include "common/vector_math.h" |
| 22 | 20 | #include "video_core/debug_utils/debug_utils.h" | |
| 23 | #include "video_core/pica.h" | 21 | #include "video_core/pica.h" |
| 24 | #include "video_core/pica_state.h" | 22 | #include "video_core/pica_state.h" |
| 25 | #include "video_core/debug_utils/debug_utils.h" | ||
| 26 | 23 | ||
| 27 | QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { | 24 | QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { |
| 28 | QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); | 25 | QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); |
| @@ -38,7 +35,8 @@ QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { | |||
| 38 | 35 | ||
| 39 | class TextureInfoWidget : public QWidget { | 36 | class TextureInfoWidget : public QWidget { |
| 40 | public: | 37 | public: |
| 41 | TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr) : QWidget(parent) { | 38 | TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr) |
| 39 | : QWidget(parent) { | ||
| 42 | QLabel* image_widget = new QLabel; | 40 | QLabel* image_widget = new QLabel; |
| 43 | QPixmap image_pixmap = QPixmap::fromImage(LoadTexture(src, info)); | 41 | QPixmap image_pixmap = QPixmap::fromImage(LoadTexture(src, info)); |
| 44 | image_pixmap = image_pixmap.scaled(200, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation); | 42 | image_pixmap = image_pixmap.scaled(200, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation); |
| @@ -50,9 +48,7 @@ public: | |||
| 50 | } | 48 | } |
| 51 | }; | 49 | }; |
| 52 | 50 | ||
| 53 | GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) { | 51 | GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) {} |
| 54 | |||
| 55 | } | ||
| 56 | 52 | ||
| 57 | int GPUCommandListModel::rowCount(const QModelIndex& parent) const { | 53 | int GPUCommandListModel::rowCount(const QModelIndex& parent) const { |
| 58 | return static_cast<int>(pica_trace.writes.size()); | 54 | return static_cast<int>(pica_trace.writes.size()); |
| @@ -70,7 +66,7 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | |||
| 70 | 66 | ||
| 71 | if (role == Qt::DisplayRole) { | 67 | if (role == Qt::DisplayRole) { |
| 72 | QString content; | 68 | QString content; |
| 73 | switch ( index.column() ) { | 69 | switch (index.column()) { |
| 74 | case 0: | 70 | case 0: |
| 75 | return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str()); | 71 | return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str()); |
| 76 | case 1: | 72 | case 1: |
| @@ -88,9 +84,8 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | |||
| 88 | } | 84 | } |
| 89 | 85 | ||
| 90 | QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientation, int role) const { | 86 | QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientation, int role) const { |
| 91 | switch(role) { | 87 | switch (role) { |
| 92 | case Qt::DisplayRole: | 88 | case Qt::DisplayRole: { |
| 93 | { | ||
| 94 | switch (section) { | 89 | switch (section) { |
| 95 | case 0: | 90 | case 0: |
| 96 | return tr("Command Name"); | 91 | return tr("Command Name"); |
| @@ -117,14 +112,14 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& | |||
| 117 | endResetModel(); | 112 | endResetModel(); |
| 118 | } | 113 | } |
| 119 | 114 | ||
| 120 | #define COMMAND_IN_RANGE(cmd_id, reg_name) \ | 115 | #define COMMAND_IN_RANGE(cmd_id, reg_name) \ |
| 121 | (cmd_id >= PICA_REG_INDEX(reg_name) && \ | 116 | (cmd_id >= PICA_REG_INDEX(reg_name) && \ |
| 122 | cmd_id < PICA_REG_INDEX(reg_name) + sizeof(decltype(Pica::g_state.regs.reg_name)) / 4) | 117 | cmd_id < PICA_REG_INDEX(reg_name) + sizeof(decltype(Pica::g_state.regs.reg_name)) / 4) |
| 123 | 118 | ||
| 124 | void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { | 119 | void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { |
| 125 | const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | 120 | const unsigned int command_id = |
| 126 | if (COMMAND_IN_RANGE(command_id, texture0) || | 121 | list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); |
| 127 | COMMAND_IN_RANGE(command_id, texture1) || | 122 | if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || |
| 128 | COMMAND_IN_RANGE(command_id, texture2)) { | 123 | COMMAND_IN_RANGE(command_id, texture2)) { |
| 129 | 124 | ||
| 130 | unsigned index; | 125 | unsigned index; |
| @@ -148,9 +143,9 @@ void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { | |||
| 148 | void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { | 143 | void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { |
| 149 | QWidget* new_info_widget = nullptr; | 144 | QWidget* new_info_widget = nullptr; |
| 150 | 145 | ||
| 151 | const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); | 146 | const unsigned int command_id = |
| 152 | if (COMMAND_IN_RANGE(command_id, texture0) || | 147 | list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); |
| 153 | COMMAND_IN_RANGE(command_id, texture1) || | 148 | if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || |
| 154 | COMMAND_IN_RANGE(command_id, texture2)) { | 149 | COMMAND_IN_RANGE(command_id, texture2)) { |
| 155 | 150 | ||
| 156 | unsigned index; | 151 | unsigned index; |
| @@ -179,7 +174,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { | |||
| 179 | } | 174 | } |
| 180 | #undef COMMAND_IN_RANGE | 175 | #undef COMMAND_IN_RANGE |
| 181 | 176 | ||
| 182 | GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pica Command List"), parent) { | 177 | GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) |
| 178 | : QDockWidget(tr("Pica Command List"), parent) { | ||
| 183 | setObjectName("Pica Command List"); | 179 | setObjectName("Pica Command List"); |
| 184 | GPUCommandListModel* model = new GPUCommandListModel(this); | 180 | GPUCommandListModel* model = new GPUCommandListModel(this); |
| 185 | 181 | ||
| @@ -191,23 +187,24 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi | |||
| 191 | list_widget->setRootIsDecorated(false); | 187 | list_widget->setRootIsDecorated(false); |
| 192 | list_widget->setUniformRowHeights(true); | 188 | list_widget->setUniformRowHeights(true); |
| 193 | 189 | ||
| 194 | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | 190 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) |
| 195 | list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); | 191 | list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); |
| 196 | #else | 192 | #else |
| 197 | list_widget->header()->setResizeMode(QHeaderView::ResizeToContents); | 193 | list_widget->header()->setResizeMode(QHeaderView::ResizeToContents); |
| 198 | #endif | 194 | #endif |
| 199 | 195 | ||
| 200 | connect(list_widget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), | 196 | connect(list_widget->selectionModel(), |
| 201 | this, SLOT(SetCommandInfo(const QModelIndex&))); | 197 | SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, |
| 202 | connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)), | 198 | SLOT(SetCommandInfo(const QModelIndex&))); |
| 203 | this, SLOT(OnCommandDoubleClicked(const QModelIndex&))); | 199 | connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)), this, |
| 200 | SLOT(OnCommandDoubleClicked(const QModelIndex&))); | ||
| 204 | 201 | ||
| 205 | toggle_tracing = new QPushButton(tr("Start Tracing")); | 202 | toggle_tracing = new QPushButton(tr("Start Tracing")); |
| 206 | QPushButton* copy_all = new QPushButton(tr("Copy All")); | 203 | QPushButton* copy_all = new QPushButton(tr("Copy All")); |
| 207 | 204 | ||
| 208 | connect(toggle_tracing, SIGNAL(clicked()), this, SLOT(OnToggleTracing())); | 205 | connect(toggle_tracing, SIGNAL(clicked()), this, SLOT(OnToggleTracing())); |
| 209 | connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)), | 206 | connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)), model, |
| 210 | model, SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&))); | 207 | SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&))); |
| 211 | 208 | ||
| 212 | connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard())); | 209 | connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard())); |
| 213 | 210 | ||
diff --git a/src/citra_qt/debugger/graphics_cmdlists.h b/src/citra_qt/debugger/graphics_cmdlists.h index 8a2a294b9..fa2b9122b 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.h +++ b/src/citra_qt/debugger/graphics_cmdlists.h | |||
| @@ -6,15 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | #include <QAbstractListModel> | 7 | #include <QAbstractListModel> |
| 8 | #include <QDockWidget> | 8 | #include <QDockWidget> |
| 9 | |||
| 10 | #include "video_core/gpu_debugger.h" | ||
| 11 | #include "video_core/debug_utils/debug_utils.h" | 9 | #include "video_core/debug_utils/debug_utils.h" |
| 10 | #include "video_core/gpu_debugger.h" | ||
| 12 | 11 | ||
| 13 | class QPushButton; | 12 | class QPushButton; |
| 14 | class QTreeView; | 13 | class QTreeView; |
| 15 | 14 | ||
| 16 | class GPUCommandListModel : public QAbstractListModel | 15 | class GPUCommandListModel : public QAbstractListModel { |
| 17 | { | ||
| 18 | Q_OBJECT | 16 | Q_OBJECT |
| 19 | 17 | ||
| 20 | public: | 18 | public: |
| @@ -27,7 +25,8 @@ public: | |||
| 27 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; | 25 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; |
| 28 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; | 26 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
| 29 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | 27 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
| 30 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | 28 | QVariant headerData(int section, Qt::Orientation orientation, |
| 29 | int role = Qt::DisplayRole) const override; | ||
| 31 | 30 | ||
| 32 | public slots: | 31 | public slots: |
| 33 | void OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& trace); | 32 | void OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& trace); |
| @@ -36,8 +35,7 @@ private: | |||
| 36 | Pica::DebugUtils::PicaTrace pica_trace; | 35 | Pica::DebugUtils::PicaTrace pica_trace; |
| 37 | }; | 36 | }; |
| 38 | 37 | ||
| 39 | class GPUCommandListWidget : public QDockWidget | 38 | class GPUCommandListWidget : public QDockWidget { |
| 40 | { | ||
| 41 | Q_OBJECT | 39 | Q_OBJECT |
| 42 | 40 | ||
| 43 | public: | 41 | public: |
diff --git a/src/citra_qt/debugger/graphics_surface.cpp b/src/citra_qt/debugger/graphics_surface.cpp index ac2d6f89b..906daaa50 100644 --- a/src/citra_qt/debugger/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics_surface.cpp | |||
| @@ -11,24 +11,20 @@ | |||
| 11 | #include <QPushButton> | 11 | #include <QPushButton> |
| 12 | #include <QScrollArea> | 12 | #include <QScrollArea> |
| 13 | #include <QSpinBox> | 13 | #include <QSpinBox> |
| 14 | |||
| 15 | #include "citra_qt/debugger/graphics_surface.h" | 14 | #include "citra_qt/debugger/graphics_surface.h" |
| 16 | #include "citra_qt/util/spinbox.h" | 15 | #include "citra_qt/util/spinbox.h" |
| 17 | |||
| 18 | #include "common/color.h" | 16 | #include "common/color.h" |
| 19 | |||
| 20 | #include "core/memory.h" | ||
| 21 | #include "core/hw/gpu.h" | 17 | #include "core/hw/gpu.h" |
| 22 | 18 | #include "core/memory.h" | |
| 23 | #include "video_core/pica.h" | 19 | #include "video_core/pica.h" |
| 24 | #include "video_core/pica_state.h" | 20 | #include "video_core/pica_state.h" |
| 25 | #include "video_core/utils.h" | 21 | #include "video_core/utils.h" |
| 26 | 22 | ||
| 27 | SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_) : QLabel(parent), surface_widget(surface_widget_) {} | 23 | SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_) |
| 24 | : QLabel(parent), surface_widget(surface_widget_) {} | ||
| 28 | SurfacePicture::~SurfacePicture() {} | 25 | SurfacePicture::~SurfacePicture() {} |
| 29 | 26 | ||
| 30 | void SurfacePicture::mousePressEvent(QMouseEvent* event) | 27 | void SurfacePicture::mousePressEvent(QMouseEvent* event) { |
| 31 | { | ||
| 32 | // Only do something while the left mouse button is held down | 28 | // Only do something while the left mouse button is held down |
| 33 | if (!(event->buttons() & Qt::LeftButton)) | 29 | if (!(event->buttons() & Qt::LeftButton)) |
| 34 | return; | 30 | return; |
| @@ -41,18 +37,15 @@ void SurfacePicture::mousePressEvent(QMouseEvent* event) | |||
| 41 | event->y() * pixmap()->height() / height()); | 37 | event->y() * pixmap()->height() / height()); |
| 42 | } | 38 | } |
| 43 | 39 | ||
| 44 | void SurfacePicture::mouseMoveEvent(QMouseEvent* event) | 40 | void SurfacePicture::mouseMoveEvent(QMouseEvent* event) { |
| 45 | { | ||
| 46 | // We also want to handle the event if the user moves the mouse while holding down the LMB | 41 | // We also want to handle the event if the user moves the mouse while holding down the LMB |
| 47 | mousePressEvent(event); | 42 | mousePressEvent(event); |
| 48 | } | 43 | } |
| 49 | 44 | ||
| 50 | |||
| 51 | GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, | 45 | GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, |
| 52 | QWidget* parent) | 46 | QWidget* parent) |
| 53 | : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), | 47 | : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), |
| 54 | surface_source(Source::ColorBuffer) | 48 | surface_source(Source::ColorBuffer) { |
| 55 | { | ||
| 56 | setObjectName("PicaSurface"); | 49 | setObjectName("PicaSurface"); |
| 57 | 50 | ||
| 58 | surface_source_list = new QComboBox; | 51 | surface_source_list = new QComboBox; |
| @@ -124,13 +117,20 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> | |||
| 124 | 117 | ||
| 125 | // Connections | 118 | // Connections |
| 126 | connect(this, SIGNAL(Update()), this, SLOT(OnUpdate())); | 119 | connect(this, SIGNAL(Update()), this, SLOT(OnUpdate())); |
| 127 | connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceSourceChanged(int))); | 120 | connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this, |
| 128 | connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this, SLOT(OnSurfaceAddressChanged(qint64))); | 121 | SLOT(OnSurfaceSourceChanged(int))); |
| 129 | connect(surface_width_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceWidthChanged(int))); | 122 | connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this, |
| 130 | connect(surface_height_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceHeightChanged(int))); | 123 | SLOT(OnSurfaceAddressChanged(qint64))); |
| 131 | connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceFormatChanged(int))); | 124 | connect(surface_width_control, SIGNAL(valueChanged(int)), this, |
| 132 | connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerXChanged(int))); | 125 | SLOT(OnSurfaceWidthChanged(int))); |
| 133 | connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerYChanged(int))); | 126 | connect(surface_height_control, SIGNAL(valueChanged(int)), this, |
| 127 | SLOT(OnSurfaceHeightChanged(int))); | ||
| 128 | connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this, | ||
| 129 | SLOT(OnSurfaceFormatChanged(int))); | ||
| 130 | connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this, | ||
| 131 | SLOT(OnSurfacePickerXChanged(int))); | ||
| 132 | connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this, | ||
| 133 | SLOT(OnSurfacePickerYChanged(int))); | ||
| 134 | connect(save_surface, SIGNAL(clicked()), this, SLOT(SaveSurface())); | 134 | connect(save_surface, SIGNAL(clicked()), this, SLOT(SaveSurface())); |
| 135 | 135 | ||
| 136 | auto main_widget = new QWidget; | 136 | auto main_widget = new QWidget; |
| @@ -203,25 +203,21 @@ GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> | |||
| 203 | } | 203 | } |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) | 206 | void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) { |
| 207 | { | ||
| 208 | emit Update(); | 207 | emit Update(); |
| 209 | widget()->setEnabled(true); | 208 | widget()->setEnabled(true); |
| 210 | } | 209 | } |
| 211 | 210 | ||
| 212 | void GraphicsSurfaceWidget::OnResumed() | 211 | void GraphicsSurfaceWidget::OnResumed() { |
| 213 | { | ||
| 214 | widget()->setEnabled(false); | 212 | widget()->setEnabled(false); |
| 215 | } | 213 | } |
| 216 | 214 | ||
| 217 | void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) | 215 | void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) { |
| 218 | { | ||
| 219 | surface_source = static_cast<Source>(new_value); | 216 | surface_source = static_cast<Source>(new_value); |
| 220 | emit Update(); | 217 | emit Update(); |
| 221 | } | 218 | } |
| 222 | 219 | ||
| 223 | void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) | 220 | void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) { |
| 224 | { | ||
| 225 | if (surface_address != new_value) { | 221 | if (surface_address != new_value) { |
| 226 | surface_address = static_cast<unsigned>(new_value); | 222 | surface_address = static_cast<unsigned>(new_value); |
| 227 | 223 | ||
| @@ -230,8 +226,7 @@ void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) | |||
| 230 | } | 226 | } |
| 231 | } | 227 | } |
| 232 | 228 | ||
| 233 | void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) | 229 | void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) { |
| 234 | { | ||
| 235 | if (surface_width != static_cast<unsigned>(new_value)) { | 230 | if (surface_width != static_cast<unsigned>(new_value)) { |
| 236 | surface_width = static_cast<unsigned>(new_value); | 231 | surface_width = static_cast<unsigned>(new_value); |
| 237 | 232 | ||
| @@ -240,8 +235,7 @@ void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) | |||
| 240 | } | 235 | } |
| 241 | } | 236 | } |
| 242 | 237 | ||
| 243 | void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) | 238 | void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) { |
| 244 | { | ||
| 245 | if (surface_height != static_cast<unsigned>(new_value)) { | 239 | if (surface_height != static_cast<unsigned>(new_value)) { |
| 246 | surface_height = static_cast<unsigned>(new_value); | 240 | surface_height = static_cast<unsigned>(new_value); |
| 247 | 241 | ||
| @@ -250,8 +244,7 @@ void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) | |||
| 250 | } | 244 | } |
| 251 | } | 245 | } |
| 252 | 246 | ||
| 253 | void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) | 247 | void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) { |
| 254 | { | ||
| 255 | if (surface_format != static_cast<Format>(new_value)) { | 248 | if (surface_format != static_cast<Format>(new_value)) { |
| 256 | surface_format = static_cast<Format>(new_value); | 249 | surface_format = static_cast<Format>(new_value); |
| 257 | 250 | ||
| @@ -260,24 +253,21 @@ void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) | |||
| 260 | } | 253 | } |
| 261 | } | 254 | } |
| 262 | 255 | ||
| 263 | void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) | 256 | void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) { |
| 264 | { | ||
| 265 | if (surface_picker_x != new_value) { | 257 | if (surface_picker_x != new_value) { |
| 266 | surface_picker_x = new_value; | 258 | surface_picker_x = new_value; |
| 267 | Pick(surface_picker_x, surface_picker_y); | 259 | Pick(surface_picker_x, surface_picker_y); |
| 268 | } | 260 | } |
| 269 | } | 261 | } |
| 270 | 262 | ||
| 271 | void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) | 263 | void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) { |
| 272 | { | ||
| 273 | if (surface_picker_y != new_value) { | 264 | if (surface_picker_y != new_value) { |
| 274 | surface_picker_y = new_value; | 265 | surface_picker_y = new_value; |
| 275 | Pick(surface_picker_x, surface_picker_y); | 266 | Pick(surface_picker_x, surface_picker_y); |
| 276 | } | 267 | } |
| 277 | } | 268 | } |
| 278 | 269 | ||
| 279 | void GraphicsSurfaceWidget::Pick(int x, int y) | 270 | void GraphicsSurfaceWidget::Pick(int x, int y) { |
| 280 | { | ||
| 281 | surface_picker_x_control->setValue(x); | 271 | surface_picker_x_control->setValue(x); |
| 282 | surface_picker_y_control->setValue(y); | 272 | surface_picker_y_control->setValue(y); |
| 283 | 273 | ||
| @@ -312,74 +302,63 @@ void GraphicsSurfaceWidget::Pick(int x, int y) | |||
| 312 | 302 | ||
| 313 | auto GetText = [offset](Format format, const u8* pixel) { | 303 | auto GetText = [offset](Format format, const u8* pixel) { |
| 314 | switch (format) { | 304 | switch (format) { |
| 315 | case Format::RGBA8: | 305 | case Format::RGBA8: { |
| 316 | { | ||
| 317 | auto value = Color::DecodeRGBA8(pixel) / 255.0f; | 306 | auto value = Color::DecodeRGBA8(pixel) / 255.0f; |
| 318 | return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") | 307 | return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") |
| 319 | .arg(QString::number(value.r(), 'f', 2)) | 308 | .arg(QString::number(value.r(), 'f', 2)) |
| 320 | .arg(QString::number(value.g(), 'f', 2)) | 309 | .arg(QString::number(value.g(), 'f', 2)) |
| 321 | .arg(QString::number(value.b(), 'f', 2)) | 310 | .arg(QString::number(value.b(), 'f', 2)) |
| 322 | .arg(QString::number(value.a(), 'f', 2)); | 311 | .arg(QString::number(value.a(), 'f', 2)); |
| 323 | } | 312 | } |
| 324 | case Format::RGB8: | 313 | case Format::RGB8: { |
| 325 | { | ||
| 326 | auto value = Color::DecodeRGB8(pixel) / 255.0f; | 314 | auto value = Color::DecodeRGB8(pixel) / 255.0f; |
| 327 | return QString("Red: %1, Green: %2, Blue: %3") | 315 | return QString("Red: %1, Green: %2, Blue: %3") |
| 328 | .arg(QString::number(value.r(), 'f', 2)) | 316 | .arg(QString::number(value.r(), 'f', 2)) |
| 329 | .arg(QString::number(value.g(), 'f', 2)) | 317 | .arg(QString::number(value.g(), 'f', 2)) |
| 330 | .arg(QString::number(value.b(), 'f', 2)); | 318 | .arg(QString::number(value.b(), 'f', 2)); |
| 331 | } | 319 | } |
| 332 | case Format::RGB5A1: | 320 | case Format::RGB5A1: { |
| 333 | { | ||
| 334 | auto value = Color::DecodeRGB5A1(pixel) / 255.0f; | 321 | auto value = Color::DecodeRGB5A1(pixel) / 255.0f; |
| 335 | return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") | 322 | return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") |
| 336 | .arg(QString::number(value.r(), 'f', 2)) | 323 | .arg(QString::number(value.r(), 'f', 2)) |
| 337 | .arg(QString::number(value.g(), 'f', 2)) | 324 | .arg(QString::number(value.g(), 'f', 2)) |
| 338 | .arg(QString::number(value.b(), 'f', 2)) | 325 | .arg(QString::number(value.b(), 'f', 2)) |
| 339 | .arg(QString::number(value.a(), 'f', 2)); | 326 | .arg(QString::number(value.a(), 'f', 2)); |
| 340 | } | 327 | } |
| 341 | case Format::RGB565: | 328 | case Format::RGB565: { |
| 342 | { | ||
| 343 | auto value = Color::DecodeRGB565(pixel) / 255.0f; | 329 | auto value = Color::DecodeRGB565(pixel) / 255.0f; |
| 344 | return QString("Red: %1, Green: %2, Blue: %3") | 330 | return QString("Red: %1, Green: %2, Blue: %3") |
| 345 | .arg(QString::number(value.r(), 'f', 2)) | 331 | .arg(QString::number(value.r(), 'f', 2)) |
| 346 | .arg(QString::number(value.g(), 'f', 2)) | 332 | .arg(QString::number(value.g(), 'f', 2)) |
| 347 | .arg(QString::number(value.b(), 'f', 2)); | 333 | .arg(QString::number(value.b(), 'f', 2)); |
| 348 | } | 334 | } |
| 349 | case Format::RGBA4: | 335 | case Format::RGBA4: { |
| 350 | { | ||
| 351 | auto value = Color::DecodeRGBA4(pixel) / 255.0f; | 336 | auto value = Color::DecodeRGBA4(pixel) / 255.0f; |
| 352 | return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") | 337 | return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") |
| 353 | .arg(QString::number(value.r(), 'f', 2)) | 338 | .arg(QString::number(value.r(), 'f', 2)) |
| 354 | .arg(QString::number(value.g(), 'f', 2)) | 339 | .arg(QString::number(value.g(), 'f', 2)) |
| 355 | .arg(QString::number(value.b(), 'f', 2)) | 340 | .arg(QString::number(value.b(), 'f', 2)) |
| 356 | .arg(QString::number(value.a(), 'f', 2)); | 341 | .arg(QString::number(value.a(), 'f', 2)); |
| 357 | } | 342 | } |
| 358 | case Format::IA8: | 343 | case Format::IA8: |
| 359 | return QString("Index: %1, Alpha: %2") | 344 | return QString("Index: %1, Alpha: %2").arg(pixel[0]).arg(pixel[1]); |
| 360 | .arg(pixel[0]) | ||
| 361 | .arg(pixel[1]); | ||
| 362 | case Format::RG8: { | 345 | case Format::RG8: { |
| 363 | auto value = Color::DecodeRG8(pixel) / 255.0f; | 346 | auto value = Color::DecodeRG8(pixel) / 255.0f; |
| 364 | return QString("Red: %1, Green: %2") | 347 | return QString("Red: %1, Green: %2") |
| 365 | .arg(QString::number(value.r(), 'f', 2)) | 348 | .arg(QString::number(value.r(), 'f', 2)) |
| 366 | .arg(QString::number(value.g(), 'f', 2)); | 349 | .arg(QString::number(value.g(), 'f', 2)); |
| 367 | } | 350 | } |
| 368 | case Format::I8: | 351 | case Format::I8: |
| 369 | return QString("Index: %1").arg(*pixel); | 352 | return QString("Index: %1").arg(*pixel); |
| 370 | case Format::A8: | 353 | case Format::A8: |
| 371 | return QString("Alpha: %1").arg(QString::number(*pixel / 255.0f, 'f', 2)); | 354 | return QString("Alpha: %1").arg(QString::number(*pixel / 255.0f, 'f', 2)); |
| 372 | case Format::IA4: | 355 | case Format::IA4: |
| 373 | return QString("Index: %1, Alpha: %2") | 356 | return QString("Index: %1, Alpha: %2").arg(*pixel & 0xF).arg((*pixel & 0xF0) >> 4); |
| 374 | .arg(*pixel & 0xF) | 357 | case Format::I4: { |
| 375 | .arg((*pixel & 0xF0) >> 4); | ||
| 376 | case Format::I4: | ||
| 377 | { | ||
| 378 | u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; | 358 | u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; |
| 379 | return QString("Index: %1").arg(i); | 359 | return QString("Index: %1").arg(i); |
| 380 | } | 360 | } |
| 381 | case Format::A4: | 361 | case Format::A4: { |
| 382 | { | ||
| 383 | u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; | 362 | u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; |
| 384 | return QString("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2)); | 363 | return QString("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2)); |
| 385 | } | 364 | } |
| @@ -387,21 +366,20 @@ void GraphicsSurfaceWidget::Pick(int x, int y) | |||
| 387 | case Format::ETC1A4: | 366 | case Format::ETC1A4: |
| 388 | // TODO: Display block information or channel values? | 367 | // TODO: Display block information or channel values? |
| 389 | return QString("Compressed data"); | 368 | return QString("Compressed data"); |
| 390 | case Format::D16: | 369 | case Format::D16: { |
| 391 | { | ||
| 392 | auto value = Color::DecodeD16(pixel); | 370 | auto value = Color::DecodeD16(pixel); |
| 393 | return QString("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4)); | 371 | return QString("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4)); |
| 394 | } | 372 | } |
| 395 | case Format::D24: | 373 | case Format::D24: { |
| 396 | { | ||
| 397 | auto value = Color::DecodeD24(pixel); | 374 | auto value = Color::DecodeD24(pixel); |
| 398 | return QString("Depth: %1").arg(QString::number(value / (float)0xFFFFFF, 'f', 4)); | 375 | return QString("Depth: %1").arg(QString::number(value / (float)0xFFFFFF, 'f', 4)); |
| 399 | } | 376 | } |
| 400 | case Format::D24X8: | 377 | case Format::D24X8: |
| 401 | case Format::X24S8: | 378 | case Format::X24S8: { |
| 402 | { | ||
| 403 | auto values = Color::DecodeD24S8(pixel); | 379 | auto values = Color::DecodeD24S8(pixel); |
| 404 | return QString("Depth: %1, Stencil: %2").arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4)).arg(values[1]); | 380 | return QString("Depth: %1, Stencil: %2") |
| 381 | .arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4)) | ||
| 382 | .arg(values[1]); | ||
| 405 | } | 383 | } |
| 406 | case Format::Unknown: | 384 | case Format::Unknown: |
| 407 | return QString("Unknown format"); | 385 | return QString("Unknown format"); |
| @@ -422,18 +400,18 @@ void GraphicsSurfaceWidget::Pick(int x, int y) | |||
| 422 | nibbles.append(QString::number(nibble, 16).toUpper()); | 400 | nibbles.append(QString::number(nibble, 16).toUpper()); |
| 423 | } | 401 | } |
| 424 | 402 | ||
| 425 | surface_info_label->setText(QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel))); | 403 | surface_info_label->setText( |
| 404 | QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel))); | ||
| 426 | surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); | 405 | surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); |
| 427 | } | 406 | } |
| 428 | 407 | ||
| 429 | void GraphicsSurfaceWidget::OnUpdate() | 408 | void GraphicsSurfaceWidget::OnUpdate() { |
| 430 | { | ||
| 431 | QPixmap pixmap; | 409 | QPixmap pixmap; |
| 432 | 410 | ||
| 433 | switch (surface_source) { | 411 | switch (surface_source) { |
| 434 | case Source::ColorBuffer: | 412 | case Source::ColorBuffer: { |
| 435 | { | 413 | // TODO: Store a reference to the registers in the debug context instead of accessing them |
| 436 | // TODO: Store a reference to the registers in the debug context instead of accessing them directly... | 414 | // directly... |
| 437 | 415 | ||
| 438 | const auto& framebuffer = Pica::g_state.regs.framebuffer; | 416 | const auto& framebuffer = Pica::g_state.regs.framebuffer; |
| 439 | 417 | ||
| @@ -470,8 +448,7 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 470 | break; | 448 | break; |
| 471 | } | 449 | } |
| 472 | 450 | ||
| 473 | case Source::DepthBuffer: | 451 | case Source::DepthBuffer: { |
| 474 | { | ||
| 475 | const auto& framebuffer = Pica::g_state.regs.framebuffer; | 452 | const auto& framebuffer = Pica::g_state.regs.framebuffer; |
| 476 | 453 | ||
| 477 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); | 454 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); |
| @@ -499,8 +476,7 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 499 | break; | 476 | break; |
| 500 | } | 477 | } |
| 501 | 478 | ||
| 502 | case Source::StencilBuffer: | 479 | case Source::StencilBuffer: { |
| 503 | { | ||
| 504 | const auto& framebuffer = Pica::g_state.regs.framebuffer; | 480 | const auto& framebuffer = Pica::g_state.regs.framebuffer; |
| 505 | 481 | ||
| 506 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); | 482 | surface_address = framebuffer.GetDepthBufferPhysicalAddress(); |
| @@ -522,12 +498,14 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 522 | 498 | ||
| 523 | case Source::Texture0: | 499 | case Source::Texture0: |
| 524 | case Source::Texture1: | 500 | case Source::Texture1: |
| 525 | case Source::Texture2: | 501 | case Source::Texture2: { |
| 526 | { | ||
| 527 | unsigned texture_index; | 502 | unsigned texture_index; |
| 528 | if (surface_source == Source::Texture0) texture_index = 0; | 503 | if (surface_source == Source::Texture0) |
| 529 | else if (surface_source == Source::Texture1) texture_index = 1; | 504 | texture_index = 0; |
| 530 | else if (surface_source == Source::Texture2) texture_index = 2; | 505 | else if (surface_source == Source::Texture1) |
| 506 | texture_index = 1; | ||
| 507 | else if (surface_source == Source::Texture2) | ||
| 508 | texture_index = 2; | ||
| 531 | else { | 509 | else { |
| 532 | qDebug() << "Unknown texture source " << static_cast<int>(surface_source); | 510 | qDebug() << "Unknown texture source " << static_cast<int>(surface_source); |
| 533 | break; | 511 | break; |
| @@ -547,8 +525,7 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 547 | break; | 525 | break; |
| 548 | } | 526 | } |
| 549 | 527 | ||
| 550 | case Source::Custom: | 528 | case Source::Custom: { |
| 551 | { | ||
| 552 | // Keep user-specified values | 529 | // Keep user-specified values |
| 553 | break; | 530 | break; |
| 554 | } | 531 | } |
| @@ -613,7 +590,8 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 613 | 590 | ||
| 614 | } else { | 591 | } else { |
| 615 | 592 | ||
| 616 | ASSERT_MSG(nibbles_per_pixel >= 2, "Depth decoder only supports formats with at least one byte per pixel"); | 593 | ASSERT_MSG(nibbles_per_pixel >= 2, |
| 594 | "Depth decoder only supports formats with at least one byte per pixel"); | ||
| 617 | unsigned bytes_per_pixel = nibbles_per_pixel / 2; | 595 | unsigned bytes_per_pixel = nibbles_per_pixel / 2; |
| 618 | 596 | ||
| 619 | for (unsigned int y = 0; y < surface_height; ++y) { | 597 | for (unsigned int y = 0; y < surface_height; ++y) { |
| @@ -621,34 +599,30 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 621 | const u32 coarse_y = y & ~7; | 599 | const u32 coarse_y = y & ~7; |
| 622 | u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; | 600 | u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; |
| 623 | const u8* pixel = buffer + offset; | 601 | const u8* pixel = buffer + offset; |
| 624 | Math::Vec4<u8> color = { 0, 0, 0, 0 }; | 602 | Math::Vec4<u8> color = {0, 0, 0, 0}; |
| 625 | 603 | ||
| 626 | switch(surface_format) { | 604 | switch (surface_format) { |
| 627 | case Format::D16: | 605 | case Format::D16: { |
| 628 | { | ||
| 629 | u32 data = Color::DecodeD16(pixel); | 606 | u32 data = Color::DecodeD16(pixel); |
| 630 | color.r() = data & 0xFF; | 607 | color.r() = data & 0xFF; |
| 631 | color.g() = (data >> 8) & 0xFF; | 608 | color.g() = (data >> 8) & 0xFF; |
| 632 | break; | 609 | break; |
| 633 | } | 610 | } |
| 634 | case Format::D24: | 611 | case Format::D24: { |
| 635 | { | ||
| 636 | u32 data = Color::DecodeD24(pixel); | 612 | u32 data = Color::DecodeD24(pixel); |
| 637 | color.r() = data & 0xFF; | 613 | color.r() = data & 0xFF; |
| 638 | color.g() = (data >> 8) & 0xFF; | 614 | color.g() = (data >> 8) & 0xFF; |
| 639 | color.b() = (data >> 16) & 0xFF; | 615 | color.b() = (data >> 16) & 0xFF; |
| 640 | break; | 616 | break; |
| 641 | } | 617 | } |
| 642 | case Format::D24X8: | 618 | case Format::D24X8: { |
| 643 | { | ||
| 644 | Math::Vec2<u32> data = Color::DecodeD24S8(pixel); | 619 | Math::Vec2<u32> data = Color::DecodeD24S8(pixel); |
| 645 | color.r() = data.x & 0xFF; | 620 | color.r() = data.x & 0xFF; |
| 646 | color.g() = (data.x >> 8) & 0xFF; | 621 | color.g() = (data.x >> 8) & 0xFF; |
| 647 | color.b() = (data.x >> 16) & 0xFF; | 622 | color.b() = (data.x >> 16) & 0xFF; |
| 648 | break; | 623 | break; |
| 649 | } | 624 | } |
| 650 | case Format::X24S8: | 625 | case Format::X24S8: { |
| 651 | { | ||
| 652 | Math::Vec2<u32> data = Color::DecodeD24S8(pixel); | 626 | Math::Vec2<u32> data = Color::DecodeD24S8(pixel); |
| 653 | color.r() = color.g() = color.b() = data.y; | 627 | color.r() = color.g() = color.b() = data.y; |
| 654 | break; | 628 | break; |
| @@ -661,7 +635,6 @@ void GraphicsSurfaceWidget::OnUpdate() | |||
| 661 | decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), 255)); | 635 | decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), 255)); |
| 662 | } | 636 | } |
| 663 | } | 637 | } |
| 664 | |||
| 665 | } | 638 | } |
| 666 | 639 | ||
| 667 | pixmap = QPixmap::fromImage(decoded_image); | 640 | pixmap = QPixmap::fromImage(decoded_image); |
| @@ -682,8 +655,10 @@ void GraphicsSurfaceWidget::SaveSurface() { | |||
| 682 | QString bin_filter = tr("Binary data (*.bin)"); | 655 | QString bin_filter = tr("Binary data (*.bin)"); |
| 683 | 656 | ||
| 684 | QString selectedFilter; | 657 | QString selectedFilter; |
| 685 | QString filename = QFileDialog::getSaveFileName(this, tr("Save Surface"), QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), | 658 | QString filename = QFileDialog::getSaveFileName( |
| 686 | QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); | 659 | this, tr("Save Surface"), |
| 660 | QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), | ||
| 661 | QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); | ||
| 687 | 662 | ||
| 688 | if (filename.isEmpty()) { | 663 | if (filename.isEmpty()) { |
| 689 | // If the user canceled the dialog, don't save anything. | 664 | // If the user canceled the dialog, don't save anything. |
| @@ -718,19 +693,18 @@ unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Forma | |||
| 718 | } | 693 | } |
| 719 | 694 | ||
| 720 | switch (format) { | 695 | switch (format) { |
| 721 | case Format::D24X8: | 696 | case Format::D24X8: |
| 722 | case Format::X24S8: | 697 | case Format::X24S8: |
| 723 | return 4 * 2; | 698 | return 4 * 2; |
| 724 | case Format::D24: | 699 | case Format::D24: |
| 725 | return 3 * 2; | 700 | return 3 * 2; |
| 726 | case Format::D16: | 701 | case Format::D16: |
| 727 | return 2 * 2; | 702 | return 2 * 2; |
| 728 | default: | 703 | default: |
| 729 | UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this " | 704 | UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this should not be reached as this " |
| 730 | "should not be reached as this function should " | 705 | "function should be given a format which is in " |
| 731 | "be given a format which is in " | 706 | "GraphicsSurfaceWidget::Format. Instead got %i", |
| 732 | "GraphicsSurfaceWidget::Format. Instead got %i", | 707 | static_cast<int>(format)); |
| 733 | static_cast<int>(format)); | 708 | return 0; |
| 734 | return 0; | ||
| 735 | } | 709 | } |
| 736 | } | 710 | } |
diff --git a/src/citra_qt/debugger/graphics_surface.h b/src/citra_qt/debugger/graphics_surface.h index 7c7f50e38..21e6b5b8b 100644 --- a/src/citra_qt/debugger/graphics_surface.h +++ b/src/citra_qt/debugger/graphics_surface.h | |||
| @@ -4,10 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "citra_qt/debugger/graphics_breakpoint_observer.h" | ||
| 8 | |||
| 9 | #include <QLabel> | 7 | #include <QLabel> |
| 10 | #include <QPushButton> | 8 | #include <QPushButton> |
| 9 | #include "citra_qt/debugger/graphics_breakpoint_observer.h" | ||
| 11 | 10 | ||
| 12 | class QComboBox; | 11 | class QComboBox; |
| 13 | class QSpinBox; | 12 | class QSpinBox; |
| @@ -15,8 +14,7 @@ class CSpinBox; | |||
| 15 | 14 | ||
| 16 | class GraphicsSurfaceWidget; | 15 | class GraphicsSurfaceWidget; |
| 17 | 16 | ||
| 18 | class SurfacePicture : public QLabel | 17 | class SurfacePicture : public QLabel { |
| 19 | { | ||
| 20 | Q_OBJECT | 18 | Q_OBJECT |
| 21 | 19 | ||
| 22 | public: | 20 | public: |
| @@ -29,7 +27,6 @@ protected slots: | |||
| 29 | 27 | ||
| 30 | private: | 28 | private: |
| 31 | GraphicsSurfaceWidget* surface_widget; | 29 | GraphicsSurfaceWidget* surface_widget; |
| 32 | |||
| 33 | }; | 30 | }; |
| 34 | 31 | ||
| 35 | class GraphicsSurfaceWidget : public BreakPointObserverDock { | 32 | class GraphicsSurfaceWidget : public BreakPointObserverDock { |
| @@ -38,43 +35,44 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock { | |||
| 38 | using Event = Pica::DebugContext::Event; | 35 | using Event = Pica::DebugContext::Event; |
| 39 | 36 | ||
| 40 | enum class Source { | 37 | enum class Source { |
| 41 | ColorBuffer = 0, | 38 | ColorBuffer = 0, |
| 42 | DepthBuffer = 1, | 39 | DepthBuffer = 1, |
| 43 | StencilBuffer = 2, | 40 | StencilBuffer = 2, |
| 44 | Texture0 = 3, | 41 | Texture0 = 3, |
| 45 | Texture1 = 4, | 42 | Texture1 = 4, |
| 46 | Texture2 = 5, | 43 | Texture2 = 5, |
| 47 | Custom = 6, | 44 | Custom = 6, |
| 48 | }; | 45 | }; |
| 49 | 46 | ||
| 50 | enum class Format { | 47 | enum class Format { |
| 51 | // These must match the TextureFormat type! | 48 | // These must match the TextureFormat type! |
| 52 | RGBA8 = 0, | 49 | RGBA8 = 0, |
| 53 | RGB8 = 1, | 50 | RGB8 = 1, |
| 54 | RGB5A1 = 2, | 51 | RGB5A1 = 2, |
| 55 | RGB565 = 3, | 52 | RGB565 = 3, |
| 56 | RGBA4 = 4, | 53 | RGBA4 = 4, |
| 57 | IA8 = 5, | 54 | IA8 = 5, |
| 58 | RG8 = 6, ///< @note Also called HILO8 in 3DBrew. | 55 | RG8 = 6, ///< @note Also called HILO8 in 3DBrew. |
| 59 | I8 = 7, | 56 | I8 = 7, |
| 60 | A8 = 8, | 57 | A8 = 8, |
| 61 | IA4 = 9, | 58 | IA4 = 9, |
| 62 | I4 = 10, | 59 | I4 = 10, |
| 63 | A4 = 11, | 60 | A4 = 11, |
| 64 | ETC1 = 12, // compressed | 61 | ETC1 = 12, // compressed |
| 65 | ETC1A4 = 13, | 62 | ETC1A4 = 13, |
| 66 | MaxTextureFormat = 13, | 63 | MaxTextureFormat = 13, |
| 67 | D16 = 14, | 64 | D16 = 14, |
| 68 | D24 = 15, | 65 | D24 = 15, |
| 69 | D24X8 = 16, | 66 | D24X8 = 16, |
| 70 | X24S8 = 17, | 67 | X24S8 = 17, |
| 71 | Unknown = 18, | 68 | Unknown = 18, |
| 72 | }; | 69 | }; |
| 73 | 70 | ||
| 74 | static unsigned int NibblesPerPixel(Format format); | 71 | static unsigned int NibblesPerPixel(Format format); |
| 75 | 72 | ||
| 76 | public: | 73 | public: |
| 77 | GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr); | 74 | GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, |
| 75 | QWidget* parent = nullptr); | ||
| 78 | void Pick(int x, int y); | 76 | void Pick(int x, int y); |
| 79 | 77 | ||
| 80 | public slots: | 78 | public slots: |
| @@ -97,7 +95,6 @@ signals: | |||
| 97 | void Update(); | 95 | void Update(); |
| 98 | 96 | ||
| 99 | private: | 97 | private: |
| 100 | |||
| 101 | QComboBox* surface_source_list; | 98 | QComboBox* surface_source_list; |
| 102 | CSpinBox* surface_address_control; | 99 | CSpinBox* surface_address_control; |
| 103 | QSpinBox* surface_width_control; | 100 | QSpinBox* surface_width_control; |
diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp index 9c80f7ec9..5c6b74034 100644 --- a/src/citra_qt/debugger/graphics_tracing.cpp +++ b/src/citra_qt/debugger/graphics_tracing.cpp | |||
| @@ -6,25 +6,18 @@ | |||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <iterator> | 7 | #include <iterator> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | |||
| 10 | #include <boost/range/algorithm/copy.hpp> | ||
| 11 | |||
| 12 | #include <QBoxLayout> | 9 | #include <QBoxLayout> |
| 13 | #include <QComboBox> | 10 | #include <QComboBox> |
| 14 | #include <QFileDialog> | 11 | #include <QFileDialog> |
| 15 | #include <QMessageBox> | 12 | #include <QMessageBox> |
| 16 | #include <QPushButton> | 13 | #include <QPushButton> |
| 17 | 14 | #include <boost/range/algorithm/copy.hpp> | |
| 18 | #include "citra_qt/debugger/graphics_tracing.h" | 15 | #include "citra_qt/debugger/graphics_tracing.h" |
| 19 | |||
| 20 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 21 | |||
| 22 | #include "core/hw/gpu.h" | 17 | #include "core/hw/gpu.h" |
| 23 | #include "core/hw/lcd.h" | 18 | #include "core/hw/lcd.h" |
| 24 | #include "core/tracer/recorder.h" | 19 | #include "core/tracer/recorder.h" |
| 25 | |||
| 26 | #include "nihstro/float24.h" | 20 | #include "nihstro/float24.h" |
| 27 | |||
| 28 | #include "video_core/pica.h" | 21 | #include "video_core/pica.h" |
| 29 | #include "video_core/pica_state.h" | 22 | #include "video_core/pica_state.h" |
| 30 | 23 | ||
| @@ -35,12 +28,16 @@ GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> | |||
| 35 | setObjectName("CiTracing"); | 28 | setObjectName("CiTracing"); |
| 36 | 29 | ||
| 37 | QPushButton* start_recording = new QPushButton(tr("Start Recording")); | 30 | QPushButton* start_recording = new QPushButton(tr("Start Recording")); |
| 38 | QPushButton* stop_recording = new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save")); | 31 | QPushButton* stop_recording = |
| 32 | new QPushButton(QIcon::fromTheme("document-save"), tr("Stop and Save")); | ||
| 39 | QPushButton* abort_recording = new QPushButton(tr("Abort Recording")); | 33 | QPushButton* abort_recording = new QPushButton(tr("Abort Recording")); |
| 40 | 34 | ||
| 41 | connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording, SLOT(setVisible(bool))); | 35 | connect(this, SIGNAL(SetStartTracingButtonEnabled(bool)), start_recording, |
| 42 | connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording, SLOT(setVisible(bool))); | 36 | SLOT(setVisible(bool))); |
| 43 | connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording, SLOT(setVisible(bool))); | 37 | connect(this, SIGNAL(SetStopTracingButtonEnabled(bool)), stop_recording, |
| 38 | SLOT(setVisible(bool))); | ||
| 39 | connect(this, SIGNAL(SetAbortTracingButtonEnabled(bool)), abort_recording, | ||
| 40 | SLOT(setVisible(bool))); | ||
| 44 | connect(start_recording, SIGNAL(clicked()), this, SLOT(StartRecording())); | 41 | connect(start_recording, SIGNAL(clicked()), this, SLOT(StartRecording())); |
| 45 | connect(stop_recording, SIGNAL(clicked()), this, SLOT(StopRecording())); | 42 | connect(stop_recording, SIGNAL(clicked()), this, SLOT(StopRecording())); |
| 46 | connect(abort_recording, SIGNAL(clicked()), this, SLOT(AbortRecording())); | 43 | connect(abort_recording, SIGNAL(clicked()), this, SLOT(AbortRecording())); |
| @@ -74,26 +71,31 @@ void GraphicsTracingWidget::StartRecording() { | |||
| 74 | std::array<u32, 4 * 16> default_attributes; | 71 | std::array<u32, 4 * 16> default_attributes; |
| 75 | for (unsigned i = 0; i < 16; ++i) { | 72 | for (unsigned i = 0; i < 16; ++i) { |
| 76 | for (unsigned comp = 0; comp < 3; ++comp) { | 73 | for (unsigned comp = 0; comp < 3; ++comp) { |
| 77 | default_attributes[4 * i + comp] = nihstro::to_float24(Pica::g_state.vs_default_attributes[i][comp].ToFloat32()); | 74 | default_attributes[4 * i + comp] = |
| 75 | nihstro::to_float24(Pica::g_state.vs_default_attributes[i][comp].ToFloat32()); | ||
| 78 | } | 76 | } |
| 79 | } | 77 | } |
| 80 | 78 | ||
| 81 | std::array<u32, 4 * 96> vs_float_uniforms; | 79 | std::array<u32, 4 * 96> vs_float_uniforms; |
| 82 | for (unsigned i = 0; i < 96; ++i) | 80 | for (unsigned i = 0; i < 96; ++i) |
| 83 | for (unsigned comp = 0; comp < 3; ++comp) | 81 | for (unsigned comp = 0; comp < 3; ++comp) |
| 84 | vs_float_uniforms[4 * i + comp] = nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32()); | 82 | vs_float_uniforms[4 * i + comp] = |
| 83 | nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32()); | ||
| 85 | 84 | ||
| 86 | CiTrace::Recorder::InitialState state; | 85 | CiTrace::Recorder::InitialState state; |
| 87 | std::copy_n((u32*)&GPU::g_regs, sizeof(GPU::g_regs) / sizeof(u32), std::back_inserter(state.gpu_registers)); | 86 | std::copy_n((u32*)&GPU::g_regs, sizeof(GPU::g_regs) / sizeof(u32), |
| 88 | std::copy_n((u32*)&LCD::g_regs, sizeof(LCD::g_regs) / sizeof(u32), std::back_inserter(state.lcd_registers)); | 87 | std::back_inserter(state.gpu_registers)); |
| 89 | std::copy_n((u32*)&Pica::g_state.regs, sizeof(Pica::g_state.regs) / sizeof(u32), std::back_inserter(state.pica_registers)); | 88 | std::copy_n((u32*)&LCD::g_regs, sizeof(LCD::g_regs) / sizeof(u32), |
| 89 | std::back_inserter(state.lcd_registers)); | ||
| 90 | std::copy_n((u32*)&Pica::g_state.regs, sizeof(Pica::g_state.regs) / sizeof(u32), | ||
| 91 | std::back_inserter(state.pica_registers)); | ||
| 90 | boost::copy(default_attributes, std::back_inserter(state.default_attributes)); | 92 | boost::copy(default_attributes, std::back_inserter(state.default_attributes)); |
| 91 | boost::copy(shader_binary, std::back_inserter(state.vs_program_binary)); | 93 | boost::copy(shader_binary, std::back_inserter(state.vs_program_binary)); |
| 92 | boost::copy(swizzle_data, std::back_inserter(state.vs_swizzle_data)); | 94 | boost::copy(swizzle_data, std::back_inserter(state.vs_swizzle_data)); |
| 93 | boost::copy(vs_float_uniforms, std::back_inserter(state.vs_float_uniforms)); | 95 | boost::copy(vs_float_uniforms, std::back_inserter(state.vs_float_uniforms)); |
| 94 | //boost::copy(TODO: Not implemented, std::back_inserter(state.gs_program_binary)); | 96 | // boost::copy(TODO: Not implemented, std::back_inserter(state.gs_program_binary)); |
| 95 | //boost::copy(TODO: Not implemented, std::back_inserter(state.gs_swizzle_data)); | 97 | // boost::copy(TODO: Not implemented, std::back_inserter(state.gs_swizzle_data)); |
| 96 | //boost::copy(TODO: Not implemented, std::back_inserter(state.gs_float_uniforms)); | 98 | // boost::copy(TODO: Not implemented, std::back_inserter(state.gs_float_uniforms)); |
| 97 | 99 | ||
| 98 | auto recorder = new CiTrace::Recorder(state); | 100 | auto recorder = new CiTrace::Recorder(state); |
| 99 | context->recorder = std::shared_ptr<CiTrace::Recorder>(recorder); | 101 | context->recorder = std::shared_ptr<CiTrace::Recorder>(recorder); |
| @@ -156,11 +158,12 @@ void GraphicsTracingWidget::OnEmulationStopping() { | |||
| 156 | if (!context) | 158 | if (!context) |
| 157 | return; | 159 | return; |
| 158 | 160 | ||
| 159 | |||
| 160 | if (context->recorder) { | 161 | if (context->recorder) { |
| 161 | auto reply = QMessageBox::question(this, tr("CiTracing still active"), | 162 | auto reply = |
| 162 | tr("A CiTrace is still being recorded. Do you want to save it? If not, all recorded data will be discarded."), | 163 | QMessageBox::question(this, tr("CiTracing still active"), |
| 163 | QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); | 164 | tr("A CiTrace is still being recorded. Do you want to save it? " |
| 165 | "If not, all recorded data will be discarded."), | ||
| 166 | QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); | ||
| 164 | 167 | ||
| 165 | if (reply == QMessageBox::Yes) { | 168 | if (reply == QMessageBox::Yes) { |
| 166 | StopRecording(); | 169 | StopRecording(); |
diff --git a/src/citra_qt/debugger/graphics_tracing.h b/src/citra_qt/debugger/graphics_tracing.h index 753dfa914..e04a3dac3 100644 --- a/src/citra_qt/debugger/graphics_tracing.h +++ b/src/citra_qt/debugger/graphics_tracing.h | |||
| @@ -12,7 +12,8 @@ class GraphicsTracingWidget : public BreakPointObserverDock { | |||
| 12 | Q_OBJECT | 12 | Q_OBJECT |
| 13 | 13 | ||
| 14 | public: | 14 | public: |
| 15 | GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent = nullptr); | 15 | GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, |
| 16 | QWidget* parent = nullptr); | ||
| 16 | 17 | ||
| 17 | private slots: | 18 | private slots: |
| 18 | void StartRecording(); | 19 | void StartRecording(); |
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp index 391666d35..0b4320da5 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #include <iomanip> | 5 | #include <iomanip> |
| 6 | #include <sstream> | 6 | #include <sstream> |
| 7 | |||
| 8 | #include <QBoxLayout> | 7 | #include <QBoxLayout> |
| 9 | #include <QFileDialog> | 8 | #include <QFileDialog> |
| 10 | #include <QFormLayout> | 9 | #include <QFormLayout> |
| @@ -15,10 +14,8 @@ | |||
| 15 | #include <QSignalMapper> | 14 | #include <QSignalMapper> |
| 16 | #include <QSpinBox> | 15 | #include <QSpinBox> |
| 17 | #include <QTreeView> | 16 | #include <QTreeView> |
| 18 | |||
| 19 | #include "citra_qt/debugger/graphics_vertex_shader.h" | 17 | #include "citra_qt/debugger/graphics_vertex_shader.h" |
| 20 | #include "citra_qt/util/util.h" | 18 | #include "citra_qt/util/util.h" |
| 21 | |||
| 22 | #include "video_core/pica.h" | 19 | #include "video_core/pica.h" |
| 23 | #include "video_core/pica_state.h" | 20 | #include "video_core/pica_state.h" |
| 24 | #include "video_core/shader/shader.h" | 21 | #include "video_core/shader/shader.h" |
| @@ -28,9 +25,8 @@ using nihstro::Instruction; | |||
| 28 | using nihstro::SourceRegister; | 25 | using nihstro::SourceRegister; |
| 29 | using nihstro::SwizzlePattern; | 26 | using nihstro::SwizzlePattern; |
| 30 | 27 | ||
| 31 | GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent): QAbstractTableModel(parent), par(parent) { | 28 | GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent) |
| 32 | 29 | : QAbstractTableModel(parent), par(parent) {} | |
| 33 | } | ||
| 34 | 30 | ||
| 35 | int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const { | 31 | int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const { |
| 36 | return 3; | 32 | return 3; |
| @@ -40,10 +36,10 @@ int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { | |||
| 40 | return static_cast<int>(par->info.code.size()); | 36 | return static_cast<int>(par->info.code.size()); |
| 41 | } | 37 | } |
| 42 | 38 | ||
| 43 | QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { | 39 | QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, |
| 44 | switch(role) { | 40 | int role) const { |
| 45 | case Qt::DisplayRole: | 41 | switch (role) { |
| 46 | { | 42 | case Qt::DisplayRole: { |
| 47 | if (section == 0) { | 43 | if (section == 0) { |
| 48 | return tr("Offset"); | 44 | return tr("Offset"); |
| 49 | } else if (section == 1) { | 45 | } else if (section == 1) { |
| @@ -69,8 +65,8 @@ static std::string SelectorToString(u32 selector) { | |||
| 69 | } | 65 | } |
| 70 | 66 | ||
| 71 | // e.g. "-c92[a0.x].xyzw" | 67 | // e.g. "-c92[a0.x].xyzw" |
| 72 | static void print_input(std::ostringstream& output, const SourceRegister& input, | 68 | static void print_input(std::ostringstream& output, const SourceRegister& input, bool negate, |
| 73 | bool negate, const std::string& swizzle_mask, bool align = true, | 69 | const std::string& swizzle_mask, bool align = true, |
| 74 | const std::string& address_register_name = std::string()) { | 70 | const std::string& address_register_name = std::string()) { |
| 75 | if (align) | 71 | if (align) |
| 76 | output << std::setw(4) << std::right; | 72 | output << std::setw(4) << std::right; |
| @@ -83,20 +79,18 @@ static void print_input(std::ostringstream& output, const SourceRegister& input, | |||
| 83 | 79 | ||
| 84 | QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const { | 80 | QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const { |
| 85 | switch (role) { | 81 | switch (role) { |
| 86 | case Qt::DisplayRole: | 82 | case Qt::DisplayRole: { |
| 87 | { | ||
| 88 | switch (index.column()) { | 83 | switch (index.column()) { |
| 89 | case 0: | 84 | case 0: |
| 90 | if (par->info.HasLabel(index.row())) | 85 | if (par->info.HasLabel(index.row())) |
| 91 | return QString::fromStdString(par->info.GetLabel(index.row())); | 86 | return QString::fromStdString(par->info.GetLabel(index.row())); |
| 92 | 87 | ||
| 93 | return QString("%1").arg(4*index.row(), 4, 16, QLatin1Char('0')); | 88 | return QString("%1").arg(4 * index.row(), 4, 16, QLatin1Char('0')); |
| 94 | 89 | ||
| 95 | case 1: | 90 | case 1: |
| 96 | return QString("%1").arg(par->info.code[index.row()].hex, 8, 16, QLatin1Char('0')); | 91 | return QString("%1").arg(par->info.code[index.row()].hex, 8, 16, QLatin1Char('0')); |
| 97 | 92 | ||
| 98 | case 2: | 93 | case 2: { |
| 99 | { | ||
| 100 | std::ostringstream output; | 94 | std::ostringstream output; |
| 101 | output.flags(std::ios::uppercase); | 95 | output.flags(std::ios::uppercase); |
| 102 | 96 | ||
| @@ -117,8 +111,9 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 117 | const Instruction instr = par->info.code[index.row()]; | 111 | const Instruction instr = par->info.code[index.row()]; |
| 118 | const OpCode opcode = instr.opcode; | 112 | const OpCode opcode = instr.opcode; |
| 119 | const OpCode::Info opcode_info = opcode.GetInfo(); | 113 | const OpCode::Info opcode_info = opcode.GetInfo(); |
| 120 | const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd ? | 114 | const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd |
| 121 | instr.mad.operand_desc_id.Value() : instr.common.operand_desc_id.Value(); | 115 | ? instr.mad.operand_desc_id.Value() |
| 116 | : instr.common.operand_desc_id.Value(); | ||
| 122 | const SwizzlePattern swizzle = par->info.swizzle_info[operand_desc_id].pattern; | 117 | const SwizzlePattern swizzle = par->info.swizzle_info[operand_desc_id].pattern; |
| 123 | 118 | ||
| 124 | // longest known instruction name: "setemit " | 119 | // longest known instruction name: "setemit " |
| @@ -136,15 +131,14 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 136 | break; | 131 | break; |
| 137 | 132 | ||
| 138 | case OpCode::Type::Arithmetic: | 133 | case OpCode::Type::Arithmetic: |
| 139 | case OpCode::Type::MultiplyAdd: | 134 | case OpCode::Type::MultiplyAdd: { |
| 140 | { | ||
| 141 | // Use custom code for special instructions | 135 | // Use custom code for special instructions |
| 142 | switch (opcode.EffectiveOpCode()) { | 136 | switch (opcode.EffectiveOpCode()) { |
| 143 | case OpCode::Id::CMP: | 137 | case OpCode::Id::CMP: { |
| 144 | { | ||
| 145 | AlignToColumn(kOpcodeColumnWidth); | 138 | AlignToColumn(kOpcodeColumnWidth); |
| 146 | 139 | ||
| 147 | // NOTE: CMP always writes both cc components, so we do not consider the dest mask here. | 140 | // NOTE: CMP always writes both cc components, so we do not consider the dest |
| 141 | // mask here. | ||
| 148 | output << " cc.xy"; | 142 | output << " cc.xy"; |
| 149 | AlignToColumn(kOutputColumnWidth); | 143 | AlignToColumn(kOutputColumnWidth); |
| 150 | 144 | ||
| @@ -152,22 +146,29 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 152 | SourceRegister src2 = instr.common.GetSrc2(false); | 146 | SourceRegister src2 = instr.common.GetSrc2(false); |
| 153 | 147 | ||
| 154 | output << ' '; | 148 | output << ' '; |
| 155 | print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), false, instr.common.AddressRegisterName()); | 149 | print_input(output, src1, swizzle.negate_src1, |
| 156 | output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) << ' '; | 150 | swizzle.SelectorToString(false).substr(0, 1), false, |
| 157 | print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(0,1), false); | 151 | instr.common.AddressRegisterName()); |
| 152 | output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) | ||
| 153 | << ' '; | ||
| 154 | print_input(output, src2, swizzle.negate_src2, | ||
| 155 | swizzle.SelectorToString(true).substr(0, 1), false); | ||
| 158 | 156 | ||
| 159 | output << ", "; | 157 | output << ", "; |
| 160 | 158 | ||
| 161 | print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), false, instr.common.AddressRegisterName()); | 159 | print_input(output, src1, swizzle.negate_src1, |
| 162 | output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) << ' '; | 160 | swizzle.SelectorToString(false).substr(1, 1), false, |
| 163 | print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(1,1), false); | 161 | instr.common.AddressRegisterName()); |
| 162 | output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) | ||
| 163 | << ' '; | ||
| 164 | print_input(output, src2, swizzle.negate_src2, | ||
| 165 | swizzle.SelectorToString(true).substr(1, 1), false); | ||
| 164 | 166 | ||
| 165 | break; | 167 | break; |
| 166 | } | 168 | } |
| 167 | 169 | ||
| 168 | case OpCode::Id::MAD: | 170 | case OpCode::Id::MAD: |
| 169 | case OpCode::Id::MADI: | 171 | case OpCode::Id::MADI: { |
| 170 | { | ||
| 171 | AlignToColumn(kOpcodeColumnWidth); | 172 | AlignToColumn(kOpcodeColumnWidth); |
| 172 | 173 | ||
| 173 | bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); | 174 | bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); |
| @@ -175,34 +176,42 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 175 | SourceRegister src2 = instr.mad.GetSrc2(src_is_inverted); | 176 | SourceRegister src2 = instr.mad.GetSrc2(src_is_inverted); |
| 176 | SourceRegister src3 = instr.mad.GetSrc3(src_is_inverted); | 177 | SourceRegister src3 = instr.mad.GetSrc3(src_is_inverted); |
| 177 | 178 | ||
| 178 | output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.' << swizzle.DestMaskToString(); | 179 | output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.' |
| 180 | << swizzle.DestMaskToString(); | ||
| 179 | AlignToColumn(kOutputColumnWidth); | 181 | AlignToColumn(kOutputColumnWidth); |
| 180 | print_input(output, src1, swizzle.negate_src1, SelectorToString(swizzle.src1_selector)); | 182 | print_input(output, src1, swizzle.negate_src1, |
| 183 | SelectorToString(swizzle.src1_selector)); | ||
| 181 | AlignToColumn(kInputOperandColumnWidth); | 184 | AlignToColumn(kInputOperandColumnWidth); |
| 182 | if (src_is_inverted) { | 185 | if (src_is_inverted) { |
| 183 | print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector)); | 186 | print_input(output, src2, swizzle.negate_src2, |
| 187 | SelectorToString(swizzle.src2_selector)); | ||
| 184 | } else { | 188 | } else { |
| 185 | print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector), true, instr.mad.AddressRegisterName()); | 189 | print_input(output, src2, swizzle.negate_src2, |
| 190 | SelectorToString(swizzle.src2_selector), true, | ||
| 191 | instr.mad.AddressRegisterName()); | ||
| 186 | } | 192 | } |
| 187 | AlignToColumn(kInputOperandColumnWidth); | 193 | AlignToColumn(kInputOperandColumnWidth); |
| 188 | if (src_is_inverted) { | 194 | if (src_is_inverted) { |
| 189 | print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector), true, instr.mad.AddressRegisterName()); | 195 | print_input(output, src3, swizzle.negate_src3, |
| 196 | SelectorToString(swizzle.src3_selector), true, | ||
| 197 | instr.mad.AddressRegisterName()); | ||
| 190 | } else { | 198 | } else { |
| 191 | print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector)); | 199 | print_input(output, src3, swizzle.negate_src3, |
| 200 | SelectorToString(swizzle.src3_selector)); | ||
| 192 | } | 201 | } |
| 193 | AlignToColumn(kInputOperandColumnWidth); | 202 | AlignToColumn(kInputOperandColumnWidth); |
| 194 | break; | 203 | break; |
| 195 | } | 204 | } |
| 196 | 205 | ||
| 197 | default: | 206 | default: { |
| 198 | { | ||
| 199 | AlignToColumn(kOpcodeColumnWidth); | 207 | AlignToColumn(kOpcodeColumnWidth); |
| 200 | 208 | ||
| 201 | bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); | 209 | bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); |
| 202 | 210 | ||
| 203 | if (opcode_info.subtype & OpCode::Info::Dest) { | 211 | if (opcode_info.subtype & OpCode::Info::Dest) { |
| 204 | // e.g. "r12.xy__" | 212 | // e.g. "r12.xy__" |
| 205 | output << std::setw(3) << std::right << instr.common.dest.Value().GetName() << '.' << swizzle.DestMaskToString(); | 213 | output << std::setw(3) << std::right << instr.common.dest.Value().GetName() |
| 214 | << '.' << swizzle.DestMaskToString(); | ||
| 206 | } else if (opcode_info.subtype == OpCode::Info::MOVA) { | 215 | } else if (opcode_info.subtype == OpCode::Info::MOVA) { |
| 207 | output << " a0." << swizzle.DestMaskToString(); | 216 | output << " a0." << swizzle.DestMaskToString(); |
| 208 | } | 217 | } |
| @@ -210,14 +219,18 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 210 | 219 | ||
| 211 | if (opcode_info.subtype & OpCode::Info::Src1) { | 220 | if (opcode_info.subtype & OpCode::Info::Src1) { |
| 212 | SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); | 221 | SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); |
| 213 | print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), true, instr.common.AddressRegisterName()); | 222 | print_input(output, src1, swizzle.negate_src1, |
| 223 | swizzle.SelectorToString(false), true, | ||
| 224 | instr.common.AddressRegisterName()); | ||
| 214 | AlignToColumn(kInputOperandColumnWidth); | 225 | AlignToColumn(kInputOperandColumnWidth); |
| 215 | } | 226 | } |
| 216 | 227 | ||
| 217 | // TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1 | 228 | // TODO: In some cases, the Address Register is used as an index for SRC2 |
| 229 | // instead of SRC1 | ||
| 218 | if (opcode_info.subtype & OpCode::Info::Src2) { | 230 | if (opcode_info.subtype & OpCode::Info::Src2) { |
| 219 | SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); | 231 | SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); |
| 220 | print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true)); | 232 | print_input(output, src2, swizzle.negate_src2, |
| 233 | swizzle.SelectorToString(true)); | ||
| 221 | AlignToColumn(kInputOperandColumnWidth); | 234 | AlignToColumn(kInputOperandColumnWidth); |
| 222 | } | 235 | } |
| 223 | break; | 236 | break; |
| @@ -228,8 +241,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 228 | } | 241 | } |
| 229 | 242 | ||
| 230 | case OpCode::Type::Conditional: | 243 | case OpCode::Type::Conditional: |
| 231 | case OpCode::Type::UniformFlowControl: | 244 | case OpCode::Type::UniformFlowControl: { |
| 232 | { | ||
| 233 | output << ' '; | 245 | output << ' '; |
| 234 | 246 | ||
| 235 | switch (opcode.EffectiveOpCode()) { | 247 | switch (opcode.EffectiveOpCode()) { |
| @@ -242,7 +254,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 242 | output << '('; | 254 | output << '('; |
| 243 | 255 | ||
| 244 | if (instr.flow_control.op != instr.flow_control.JustY) { | 256 | if (instr.flow_control.op != instr.flow_control.JustY) { |
| 245 | if (instr.flow_control.refx) output << '!'; | 257 | if (instr.flow_control.refx) |
| 258 | output << '!'; | ||
| 246 | output << "cc.x"; | 259 | output << "cc.x"; |
| 247 | } | 260 | } |
| 248 | 261 | ||
| @@ -253,7 +266,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 253 | } | 266 | } |
| 254 | 267 | ||
| 255 | if (instr.flow_control.op != instr.flow_control.JustX) { | 268 | if (instr.flow_control.op != instr.flow_control.JustX) { |
| 256 | if (instr.flow_control.refy) output << '!'; | 269 | if (instr.flow_control.refy) |
| 270 | output << '!'; | ||
| 257 | output << "cc.y"; | 271 | output << "cc.y"; |
| 258 | } | 272 | } |
| 259 | 273 | ||
| @@ -266,17 +280,23 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 266 | u32 target_addr_else = instr.flow_control.dest_offset; | 280 | u32 target_addr_else = instr.flow_control.dest_offset; |
| 267 | 281 | ||
| 268 | if (opcode_info.subtype & OpCode::Info::HasAlternative) { | 282 | if (opcode_info.subtype & OpCode::Info::HasAlternative) { |
| 269 | output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset); | 283 | output << "else jump to 0x" << std::setw(4) << std::right |
| 284 | << std::setfill('0') << std::hex | ||
| 285 | << (4 * instr.flow_control.dest_offset); | ||
| 270 | } else if (opcode_info.subtype & OpCode::Info::HasExplicitDest) { | 286 | } else if (opcode_info.subtype & OpCode::Info::HasExplicitDest) { |
| 271 | output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset); | 287 | output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') |
| 288 | << std::hex << (4 * instr.flow_control.dest_offset); | ||
| 272 | } else { | 289 | } else { |
| 273 | // TODO: Handle other cases | 290 | // TODO: Handle other cases |
| 274 | output << "(unknown destination)"; | 291 | output << "(unknown destination)"; |
| 275 | } | 292 | } |
| 276 | 293 | ||
| 277 | if (opcode_info.subtype & OpCode::Info::HasFinishPoint) { | 294 | if (opcode_info.subtype & OpCode::Info::HasFinishPoint) { |
| 278 | output << " (return on 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex | 295 | output << " (return on 0x" << std::setw(4) << std::right |
| 279 | << (4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions) << ')'; | 296 | << std::setfill('0') << std::hex |
| 297 | << (4 * instr.flow_control.dest_offset + | ||
| 298 | 4 * instr.flow_control.num_instructions) | ||
| 299 | << ')'; | ||
| 280 | } | 300 | } |
| 281 | 301 | ||
| 282 | break; | 302 | break; |
| @@ -300,8 +320,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 300 | case Qt::FontRole: | 320 | case Qt::FontRole: |
| 301 | return GetMonospaceFont(); | 321 | return GetMonospaceFont(); |
| 302 | 322 | ||
| 303 | case Qt::BackgroundRole: | 323 | case Qt::BackgroundRole: { |
| 304 | { | ||
| 305 | // Highlight current instruction | 324 | // Highlight current instruction |
| 306 | int current_record_index = par->cycle_index->value(); | 325 | int current_record_index = par->cycle_index->value(); |
| 307 | if (current_record_index < static_cast<int>(par->debug_data.records.size())) { | 326 | if (current_record_index < static_cast<int>(par->debug_data.records.size())) { |
| @@ -319,10 +338,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 319 | return QBrush(QColor(192, 192, 192)); | 338 | return QBrush(QColor(192, 192, 192)); |
| 320 | } | 339 | } |
| 321 | 340 | ||
| 322 | |||
| 323 | // TODO: Draw arrows for each "reachable" instruction to visualize control flow | 341 | // TODO: Draw arrows for each "reachable" instruction to visualize control flow |
| 324 | 342 | ||
| 325 | |||
| 326 | default: | 343 | default: |
| 327 | break; | 344 | break; |
| 328 | } | 345 | } |
| @@ -331,23 +348,24 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con | |||
| 331 | } | 348 | } |
| 332 | 349 | ||
| 333 | void GraphicsVertexShaderWidget::DumpShader() { | 350 | void GraphicsVertexShaderWidget::DumpShader() { |
| 334 | QString filename = QFileDialog::getSaveFileName(this, tr("Save Shader Dump"), "shader_dump.shbin", | 351 | QString filename = QFileDialog::getSaveFileName( |
| 335 | tr("Shader Binary (*.shbin)")); | 352 | this, tr("Save Shader Dump"), "shader_dump.shbin", tr("Shader Binary (*.shbin)")); |
| 336 | 353 | ||
| 337 | if (filename.isEmpty()) { | 354 | if (filename.isEmpty()) { |
| 338 | // If the user canceled the dialog, don't dump anything. | 355 | // If the user canceled the dialog, don't dump anything. |
| 339 | return; | 356 | return; |
| 340 | } | 357 | } |
| 341 | 358 | ||
| 342 | auto& setup = Pica::g_state.vs; | 359 | auto& setup = Pica::g_state.vs; |
| 343 | auto& config = Pica::g_state.regs.vs; | 360 | auto& config = Pica::g_state.regs.vs; |
| 344 | 361 | ||
| 345 | Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, Pica::g_state.regs.vs_output_attributes); | 362 | Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, |
| 363 | Pica::g_state.regs.vs_output_attributes); | ||
| 346 | } | 364 | } |
| 347 | 365 | ||
| 348 | GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::DebugContext > debug_context, | 366 | GraphicsVertexShaderWidget::GraphicsVertexShaderWidget( |
| 349 | QWidget* parent) | 367 | std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent) |
| 350 | : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) { | 368 | : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) { |
| 351 | setObjectName("PicaVertexShader"); | 369 | setObjectName("PicaVertexShader"); |
| 352 | 370 | ||
| 353 | // Clear input vertex data so that it contains valid float values in case a debug shader | 371 | // Clear input vertex data so that it contains valid float values in case a debug shader |
| @@ -365,7 +383,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De | |||
| 365 | input_data[i]->setValidator(new QDoubleValidator(input_data[i])); | 383 | input_data[i]->setValidator(new QDoubleValidator(input_data[i])); |
| 366 | } | 384 | } |
| 367 | 385 | ||
| 368 | breakpoint_warning = new QLabel(tr("(data only available at vertex shader invocation breakpoints)")); | 386 | breakpoint_warning = |
| 387 | new QLabel(tr("(data only available at vertex shader invocation breakpoints)")); | ||
| 369 | 388 | ||
| 370 | // TODO: Add some button for jumping to the shader entry point | 389 | // TODO: Add some button for jumping to the shader entry point |
| 371 | 390 | ||
| @@ -442,7 +461,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De | |||
| 442 | 461 | ||
| 443 | // Set a minimum height so that the size of this label doesn't cause the rest of the bottom | 462 | // Set a minimum height so that the size of this label doesn't cause the rest of the bottom |
| 444 | // part of the UI to keep jumping up and down when cycling through instructions. | 463 | // part of the UI to keep jumping up and down when cycling through instructions. |
| 445 | instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() * 6); | 464 | instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() * |
| 465 | 6); | ||
| 446 | instruction_description->setAlignment(Qt::AlignLeft | Qt::AlignTop); | 466 | instruction_description->setAlignment(Qt::AlignLeft | Qt::AlignTop); |
| 447 | main_layout->addWidget(instruction_description); | 467 | main_layout->addWidget(instruction_description); |
| 448 | 468 | ||
| @@ -471,7 +491,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d | |||
| 471 | memcpy(&input_vertex, vertex_data, sizeof(input_vertex)); | 491 | memcpy(&input_vertex, vertex_data, sizeof(input_vertex)); |
| 472 | for (unsigned attr = 0; attr < 16; ++attr) { | 492 | for (unsigned attr = 0; attr < 16; ++attr) { |
| 473 | for (unsigned comp = 0; comp < 4; ++comp) { | 493 | for (unsigned comp = 0; comp < 4; ++comp) { |
| 474 | input_data[4 * attr + comp]->setText(QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32())); | 494 | input_data[4 * attr + comp]->setText( |
| 495 | QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32())); | ||
| 475 | } | 496 | } |
| 476 | } | 497 | } |
| 477 | breakpoint_warning->hide(); | 498 | breakpoint_warning->hide(); |
| @@ -498,10 +519,11 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d | |||
| 498 | info.swizzle_info.push_back({pattern}); | 519 | info.swizzle_info.push_back({pattern}); |
| 499 | 520 | ||
| 500 | u32 entry_point = Pica::g_state.regs.vs.main_offset; | 521 | u32 entry_point = Pica::g_state.regs.vs.main_offset; |
| 501 | info.labels.insert({ entry_point, "main" }); | 522 | info.labels.insert({entry_point, "main"}); |
| 502 | 523 | ||
| 503 | // Generate debug information | 524 | // Generate debug information |
| 504 | debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config, shader_setup); | 525 | debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config, |
| 526 | shader_setup); | ||
| 505 | 527 | ||
| 506 | // Reload widget state | 528 | // Reload widget state |
| 507 | for (int attr = 0; attr < num_attributes; ++attr) { | 529 | for (int attr = 0; attr < num_attributes; ++attr) { |
| @@ -537,29 +559,60 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) { | |||
| 537 | 559 | ||
| 538 | auto& record = debug_data.records[index]; | 560 | auto& record = debug_data.records[index]; |
| 539 | if (record.mask & Pica::Shader::DebugDataRecord::SRC1) | 561 | if (record.mask & Pica::Shader::DebugDataRecord::SRC1) |
| 540 | 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()); | 562 | text += tr("SRC1: %1, %2, %3, %4\n") |
| 563 | .arg(record.src1.x.ToFloat32()) | ||
| 564 | .arg(record.src1.y.ToFloat32()) | ||
| 565 | .arg(record.src1.z.ToFloat32()) | ||
| 566 | .arg(record.src1.w.ToFloat32()); | ||
| 541 | if (record.mask & Pica::Shader::DebugDataRecord::SRC2) | 567 | if (record.mask & Pica::Shader::DebugDataRecord::SRC2) |
| 542 | 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()); | 568 | text += tr("SRC2: %1, %2, %3, %4\n") |
| 569 | .arg(record.src2.x.ToFloat32()) | ||
| 570 | .arg(record.src2.y.ToFloat32()) | ||
| 571 | .arg(record.src2.z.ToFloat32()) | ||
| 572 | .arg(record.src2.w.ToFloat32()); | ||
| 543 | if (record.mask & Pica::Shader::DebugDataRecord::SRC3) | 573 | if (record.mask & Pica::Shader::DebugDataRecord::SRC3) |
| 544 | 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()); | 574 | text += tr("SRC3: %1, %2, %3, %4\n") |
| 575 | .arg(record.src3.x.ToFloat32()) | ||
| 576 | .arg(record.src3.y.ToFloat32()) | ||
| 577 | .arg(record.src3.z.ToFloat32()) | ||
| 578 | .arg(record.src3.w.ToFloat32()); | ||
| 545 | if (record.mask & Pica::Shader::DebugDataRecord::DEST_IN) | 579 | if (record.mask & Pica::Shader::DebugDataRecord::DEST_IN) |
| 546 | 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()); | 580 | text += tr("DEST_IN: %1, %2, %3, %4\n") |
| 581 | .arg(record.dest_in.x.ToFloat32()) | ||
| 582 | .arg(record.dest_in.y.ToFloat32()) | ||
| 583 | .arg(record.dest_in.z.ToFloat32()) | ||
| 584 | .arg(record.dest_in.w.ToFloat32()); | ||
| 547 | if (record.mask & Pica::Shader::DebugDataRecord::DEST_OUT) | 585 | if (record.mask & Pica::Shader::DebugDataRecord::DEST_OUT) |
| 548 | 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()); | 586 | text += tr("DEST_OUT: %1, %2, %3, %4\n") |
| 587 | .arg(record.dest_out.x.ToFloat32()) | ||
| 588 | .arg(record.dest_out.y.ToFloat32()) | ||
| 589 | .arg(record.dest_out.z.ToFloat32()) | ||
| 590 | .arg(record.dest_out.w.ToFloat32()); | ||
| 549 | 591 | ||
| 550 | if (record.mask & Pica::Shader::DebugDataRecord::ADDR_REG_OUT) | 592 | if (record.mask & Pica::Shader::DebugDataRecord::ADDR_REG_OUT) |
| 551 | text += tr("Addres Registers: %1, %2\n").arg(record.address_registers[0]).arg(record.address_registers[1]); | 593 | text += tr("Addres Registers: %1, %2\n") |
| 594 | .arg(record.address_registers[0]) | ||
| 595 | .arg(record.address_registers[1]); | ||
| 552 | if (record.mask & Pica::Shader::DebugDataRecord::CMP_RESULT) | 596 | if (record.mask & Pica::Shader::DebugDataRecord::CMP_RESULT) |
| 553 | text += tr("Compare Result: %1, %2\n").arg(record.conditional_code[0] ? "true" : "false").arg(record.conditional_code[1] ? "true" : "false"); | 597 | text += tr("Compare Result: %1, %2\n") |
| 598 | .arg(record.conditional_code[0] ? "true" : "false") | ||
| 599 | .arg(record.conditional_code[1] ? "true" : "false"); | ||
| 554 | 600 | ||
| 555 | if (record.mask & Pica::Shader::DebugDataRecord::COND_BOOL_IN) | 601 | if (record.mask & Pica::Shader::DebugDataRecord::COND_BOOL_IN) |
| 556 | text += tr("Static Condition: %1\n").arg(record.cond_bool ? "true" : "false"); | 602 | text += tr("Static Condition: %1\n").arg(record.cond_bool ? "true" : "false"); |
| 557 | if (record.mask & Pica::Shader::DebugDataRecord::COND_CMP_IN) | 603 | if (record.mask & Pica::Shader::DebugDataRecord::COND_CMP_IN) |
| 558 | text += tr("Dynamic Conditions: %1, %2\n").arg(record.cond_cmp[0] ? "true" : "false").arg(record.cond_cmp[1] ? "true" : "false"); | 604 | text += tr("Dynamic Conditions: %1, %2\n") |
| 605 | .arg(record.cond_cmp[0] ? "true" : "false") | ||
| 606 | .arg(record.cond_cmp[1] ? "true" : "false"); | ||
| 559 | if (record.mask & Pica::Shader::DebugDataRecord::LOOP_INT_IN) | 607 | if (record.mask & Pica::Shader::DebugDataRecord::LOOP_INT_IN) |
| 560 | 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); | 608 | text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n") |
| 561 | 609 | .arg(record.loop_int.x) | |
| 562 | text += tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0')); | 610 | .arg(record.loop_int.y) |
| 611 | .arg(record.loop_int.z) | ||
| 612 | .arg(record.loop_int.w); | ||
| 613 | |||
| 614 | text += | ||
| 615 | tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0')); | ||
| 563 | if (record.mask & Pica::Shader::DebugDataRecord::NEXT_INSTR) { | 616 | if (record.mask & Pica::Shader::DebugDataRecord::NEXT_INSTR) { |
| 564 | text += tr(" -> 0x%2").arg(4 * record.next_instruction, 4, 16, QLatin1Char('0')); | 617 | text += tr(" -> 0x%2").arg(4 * record.next_instruction, 4, 16, QLatin1Char('0')); |
| 565 | } else { | 618 | } else { |
| @@ -570,6 +623,7 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) { | |||
| 570 | 623 | ||
| 571 | // Emit model update notification and scroll to current instruction | 624 | // Emit model update notification and scroll to current instruction |
| 572 | QModelIndex instr_index = model->index(record.instruction_offset, 0); | 625 | QModelIndex instr_index = model->index(record.instruction_offset, 0); |
| 573 | emit model->dataChanged(instr_index, model->index(record.instruction_offset, model->columnCount())); | 626 | emit model->dataChanged(instr_index, |
| 627 | model->index(record.instruction_offset, model->columnCount())); | ||
| 574 | binary_list->scrollTo(instr_index, QAbstractItemView::EnsureVisible); | 628 | binary_list->scrollTo(instr_index, QAbstractItemView::EnsureVisible); |
| 575 | } | 629 | } |
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.h b/src/citra_qt/debugger/graphics_vertex_shader.h index 7f06f496a..ec42f24bb 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.h +++ b/src/citra_qt/debugger/graphics_vertex_shader.h | |||
| @@ -5,11 +5,9 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <QAbstractTableModel> | 7 | #include <QAbstractTableModel> |
| 8 | 8 | #include <QTreeView> | |
| 9 | #include "citra_qt/debugger/graphics_breakpoint_observer.h" | 9 | #include "citra_qt/debugger/graphics_breakpoint_observer.h" |
| 10 | |||
| 11 | #include "nihstro/parser_shbin.h" | 10 | #include "nihstro/parser_shbin.h" |
| 12 | |||
| 13 | #include "video_core/shader/shader.h" | 11 | #include "video_core/shader/shader.h" |
| 14 | 12 | ||
| 15 | class QLabel; | 13 | class QLabel; |
| @@ -26,7 +24,8 @@ public: | |||
| 26 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; | 24 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; |
| 27 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; | 25 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
| 28 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; | 26 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; |
| 29 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | 27 | QVariant headerData(int section, Qt::Orientation orientation, |
| 28 | int role = Qt::DisplayRole) const override; | ||
| 30 | 29 | ||
| 31 | private: | 30 | private: |
| 32 | GraphicsVertexShaderWidget* par; | 31 | GraphicsVertexShaderWidget* par; |
| @@ -56,7 +55,9 @@ private slots: | |||
| 56 | /** | 55 | /** |
| 57 | * Reload widget based on the current PICA200 state | 56 | * Reload widget based on the current PICA200 state |
| 58 | * @param replace_vertex_data If true, invalidate all current vertex data | 57 | * @param replace_vertex_data If true, invalidate all current vertex data |
| 59 | * @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. | 58 | * @param vertex_data New vertex data to use, as passed to OnBreakPointHit. May be nullptr to |
| 59 | * specify that no valid vertex data can be retrieved currently. Only used if | ||
| 60 | * replace_vertex_data is true. | ||
| 60 | */ | 61 | */ |
| 61 | void Reload(bool replace_vertex_data = false, void* vertex_data = nullptr); | 62 | void Reload(bool replace_vertex_data = false, void* vertex_data = nullptr); |
| 62 | 63 | ||
| @@ -66,9 +67,12 @@ private: | |||
| 66 | GraphicsVertexShaderModel* model; | 67 | GraphicsVertexShaderModel* model; |
| 67 | 68 | ||
| 68 | /// TODO: Move these into a single struct | 69 | /// TODO: Move these into a single struct |
| 69 | std::array<QLineEdit*, 4*16> input_data; // A text box for each of the 4 components of up to 16 vertex attributes | 70 | std::array<QLineEdit*, 4 * 16> |
| 70 | std::array<QWidget*, 16> input_data_container; // QWidget containing the QLayout containing each vertex attribute | 71 | input_data; // A text box for each of the 4 components of up to 16 vertex attributes |
| 71 | std::array<QLabel*, 16> input_data_mapping; // A QLabel denoting the shader input attribute which the vertex attribute maps to | 72 | std::array<QWidget*, 16> |
| 73 | input_data_container; // QWidget containing the QLayout containing each vertex attribute | ||
| 74 | std::array<QLabel*, 16> input_data_mapping; // A QLabel denoting the shader input attribute | ||
| 75 | // which the vertex attribute maps to | ||
| 72 | 76 | ||
| 73 | // Text to be shown when input vertex data is not retrievable | 77 | // Text to be shown when input vertex data is not retrievable |
| 74 | QLabel* breakpoint_warning; | 78 | QLabel* breakpoint_warning; |
diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp index 17898f54b..cee10403d 100644 --- a/src/citra_qt/debugger/profiler.cpp +++ b/src/citra_qt/debugger/profiler.cpp | |||
| @@ -5,10 +5,8 @@ | |||
| 5 | #include <QMouseEvent> | 5 | #include <QMouseEvent> |
| 6 | #include <QPainter> | 6 | #include <QPainter> |
| 7 | #include <QString> | 7 | #include <QString> |
| 8 | |||
| 9 | #include "citra_qt/debugger/profiler.h" | 8 | #include "citra_qt/debugger/profiler.h" |
| 10 | #include "citra_qt/util/util.h" | 9 | #include "citra_qt/util/util.h" |
| 11 | |||
| 12 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 13 | #include "common/microprofile.h" | 11 | #include "common/microprofile.h" |
| 14 | #include "common/profiler_reporting.h" | 12 | #include "common/profiler_reporting.h" |
| @@ -22,57 +20,58 @@ | |||
| 22 | 20 | ||
| 23 | using namespace Common::Profiling; | 21 | using namespace Common::Profiling; |
| 24 | 22 | ||
| 25 | static QVariant GetDataForColumn(int col, const AggregatedDuration& duration) | 23 | static QVariant GetDataForColumn(int col, const AggregatedDuration& duration) { |
| 26 | { | ||
| 27 | static auto duration_to_float = [](Duration dur) -> float { | 24 | static auto duration_to_float = [](Duration dur) -> float { |
| 28 | using FloatMs = std::chrono::duration<float, std::chrono::milliseconds::period>; | 25 | using FloatMs = std::chrono::duration<float, std::chrono::milliseconds::period>; |
| 29 | return std::chrono::duration_cast<FloatMs>(dur).count(); | 26 | return std::chrono::duration_cast<FloatMs>(dur).count(); |
| 30 | }; | 27 | }; |
| 31 | 28 | ||
| 32 | switch (col) { | 29 | switch (col) { |
| 33 | case 1: return duration_to_float(duration.avg); | 30 | case 1: |
| 34 | case 2: return duration_to_float(duration.min); | 31 | return duration_to_float(duration.avg); |
| 35 | case 3: return duration_to_float(duration.max); | 32 | case 2: |
| 36 | default: return QVariant(); | 33 | return duration_to_float(duration.min); |
| 34 | case 3: | ||
| 35 | return duration_to_float(duration.max); | ||
| 36 | default: | ||
| 37 | return QVariant(); | ||
| 37 | } | 38 | } |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent) | 41 | ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent) { |
| 41 | { | ||
| 42 | updateProfilingInfo(); | 42 | updateProfilingInfo(); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const | 45 | QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const { |
| 46 | { | ||
| 47 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { | 46 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { |
| 48 | switch (section) { | 47 | switch (section) { |
| 49 | case 0: return tr("Category"); | 48 | case 0: |
| 50 | case 1: return tr("Avg"); | 49 | return tr("Category"); |
| 51 | case 2: return tr("Min"); | 50 | case 1: |
| 52 | case 3: return tr("Max"); | 51 | return tr("Avg"); |
| 52 | case 2: | ||
| 53 | return tr("Min"); | ||
| 54 | case 3: | ||
| 55 | return tr("Max"); | ||
| 53 | } | 56 | } |
| 54 | } | 57 | } |
| 55 | 58 | ||
| 56 | return QVariant(); | 59 | return QVariant(); |
| 57 | } | 60 | } |
| 58 | 61 | ||
| 59 | QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const | 62 | QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const { |
| 60 | { | ||
| 61 | return createIndex(row, column); | 63 | return createIndex(row, column); |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 64 | QModelIndex ProfilerModel::parent(const QModelIndex& child) const | 66 | QModelIndex ProfilerModel::parent(const QModelIndex& child) const { |
| 65 | { | ||
| 66 | return QModelIndex(); | 67 | return QModelIndex(); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | int ProfilerModel::columnCount(const QModelIndex& parent) const | 70 | int ProfilerModel::columnCount(const QModelIndex& parent) const { |
| 70 | { | ||
| 71 | return 4; | 71 | return 4; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | int ProfilerModel::rowCount(const QModelIndex& parent) const | 74 | int ProfilerModel::rowCount(const QModelIndex& parent) const { |
| 75 | { | ||
| 76 | if (parent.isValid()) { | 75 | if (parent.isValid()) { |
| 77 | return 0; | 76 | return 0; |
| 78 | } else { | 77 | } else { |
| @@ -80,8 +79,7 @@ int ProfilerModel::rowCount(const QModelIndex& parent) const | |||
| 80 | } | 79 | } |
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | QVariant ProfilerModel::data(const QModelIndex& index, int role) const | 82 | QVariant ProfilerModel::data(const QModelIndex& index, int role) const { |
| 84 | { | ||
| 85 | if (role == Qt::DisplayRole) { | 83 | if (role == Qt::DisplayRole) { |
| 86 | if (index.row() == 0) { | 84 | if (index.row() == 0) { |
| 87 | if (index.column() == 0) { | 85 | if (index.column() == 0) { |
| @@ -101,14 +99,12 @@ QVariant ProfilerModel::data(const QModelIndex& index, int role) const | |||
| 101 | return QVariant(); | 99 | return QVariant(); |
| 102 | } | 100 | } |
| 103 | 101 | ||
| 104 | void ProfilerModel::updateProfilingInfo() | 102 | void ProfilerModel::updateProfilingInfo() { |
| 105 | { | ||
| 106 | results = GetTimingResultsAggregator()->GetAggregatedResults(); | 103 | results = GetTimingResultsAggregator()->GetAggregatedResults(); |
| 107 | emit dataChanged(createIndex(0, 1), createIndex(rowCount() - 1, 3)); | 104 | emit dataChanged(createIndex(0, 1), createIndex(rowCount() - 1, 3)); |
| 108 | } | 105 | } |
| 109 | 106 | ||
| 110 | ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) | 107 | ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) { |
| 111 | { | ||
| 112 | ui.setupUi(this); | 108 | ui.setupUi(this); |
| 113 | 109 | ||
| 114 | model = new ProfilerModel(this); | 110 | model = new ProfilerModel(this); |
| @@ -118,8 +114,7 @@ ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent) | |||
| 118 | connect(&update_timer, SIGNAL(timeout()), model, SLOT(updateProfilingInfo())); | 114 | connect(&update_timer, SIGNAL(timeout()), model, SLOT(updateProfilingInfo())); |
| 119 | } | 115 | } |
| 120 | 116 | ||
| 121 | void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) | 117 | void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) { |
| 122 | { | ||
| 123 | if (enable) { | 118 | if (enable) { |
| 124 | update_timer.start(100); | 119 | update_timer.start(100); |
| 125 | model->updateProfilingInfo(); | 120 | model->updateProfilingInfo(); |
| @@ -157,9 +152,7 @@ private: | |||
| 157 | 152 | ||
| 158 | #endif | 153 | #endif |
| 159 | 154 | ||
| 160 | MicroProfileDialog::MicroProfileDialog(QWidget* parent) | 155 | MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { |
| 161 | : QWidget(parent, Qt::Dialog) | ||
| 162 | { | ||
| 163 | setObjectName("MicroProfile"); | 156 | setObjectName("MicroProfile"); |
| 164 | setWindowTitle(tr("MicroProfile")); | 157 | setWindowTitle(tr("MicroProfile")); |
| 165 | resize(1000, 600); | 158 | resize(1000, 600); |
| @@ -175,7 +168,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent) | |||
| 175 | layout->addWidget(widget); | 168 | layout->addWidget(widget); |
| 176 | setLayout(layout); | 169 | setLayout(layout); |
| 177 | 170 | ||
| 178 | // Configure focus so that widget is focusable and the dialog automatically forwards focus to it. | 171 | // Configure focus so that widget is focusable and the dialog automatically forwards focus to |
| 172 | // it. | ||
| 179 | setFocusProxy(widget); | 173 | setFocusProxy(widget); |
| 180 | widget->setFocusPolicy(Qt::StrongFocus); | 174 | widget->setFocusPolicy(Qt::StrongFocus); |
| 181 | widget->setFocus(); | 175 | widget->setFocus(); |
| @@ -207,7 +201,6 @@ void MicroProfileDialog::hideEvent(QHideEvent* ev) { | |||
| 207 | QWidget::hideEvent(ev); | 201 | QWidget::hideEvent(ev); |
| 208 | } | 202 | } |
| 209 | 203 | ||
| 210 | |||
| 211 | #if MICROPROFILE_ENABLED | 204 | #if MICROPROFILE_ENABLED |
| 212 | 205 | ||
| 213 | /// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the | 206 | /// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the |
| @@ -308,7 +301,8 @@ void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 tex | |||
| 308 | } | 301 | } |
| 309 | } | 302 | } |
| 310 | 303 | ||
| 311 | void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, MicroProfileBoxType type) { | 304 | void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, |
| 305 | MicroProfileBoxType type) { | ||
| 312 | QColor color = QColor::fromRgba(hex_color); | 306 | QColor color = QColor::fromRgba(hex_color); |
| 313 | QBrush brush = color; | 307 | QBrush brush = color; |
| 314 | if (type == MicroProfileBoxTypeBar) { | 308 | if (type == MicroProfileBoxTypeBar) { |
| @@ -326,7 +320,7 @@ void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color) | |||
| 326 | static std::vector<QPointF> point_buf; | 320 | static std::vector<QPointF> point_buf; |
| 327 | 321 | ||
| 328 | for (u32 i = 0; i < vertices_length; ++i) { | 322 | for (u32 i = 0; i < vertices_length; ++i) { |
| 329 | point_buf.emplace_back(vertices[i*2 + 0], vertices[i*2 + 1]); | 323 | point_buf.emplace_back(vertices[i * 2 + 0], vertices[i * 2 + 1]); |
| 330 | } | 324 | } |
| 331 | 325 | ||
| 332 | // hex_color does not include an alpha, so it must be assumed to be 255 | 326 | // hex_color does not include an alpha, so it must be assumed to be 255 |
diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h index 3b38ed8ec..d8c6487aa 100644 --- a/src/citra_qt/debugger/profiler.h +++ b/src/citra_qt/debugger/profiler.h | |||
| @@ -7,21 +7,20 @@ | |||
| 7 | #include <QAbstractItemModel> | 7 | #include <QAbstractItemModel> |
| 8 | #include <QDockWidget> | 8 | #include <QDockWidget> |
| 9 | #include <QTimer> | 9 | #include <QTimer> |
| 10 | |||
| 11 | #include "ui_profiler.h" | ||
| 12 | |||
| 13 | #include "common/microprofile.h" | 10 | #include "common/microprofile.h" |
| 14 | #include "common/profiler_reporting.h" | 11 | #include "common/profiler_reporting.h" |
| 12 | #include "ui_profiler.h" | ||
| 15 | 13 | ||
| 16 | class ProfilerModel : public QAbstractItemModel | 14 | class ProfilerModel : public QAbstractItemModel { |
| 17 | { | ||
| 18 | Q_OBJECT | 15 | Q_OBJECT |
| 19 | 16 | ||
| 20 | public: | 17 | public: |
| 21 | ProfilerModel(QObject* parent); | 18 | ProfilerModel(QObject* parent); |
| 22 | 19 | ||
| 23 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; | 20 | QVariant headerData(int section, Qt::Orientation orientation, |
| 24 | QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; | 21 | int role = Qt::DisplayRole) const override; |
| 22 | QModelIndex index(int row, int column, | ||
| 23 | const QModelIndex& parent = QModelIndex()) const override; | ||
| 25 | QModelIndex parent(const QModelIndex& child) const override; | 24 | QModelIndex parent(const QModelIndex& child) const override; |
| 26 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; | 25 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; |
| 27 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; | 26 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; |
| @@ -34,8 +33,7 @@ private: | |||
| 34 | Common::Profiling::AggregatedFrameResult results; | 33 | Common::Profiling::AggregatedFrameResult results; |
| 35 | }; | 34 | }; |
| 36 | 35 | ||
| 37 | class ProfilerWidget : public QDockWidget | 36 | class ProfilerWidget : public QDockWidget { |
| 38 | { | ||
| 39 | Q_OBJECT | 37 | Q_OBJECT |
| 40 | 38 | ||
| 41 | public: | 39 | public: |
| @@ -51,7 +49,6 @@ private: | |||
| 51 | QTimer update_timer; | 49 | QTimer update_timer; |
| 52 | }; | 50 | }; |
| 53 | 51 | ||
| 54 | |||
| 55 | class MicroProfileDialog : public QWidget { | 52 | class MicroProfileDialog : public QWidget { |
| 56 | Q_OBJECT | 53 | Q_OBJECT |
| 57 | 54 | ||
diff --git a/src/citra_qt/debugger/ramview.cpp b/src/citra_qt/debugger/ramview.cpp index 02347e83a..10a09dda8 100644 --- a/src/citra_qt/debugger/ramview.cpp +++ b/src/citra_qt/debugger/ramview.cpp | |||
| @@ -4,12 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include "citra_qt/debugger/ramview.h" | 5 | #include "citra_qt/debugger/ramview.h" |
| 6 | 6 | ||
| 7 | GRamView::GRamView(QWidget* parent) : QHexEdit(parent) | 7 | GRamView::GRamView(QWidget* parent) : QHexEdit(parent) {} |
| 8 | { | ||
| 9 | } | ||
| 10 | 8 | ||
| 11 | void GRamView::OnCPUStepped() | 9 | void GRamView::OnCPUStepped() { |
| 12 | { | ||
| 13 | // TODO: QHexEdit doesn't show vertical scroll bars for > 10MB data streams... | 10 | // TODO: QHexEdit doesn't show vertical scroll bars for > 10MB data streams... |
| 14 | //setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8)); | 11 | // setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8)); |
| 15 | } | 12 | } |
diff --git a/src/citra_qt/debugger/ramview.h b/src/citra_qt/debugger/ramview.h index 0ef74586b..8043c59e8 100644 --- a/src/citra_qt/debugger/ramview.h +++ b/src/citra_qt/debugger/ramview.h | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "qhexedit.h" | 5 | #include "qhexedit.h" |
| 6 | 6 | ||
| 7 | class GRamView : public QHexEdit | 7 | class GRamView : public QHexEdit { |
| 8 | { | ||
| 9 | Q_OBJECT | 8 | Q_OBJECT |
| 10 | 9 | ||
| 11 | public: | 10 | public: |
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp index 1bd0bfebc..0b644432f 100644 --- a/src/citra_qt/debugger/registers.cpp +++ b/src/citra_qt/debugger/registers.cpp | |||
| @@ -3,12 +3,10 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <QTreeWidgetItem> | 5 | #include <QTreeWidgetItem> |
| 6 | |||
| 7 | #include "citra_qt/debugger/registers.h" | 6 | #include "citra_qt/debugger/registers.h" |
| 8 | #include "citra_qt/util/util.h" | 7 | #include "citra_qt/util/util.h" |
| 9 | |||
| 10 | #include "core/core.h" | ||
| 11 | #include "core/arm/arm_interface.h" | 8 | #include "core/arm/arm_interface.h" |
| 9 | #include "core/core.h" | ||
| 12 | 10 | ||
| 13 | RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { | 11 | RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { |
| 14 | cpu_regs_ui.setupUi(this); | 12 | cpu_regs_ui.setupUi(this); |
| @@ -16,7 +14,8 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { | |||
| 16 | tree = cpu_regs_ui.treeWidget; | 14 | tree = cpu_regs_ui.treeWidget; |
| 17 | tree->addTopLevelItem(core_registers = new QTreeWidgetItem(QStringList(tr("Registers")))); | 15 | tree->addTopLevelItem(core_registers = new QTreeWidgetItem(QStringList(tr("Registers")))); |
| 18 | tree->addTopLevelItem(vfp_registers = new QTreeWidgetItem(QStringList(tr("VFP Registers")))); | 16 | tree->addTopLevelItem(vfp_registers = new QTreeWidgetItem(QStringList(tr("VFP Registers")))); |
| 19 | tree->addTopLevelItem(vfp_system_registers = new QTreeWidgetItem(QStringList(tr("VFP System Registers")))); | 17 | tree->addTopLevelItem(vfp_system_registers = |
| 18 | new QTreeWidgetItem(QStringList(tr("VFP System Registers")))); | ||
| 20 | tree->addTopLevelItem(cpsr = new QTreeWidgetItem(QStringList("CPSR"))); | 19 | tree->addTopLevelItem(cpsr = new QTreeWidgetItem(QStringList("CPSR"))); |
| 21 | 20 | ||
| 22 | for (int i = 0; i < 16; ++i) { | 21 | for (int i = 0; i < 16; ++i) { |
| @@ -63,17 +62,18 @@ void RegistersWidget::OnDebugModeEntered() { | |||
| 63 | return; | 62 | return; |
| 64 | 63 | ||
| 65 | for (int i = 0; i < core_registers->childCount(); ++i) | 64 | for (int i = 0; i < core_registers->childCount(); ++i) |
| 66 | core_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); | 65 | core_registers->child(i)->setText( |
| 66 | 1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); | ||
| 67 | 67 | ||
| 68 | for (int i = 0; i < vfp_registers->childCount(); ++i) | 68 | for (int i = 0; i < vfp_registers->childCount(); ++i) |
| 69 | vfp_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); | 69 | vfp_registers->child(i)->setText( |
| 70 | 1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); | ||
| 70 | 71 | ||
| 71 | UpdateCPSRValues(); | 72 | UpdateCPSRValues(); |
| 72 | UpdateVFPSystemRegisterValues(); | 73 | UpdateVFPSystemRegisterValues(); |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | void RegistersWidget::OnDebugModeLeft() { | 76 | void RegistersWidget::OnDebugModeLeft() {} |
| 76 | } | ||
| 77 | 77 | ||
| 78 | void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) { | 78 | void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) { |
| 79 | setEnabled(true); | 79 | setEnabled(true); |
| @@ -130,21 +130,24 @@ void RegistersWidget::UpdateCPSRValues() { | |||
| 130 | const u32 cpsr_val = Core::g_app_core->GetCPSR(); | 130 | const u32 cpsr_val = Core::g_app_core->GetCPSR(); |
| 131 | 131 | ||
| 132 | cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); | 132 | cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); |
| 133 | cpsr->child(0)->setText(1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode | 133 | cpsr->child(0)->setText( |
| 134 | cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1)); // T - State | 134 | 1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode |
| 135 | cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1)); // F - FIQ disable | 135 | cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1)); // T - State |
| 136 | cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1)); // I - IRQ disable | 136 | cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1)); // F - FIQ disable |
| 137 | cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1)); // A - Imprecise abort | 137 | cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1)); // I - IRQ disable |
| 138 | cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1)); // E - Data endianess | 138 | cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1)); // A - Imprecise abort |
| 139 | cpsr->child(6)->setText(1, QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM) | 139 | cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1)); // E - Data endianess |
| 140 | cpsr->child(7)->setText(1, QString::number((cpsr_val >> 16) & 0xF)); // GE - Greater-than-or-Equal | 140 | cpsr->child(6)->setText(1, |
| 141 | cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF)); // DNM - Do not modify | 141 | QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM) |
| 142 | cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1)); // J - Jazelle | 142 | cpsr->child(7)->setText(1, |
| 143 | cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1)); // Q - Saturation | 143 | QString::number((cpsr_val >> 16) & 0xF)); // GE - Greater-than-or-Equal |
| 144 | cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1)); // V - Overflow | 144 | cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF)); // DNM - Do not modify |
| 145 | cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1)); // C - Carry/Borrow/Extend | 145 | cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1)); // J - Jazelle |
| 146 | cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1)); // Z - Zero | 146 | cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1)); // Q - Saturation |
| 147 | cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1)); // N - Negative/Less than | 147 | cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1)); // V - Overflow |
| 148 | cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1)); // C - Carry/Borrow/Extend | ||
| 149 | cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1)); // Z - Zero | ||
| 150 | cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1)); // N - Negative/Less than | ||
| 148 | } | 151 | } |
| 149 | 152 | ||
| 150 | void RegistersWidget::CreateVFPSystemRegisterChildren() { | 153 | void RegistersWidget::CreateVFPSystemRegisterChildren() { |
| @@ -188,9 +191,9 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() { | |||
| 188 | } | 191 | } |
| 189 | 192 | ||
| 190 | void RegistersWidget::UpdateVFPSystemRegisterValues() { | 193 | void RegistersWidget::UpdateVFPSystemRegisterValues() { |
| 191 | const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); | 194 | const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); |
| 192 | const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); | 195 | const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); |
| 193 | const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); | 196 | const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); |
| 194 | const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); | 197 | const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); |
| 195 | 198 | ||
| 196 | QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); | 199 | QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); |
| @@ -228,6 +231,8 @@ void RegistersWidget::UpdateVFPSystemRegisterValues() { | |||
| 228 | fpexc->child(6)->setText(1, QString::number((fpexc_val >> 30) & 1)); | 231 | fpexc->child(6)->setText(1, QString::number((fpexc_val >> 30) & 1)); |
| 229 | fpexc->child(7)->setText(1, QString::number((fpexc_val >> 31) & 1)); | 232 | fpexc->child(7)->setText(1, QString::number((fpexc_val >> 31) & 1)); |
| 230 | 233 | ||
| 231 | vfp_system_registers->child(2)->setText(1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0'))); | 234 | vfp_system_registers->child(2)->setText( |
| 232 | vfp_system_registers->child(3)->setText(1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0'))); | 235 | 1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0'))); |
| 236 | vfp_system_registers->child(3)->setText( | ||
| 237 | 1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0'))); | ||
| 233 | } | 238 | } |
diff --git a/src/citra_qt/debugger/registers.h b/src/citra_qt/debugger/registers.h index cf27acc1c..54c9a8155 100644 --- a/src/citra_qt/debugger/registers.h +++ b/src/citra_qt/debugger/registers.h | |||
| @@ -2,16 +2,14 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "ui_registers.h" | ||
| 6 | |||
| 7 | #include <QDockWidget> | 5 | #include <QDockWidget> |
| 6 | #include "ui_registers.h" | ||
| 8 | 7 | ||
| 9 | class QTreeWidget; | 8 | class QTreeWidget; |
| 10 | class QTreeWidgetItem; | 9 | class QTreeWidgetItem; |
| 11 | class EmuThread; | 10 | class EmuThread; |
| 12 | 11 | ||
| 13 | class RegistersWidget : public QDockWidget | 12 | class RegistersWidget : public QDockWidget { |
| 14 | { | ||
| 15 | Q_OBJECT | 13 | Q_OBJECT |
| 16 | 14 | ||
| 17 | public: | 15 | public: |