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