diff options
Diffstat (limited to 'src/citra_qt/debugger')
-rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 11 | ||||
-rw-r--r-- | src/citra_qt/debugger/callstack.h | 3 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.cpp | 9 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.h | 9 | ||||
-rw-r--r-- | src/citra_qt/debugger/disassembler.ui | 117 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_breakpoint_observer.cpp | 32 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_breakpoint_observer.h | 33 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_breakpoints.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_cmdlists.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_framebuffer.cpp | 31 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_framebuffer.h | 24 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_vertex_shader.cpp | 298 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_vertex_shader.h | 51 | ||||
-rw-r--r-- | src/citra_qt/debugger/ramview.cpp | 2 |
14 files changed, 501 insertions, 123 deletions
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 025a5896b..9bb22ca2e 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -33,6 +33,8 @@ void CallstackWidget::OnDebugModeEntered() u32 sp = app_core->GetReg(13); //stack pointer u32 ret_addr, call_addr, func_addr; + Clear(); + int counter = 0; for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { @@ -76,3 +78,12 @@ void CallstackWidget::OnDebugModeLeft() { } + +void CallstackWidget::Clear() +{ + for (int row = 0; row < callstack_model->rowCount(); row++) { + for (int column = 0; column < callstack_model->columnCount(); column++) { + callstack_model->setItem(row, column, new QStandardItem()); + } + } +} diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h index fb390f5c3..1a9b6dc81 100644 --- a/src/citra_qt/debugger/callstack.h +++ b/src/citra_qt/debugger/callstack.h @@ -21,4 +21,7 @@ public slots: private: Ui::CallStack ui; QStandardItemModel* callstack_model; + + /// Clears the callstack widget while keeping the column widths the same + void Clear(); }; diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index c61ace925..54d21dc90 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -17,16 +17,9 @@ #include "core/arm/skyeye_common/armdefs.h" #include "core/arm/disassembler/arm_disasm.h" -DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) { -} - -QModelIndex DisassemblerModel::index(int row, int column, const QModelIndex& parent) const { - return createIndex(row, column); -} +DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) { -QModelIndex DisassemblerModel::parent(const QModelIndex& child) const { - return QModelIndex(); } int DisassemblerModel::columnCount(const QModelIndex& parent) const { diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h index 0deccc240..5e19d7c51 100644 --- a/src/citra_qt/debugger/disassembler.h +++ b/src/citra_qt/debugger/disassembler.h @@ -2,8 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <QAbstractItemModel> +#pragma once + +#include <QAbstractListModel> #include <QDockWidget> + #include "ui_disassembler.h" #include "common/common.h" @@ -12,15 +15,13 @@ class QAction; class EmuThread; -class DisassemblerModel : public QAbstractItemModel +class DisassemblerModel : public QAbstractListModel { Q_OBJECT public: DisassemblerModel(QObject* parent); - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex& child) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; diff --git a/src/citra_qt/debugger/disassembler.ui b/src/citra_qt/debugger/disassembler.ui index bd0752aa4..5ca6dc5d2 100644 --- a/src/citra_qt/debugger/disassembler.ui +++ b/src/citra_qt/debugger/disassembler.ui @@ -13,63 +13,66 @@ <property name="windowTitle"> <string>Disassembly</string> </property> - <widget class="QWidget" name="dockWidgetContents"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="button_step"> - <property name="text"> - <string>Step</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_pause"> - <property name="text"> - <string>Pause</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_continue"> - <property name="text"> - <string>Continue</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton"> - <property name="text"> - <string>Step Into</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_breakpoint"> - <property name="text"> - <string>Set Breakpoint</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QTreeView" name="treeView"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="indentation"> - <number>20</number> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <attribute name="headerVisible"> - <bool>false</bool> - </attribute> - </widget> - </item> + <widget class="QWidget" name="dockWidgetContents"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="button_step"> + <property name="text"> + <string>Step</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_pause"> + <property name="text"> + <string>Pause</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_continue"> + <property name="text"> + <string>Continue</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="text"> + <string>Step Into</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_breakpoint"> + <property name="text"> + <string>Set Breakpoint</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QTreeView" name="treeView"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="indentation"> + <number>20</number> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="uniformRowHeights"> + <bool>true</bool> + </property> + <attribute name="headerVisible"> + <bool>false</bool> + </attribute> + </widget> + </item> </layout> </widget> </widget> diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.cpp b/src/citra_qt/debugger/graphics_breakpoint_observer.cpp new file mode 100644 index 000000000..10ac1ebad --- /dev/null +++ b/src/citra_qt/debugger/graphics_breakpoint_observer.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <QMetaType> + +#include "graphics_breakpoint_observer.h" + +BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, + const QString& title, QWidget* parent) + : QDockWidget(title, parent), BreakPointObserver(debug_context) +{ + qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); + + connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); + + // NOTE: This signal is emitted from a non-GUI thread, but connect() takes + // care of delaying its handling to the GUI thread. + connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), + this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), + Qt::BlockingQueuedConnection); +} + +void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) +{ + emit BreakPointHit(event, data); +} + +void BreakPointObserverDock::OnPicaResume() +{ + emit Resumed(); +} diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.h b/src/citra_qt/debugger/graphics_breakpoint_observer.h new file mode 100644 index 000000000..f0d3361f8 --- /dev/null +++ b/src/citra_qt/debugger/graphics_breakpoint_observer.h @@ -0,0 +1,33 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <QDockWidget> + +#include "video_core/debug_utils/debug_utils.h" + +/** + * Utility class which forwards calls to OnPicaBreakPointHit and OnPicaResume to public slots. + * This is because the Pica breakpoint callbacks are called from a non-GUI thread, while + * the widget usually wants to perform reactions in the GUI thread. + */ +class BreakPointObserverDock : public QDockWidget, private Pica::DebugContext::BreakPointObserver { + Q_OBJECT + +public: + BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, const QString& title, + QWidget* parent = nullptr); + + void OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) override; + void OnPicaResume() override; + +private slots: + virtual void OnBreakPointHit(Pica::DebugContext::Event event, void* data) = 0; + virtual void OnResumed() = 0; + +signals: + void Resumed(); + void BreakPointHit(Pica::DebugContext::Event event, void* data); +}; diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 262e2e770..92348be34 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -47,7 +47,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") } }; - _dbg_assert_(Debug_GPU, map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); + DEBUG_ASSERT(map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); return (map.find(event) != map.end()) ? map.at(event) : QString(); } diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index 4a6159fdf..bd420f24a 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp @@ -76,6 +76,8 @@ TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo format_choice->addItem(tr("IA4")); format_choice->addItem(tr("UNK10")); format_choice->addItem(tr("A4")); + format_choice->addItem(tr("ETC1")); + format_choice->addItem(tr("ETC1A4")); format_choice->setCurrentIndex(static_cast<int>(info.format)); connect(format_choice, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormatChanged(int))); diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp index a9423d6c7..1ba60021f 100644 --- a/src/citra_qt/debugger/graphics_framebuffer.cpp +++ b/src/citra_qt/debugger/graphics_framebuffer.cpp @@ -6,7 +6,6 @@ #include <QComboBox> #include <QDebug> #include <QLabel> -#include <QMetaType> #include <QPushButton> #include <QSpinBox> @@ -17,32 +16,6 @@ #include "util/spinbox.h" -BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, - const QString& title, QWidget* parent) - : QDockWidget(title, parent), BreakPointObserver(debug_context) -{ - qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event"); - - connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); - - // NOTE: This signal is emitted from a non-GUI thread, but connect() takes - // care of delaying its handling to the GUI thread. - connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), - this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), - Qt::BlockingQueuedConnection); -} - -void BreakPointObserverDock::OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) -{ - emit BreakPointHit(event, data); -} - -void BreakPointObserverDock::OnPicaResume() -{ - emit Resumed(); -} - - GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent) : BreakPointObserverDock(debug_context, tr("Pica Framebuffer"), parent), @@ -170,8 +143,8 @@ void GraphicsFramebufferWidget::OnFramebufferWidthChanged(int new_value) void GraphicsFramebufferWidget::OnFramebufferHeightChanged(int new_value) { - if (framebuffer_height != new_value) { - framebuffer_height = new_value; + if (framebuffer_height != static_cast<unsigned>(new_value)) { + framebuffer_height = static_cast<unsigned>(new_value); framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom)); emit Update(); diff --git a/src/citra_qt/debugger/graphics_framebuffer.h b/src/citra_qt/debugger/graphics_framebuffer.h index 56215761e..c6e293bc9 100644 --- a/src/citra_qt/debugger/graphics_framebuffer.h +++ b/src/citra_qt/debugger/graphics_framebuffer.h @@ -6,7 +6,7 @@ #include <QDockWidget> -#include "video_core/debug_utils/debug_utils.h" +#include "graphics_breakpoint_observer.h" class QComboBox; class QLabel; @@ -14,28 +14,6 @@ class QSpinBox; class CSpinBox; -// Utility class which forwards calls to OnPicaBreakPointHit and OnPicaResume to public slots. -// This is because the Pica breakpoint callbacks are called from a non-GUI thread, while -// the widget usually wants to perform reactions in the GUI thread. -class BreakPointObserverDock : public QDockWidget, Pica::DebugContext::BreakPointObserver { - Q_OBJECT - -public: - BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, const QString& title, - QWidget* parent = nullptr); - - void OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) override; - void OnPicaResume() override; - -private slots: - virtual void OnBreakPointHit(Pica::DebugContext::Event event, void* data) = 0; - virtual void OnResumed() = 0; - -signals: - void Resumed(); - void BreakPointHit(Pica::DebugContext::Event event, void* data); -}; - class GraphicsFramebufferWidget : public BreakPointObserverDock { Q_OBJECT diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp new file mode 100644 index 000000000..06eaf0bf0 --- /dev/null +++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp @@ -0,0 +1,298 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <iomanip> +#include <sstream> + +#include <QBoxLayout> +#include <QTreeView> + +#include "video_core/vertex_shader.h" + +#include "graphics_vertex_shader.h" + +using nihstro::Instruction; +using nihstro::SourceRegister; +using nihstro::SwizzlePattern; + +GraphicsVertexShaderModel::GraphicsVertexShaderModel(QObject* parent): QAbstractItemModel(parent) { + +} + +QModelIndex GraphicsVertexShaderModel::index(int row, int column, const QModelIndex& parent) const { + return createIndex(row, column); +} + +QModelIndex GraphicsVertexShaderModel::parent(const QModelIndex& child) const { + return QModelIndex(); +} + +int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const { + return 3; +} + +int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const { + return info.code.size(); +} + +QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { + switch(role) { + case Qt::DisplayRole: + { + if (section == 0) { + return tr("Offset"); + } else if (section == 1) { + return tr("Raw"); + } else if (section == 2) { + return tr("Disassembly"); + } + + break; + } + } + + return QVariant(); +} + +QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const { + switch (role) { + case Qt::DisplayRole: + { + switch (index.column()) { + case 0: + if (info.HasLabel(index.row())) + return QString::fromStdString(info.GetLabel(index.row())); + + return QString("%1").arg(4*index.row(), 4, 16, QLatin1Char('0')); + + case 1: + return QString("%1").arg(info.code[index.row()].hex, 8, 16, QLatin1Char('0')); + + case 2: + { + std::stringstream output; + output.flags(std::ios::hex); + + Instruction instr = info.code[index.row()]; + const SwizzlePattern& swizzle = info.swizzle_info[instr.common.operand_desc_id].pattern; + + // longest known instruction name: "setemit " + output << std::setw(8) << std::left << instr.opcode.GetInfo().name; + + // e.g. "-c92.xyzw" + static auto print_input = [](std::stringstream& output, const SourceRegister& input, + bool negate, const std::string& swizzle_mask) { + output << std::setw(4) << std::right << (negate ? "-" : "") + input.GetName(); + output << "." << swizzle_mask; + }; + + // e.g. "-c92[a0.x].xyzw" + static auto print_input_indexed = [](std::stringstream& output, const SourceRegister& input, + bool negate, const std::string& swizzle_mask, + const std::string& address_register_name) { + std::string relative_address; + if (!address_register_name.empty()) + relative_address = "[" + address_register_name + "]"; + + output << std::setw(10) << std::right << (negate ? "-" : "") + input.GetName() + relative_address; + output << "." << swizzle_mask; + }; + + // Use print_input or print_input_indexed depending on whether relative addressing is used or not. + static auto print_input_indexed_compact = [](std::stringstream& output, const SourceRegister& input, + bool negate, const std::string& swizzle_mask, + const std::string& address_register_name) { + if (address_register_name.empty()) + print_input(output, input, negate, swizzle_mask); + else + print_input_indexed(output, input, negate, swizzle_mask, address_register_name); + }; + + switch (instr.opcode.GetInfo().type) { + case Instruction::OpCodeType::Trivial: + // Nothing to do here + break; + + case Instruction::OpCodeType::Arithmetic: + { + // Use custom code for special instructions + switch (instr.opcode.EffectiveOpCode()) { + case Instruction::OpCode::CMP: + { + // NOTE: CMP always writes both cc components, so we do not consider the dest mask here. + output << std::setw(4) << std::right << "cc."; + output << "xy "; + + SourceRegister src1 = instr.common.GetSrc1(false); + SourceRegister src2 = instr.common.GetSrc2(false); + + print_input_indexed_compact(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), instr.common.AddressRegisterName()); + output << " " << instr.common.compare_op.ToString(instr.common.compare_op.x) << " "; + print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(false).substr(0,1)); + + output << ", "; + + print_input_indexed_compact(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), instr.common.AddressRegisterName()); + output << " " << instr.common.compare_op.ToString(instr.common.compare_op.y) << " "; + print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(false).substr(1,1)); + + break; + } + + default: + { + bool src_is_inverted = 0 != (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::SrcInversed); + + if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::Dest) { + // e.g. "r12.xy__" + output << std::setw(4) << std::right << instr.common.dest.GetName() + "."; + output << swizzle.DestMaskToString(); + } else if (instr.opcode.GetInfo().subtype == Instruction::OpCodeInfo::MOVA) { + output << std::setw(4) << std::right << "a0."; + output << swizzle.DestMaskToString(); + } else { + output << " "; + } + output << " "; + + if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::Src1) { + SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); + print_input_indexed(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), instr.common.AddressRegisterName()); + } else { + output << " "; + } + + // TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1 + if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::Src2) { + SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); + print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(false)); + } + break; + } + } + + break; + } + + case Instruction::OpCodeType::Conditional: + { + switch (instr.opcode.EffectiveOpCode()) { + case Instruction::OpCode::LOOP: + output << "(unknown instruction format)"; + break; + + default: + output << "if "; + + if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::HasCondition) { + const char* ops[] = { + " || ", " && ", "", "" + }; + if (instr.flow_control.op != instr.flow_control.JustY) + output << ((!instr.flow_control.refx) ? "!" : " ") << "cc.x"; + + output << ops[instr.flow_control.op]; + + if (instr.flow_control.op != instr.flow_control.JustX) + output << ((!instr.flow_control.refy) ? "!" : " ") << "cc.y"; + + output << " "; + } else if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::HasUniformIndex) { + output << "b" << instr.flow_control.bool_uniform_id << " "; + } + + u32 target_addr = instr.flow_control.dest_offset; + u32 target_addr_else = instr.flow_control.dest_offset; + + if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::HasAlternative) { + output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << 4 * instr.flow_control.dest_offset << " "; + } else if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::HasExplicitDest) { + output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << 4 * instr.flow_control.dest_offset << " "; + } else { + // TODO: Handle other cases + } + + if (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::HasFinishPoint) { + output << "(return on " << std::setw(4) << std::right << std::setfill('0') + << 4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions << ")"; + } + + break; + } + break; + } + + default: + output << "(unknown instruction format)"; + break; + } + + return QString::fromLatin1(output.str().c_str()); + } + + default: + break; + } + } + + case Qt::FontRole: + return QFont("monospace"); + + default: + break; + } + + return QVariant(); +} + +void GraphicsVertexShaderModel::OnUpdate() +{ + beginResetModel(); + + info.Clear(); + + for (auto instr : Pica::VertexShader::GetShaderBinary()) + info.code.push_back({instr}); + + for (auto pattern : Pica::VertexShader::GetSwizzlePatterns()) + info.swizzle_info.push_back({pattern}); + + info.labels.insert({Pica::registers.vs_main_offset, "main"}); + + endResetModel(); +} + + +GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::DebugContext > debug_context, + QWidget* parent) + : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) { + setObjectName("PicaVertexShader"); + + auto binary_model = new GraphicsVertexShaderModel(this); + auto binary_list = new QTreeView; + binary_list->setModel(binary_model); + binary_list->setRootIsDecorated(false); + binary_list->setAlternatingRowColors(true); + + connect(this, SIGNAL(Update()), binary_model, SLOT(OnUpdate())); + + auto main_widget = new QWidget; + auto main_layout = new QVBoxLayout; + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(binary_list); + main_layout->addLayout(sub_layout); + } + main_widget->setLayout(main_layout); + setWidget(main_widget); +} + +void GraphicsVertexShaderWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) { + emit Update(); + widget()->setEnabled(true); +} + +void GraphicsVertexShaderWidget::OnResumed() { + widget()->setEnabled(false); +} diff --git a/src/citra_qt/debugger/graphics_vertex_shader.h b/src/citra_qt/debugger/graphics_vertex_shader.h new file mode 100644 index 000000000..38339dc05 --- /dev/null +++ b/src/citra_qt/debugger/graphics_vertex_shader.h @@ -0,0 +1,51 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <QAbstractListModel> + +#include "graphics_breakpoint_observer.h" + +#include "nihstro/parser_shbin.h" + +class GraphicsVertexShaderModel : public QAbstractItemModel { + Q_OBJECT + +public: + GraphicsVertexShaderModel(QObject* parent); + + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + +public slots: + void OnUpdate(); + +private: + nihstro::ShaderInfo info; +}; + +class GraphicsVertexShaderWidget : public BreakPointObserverDock { + Q_OBJECT + + using Event = Pica::DebugContext::Event; + +public: + GraphicsVertexShaderWidget(std::shared_ptr<Pica::DebugContext> debug_context, + QWidget* parent = nullptr); + +private slots: + void OnBreakPointHit(Pica::DebugContext::Event event, void* data) override; + void OnResumed() override; + +signals: + void Update(); + +private: + +}; diff --git a/src/citra_qt/debugger/ramview.cpp b/src/citra_qt/debugger/ramview.cpp index 2b199bad1..88570f2cd 100644 --- a/src/citra_qt/debugger/ramview.cpp +++ b/src/citra_qt/debugger/ramview.cpp @@ -14,4 +14,4 @@ void GRamView::OnCPUStepped() { // TODO: QHexEdit doesn't show vertical scroll bars for > 10MB data streams... //setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8)); -}
\ No newline at end of file +} |