summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/CMakeLists.txt3
-rw-r--r--src/citra_qt/debugger/disassembler.cpp272
-rw-r--r--src/citra_qt/debugger/disassembler.h76
-rw-r--r--src/citra_qt/debugger/disassembler.ui81
-rw-r--r--src/citra_qt/main.cpp14
-rw-r--r--src/citra_qt/main.h2
6 files changed, 0 insertions, 448 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 3e6106f0a..0b4fe6dd2 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -12,7 +12,6 @@ set(SRCS
12 configuration/configure_input.cpp 12 configuration/configure_input.cpp
13 configuration/configure_system.cpp 13 configuration/configure_system.cpp
14 debugger/callstack.cpp 14 debugger/callstack.cpp
15 debugger/disassembler.cpp
16 debugger/graphics/graphics.cpp 15 debugger/graphics/graphics.cpp
17 debugger/graphics/graphics_breakpoint_observer.cpp 16 debugger/graphics/graphics_breakpoint_observer.cpp
18 debugger/graphics/graphics_breakpoints.cpp 17 debugger/graphics/graphics_breakpoints.cpp
@@ -44,7 +43,6 @@ set(HEADERS
44 configuration/configure_input.h 43 configuration/configure_input.h
45 configuration/configure_system.h 44 configuration/configure_system.h
46 debugger/callstack.h 45 debugger/callstack.h
47 debugger/disassembler.h
48 debugger/graphics/graphics.h 46 debugger/graphics/graphics.h
49 debugger/graphics/graphics_breakpoint_observer.h 47 debugger/graphics/graphics_breakpoint_observer.h
50 debugger/graphics/graphics_breakpoints.h 48 debugger/graphics/graphics_breakpoints.h
@@ -75,7 +73,6 @@ set(UIS
75 configuration/configure_input.ui 73 configuration/configure_input.ui
76 configuration/configure_system.ui 74 configuration/configure_system.ui
77 debugger/callstack.ui 75 debugger/callstack.ui
78 debugger/disassembler.ui
79 debugger/registers.ui 76 debugger/registers.ui
80 hotkeys.ui 77 hotkeys.ui
81 main.ui 78 main.ui
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
deleted file mode 100644
index e9c8ad858..000000000
--- a/src/citra_qt/debugger/disassembler.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QShortcut>
6#include "citra_qt/bootmanager.h"
7#include "citra_qt/debugger/disassembler.h"
8#include "citra_qt/hotkeys.h"
9#include "citra_qt/util/util.h"
10#include "common/break_points.h"
11#include "common/symbols.h"
12#include "core/arm/arm_interface.h"
13#include "core/arm/disassembler/arm_disasm.h"
14#include "core/core.h"
15#include "core/memory.h"
16
17DisassemblerModel::DisassemblerModel(QObject* parent)
18 : QAbstractListModel(parent), base_address(0), code_size(0), program_counter(0),
19 selection(QModelIndex()) {}
20
21int DisassemblerModel::columnCount(const QModelIndex& parent) const {
22 return 3;
23}
24
25int DisassemblerModel::rowCount(const QModelIndex& parent) const {
26 return code_size;
27}
28
29QVariant DisassemblerModel::data(const QModelIndex& index, int role) const {
30 switch (role) {
31 case Qt::DisplayRole: {
32 u32 address = base_address + index.row() * 4;
33 u32 instr = Memory::Read32(address);
34 std::string disassembly = ARM_Disasm::Disassemble(address, instr);
35
36 if (index.column() == 0) {
37 return QString("0x%1").arg((uint)(address), 8, 16, QLatin1Char('0'));
38 } else if (index.column() == 1) {
39 return QString::fromStdString(disassembly);
40 } else if (index.column() == 2) {
41 if (Symbols::HasSymbol(address)) {
42 TSymbol symbol = Symbols::GetSymbol(address);
43 return QString("%1 - Size:%2")
44 .arg(QString::fromStdString(symbol.name))
45 .arg(symbol.size / 4); // divide by 4 to get instruction count
46 } else if (ARM_Disasm::Decode(instr) == OP_BL) {
47 u32 offset = instr & 0xFFFFFF;
48
49 // Sign-extend the 24-bit offset
50 if ((offset >> 23) & 1)
51 offset |= 0xFF000000;
52
53 // Pre-compute the left-shift and the prefetch offset
54 offset <<= 2;
55 offset += 8;
56
57 TSymbol symbol = Symbols::GetSymbol(address + offset);
58 return QString(" --> %1").arg(QString::fromStdString(symbol.name));
59 }
60 }
61
62 break;
63 }
64
65 case Qt::BackgroundRole: {
66 unsigned int address = base_address + 4 * index.row();
67
68 if (breakpoints.IsAddressBreakPoint(address))
69 return QBrush(QColor(0xFF, 0xC0, 0xC0));
70 else if (address == program_counter)
71 return QBrush(QColor(0xC0, 0xC0, 0xFF));
72
73 break;
74 }
75
76 case Qt::FontRole: {
77 if (index.column() == 0 || index.column() == 1) { // 2 is the symbols column
78 return GetMonospaceFont();
79 }
80 break;
81 }
82
83 default:
84 break;
85 }
86
87 return QVariant();
88}
89
90QModelIndex DisassemblerModel::IndexFromAbsoluteAddress(unsigned int address) const {
91 return index((address - base_address) / 4, 0);
92}
93
94const BreakPoints& DisassemblerModel::GetBreakPoints() const {
95 return breakpoints;
96}
97
98void DisassemblerModel::ParseFromAddress(unsigned int address) {
99
100 // NOTE: A too large value causes lagging when scrolling the disassembly
101 const unsigned int chunk_size = 1000 * 500;
102
103 // If we haven't loaded anything yet, initialize base address to the parameter address
104 if (code_size == 0)
105 base_address = address;
106
107 // If the new area is already loaded, just continue
108 if (base_address + code_size > address + chunk_size && base_address <= address)
109 return;
110
111 // Insert rows before currently loaded data
112 if (base_address > address) {
113 unsigned int num_rows = (address - base_address) / 4;
114
115 beginInsertRows(QModelIndex(), 0, num_rows);
116 code_size += num_rows;
117 base_address = address;
118
119 endInsertRows();
120 }
121
122 // Insert rows after currently loaded data
123 if (base_address + code_size < address + chunk_size) {
124 unsigned int num_rows = (base_address + chunk_size - code_size - address) / 4;
125
126 beginInsertRows(QModelIndex(), 0, num_rows);
127 code_size += num_rows;
128 endInsertRows();
129 }
130
131 SetNextInstruction(address);
132}
133
134void DisassemblerModel::OnSelectionChanged(const QModelIndex& new_selection) {
135 selection = new_selection;
136}
137
138void DisassemblerModel::OnSetOrUnsetBreakpoint() {
139 if (!selection.isValid())
140 return;
141
142 unsigned int address = base_address + selection.row() * 4;
143
144 if (breakpoints.IsAddressBreakPoint(address)) {
145 breakpoints.Remove(address);
146 } else {
147 breakpoints.Add(address);
148 }
149
150 emit dataChanged(selection, selection);
151}
152
153void DisassemblerModel::SetNextInstruction(unsigned int address) {
154 QModelIndex cur_index = IndexFromAbsoluteAddress(program_counter);
155 QModelIndex prev_index = IndexFromAbsoluteAddress(address);
156
157 program_counter = address;
158
159 emit dataChanged(cur_index, cur_index);
160 emit dataChanged(prev_index, prev_index);
161}
162
163DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread)
164 : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) {
165
166 disasm_ui.setupUi(this);
167
168 RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut);
169 RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut);
170 RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut);
171 RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9),
172 Qt::ApplicationShortcut);
173
174 connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep()));
175 connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause()));
176 connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue()));
177
178 connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this,
179 SLOT(OnToggleStartStop()));
180 connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep()));
181 connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this,
182 SLOT(OnStepInto()));
183
184 setEnabled(false);
185}
186
187void DisassemblerWidget::Init() {
188 model->ParseFromAddress(Core::CPU().GetPC());
189
190 disasm_ui.treeView->resizeColumnToContents(0);
191 disasm_ui.treeView->resizeColumnToContents(1);
192 disasm_ui.treeView->resizeColumnToContents(2);
193
194 QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::CPU().GetPC());
195 disasm_ui.treeView->scrollTo(model_index);
196 disasm_ui.treeView->selectionModel()->setCurrentIndex(
197 model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
198}
199
200void DisassemblerWidget::OnContinue() {
201 emu_thread->SetRunning(true);
202}
203
204void DisassemblerWidget::OnStep() {
205 OnStepInto(); // change later
206}
207
208void DisassemblerWidget::OnStepInto() {
209 emu_thread->SetRunning(false);
210 emu_thread->ExecStep();
211}
212
213void DisassemblerWidget::OnPause() {
214 emu_thread->SetRunning(false);
215
216 // TODO: By now, the CPU might not have actually stopped...
217 if (Core::System::GetInstance().IsPoweredOn()) {
218 model->SetNextInstruction(Core::CPU().GetPC());
219 }
220}
221
222void DisassemblerWidget::OnToggleStartStop() {
223 emu_thread->SetRunning(!emu_thread->IsRunning());
224}
225
226void DisassemblerWidget::OnDebugModeEntered() {
227 u32 next_instr = Core::CPU().GetPC();
228
229 if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))
230 emu_thread->SetRunning(false);
231
232 model->SetNextInstruction(next_instr);
233
234 QModelIndex model_index = model->IndexFromAbsoluteAddress(next_instr);
235 disasm_ui.treeView->scrollTo(model_index);
236 disasm_ui.treeView->selectionModel()->setCurrentIndex(
237 model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
238}
239
240void DisassemblerWidget::OnDebugModeLeft() {}
241
242int DisassemblerWidget::SelectedRow() {
243 QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex();
244 if (!index.isValid())
245 return -1;
246
247 return disasm_ui.treeView->selectionModel()->currentIndex().row();
248}
249
250void DisassemblerWidget::OnEmulationStarting(EmuThread* emu_thread) {
251 this->emu_thread = emu_thread;
252
253 model = new DisassemblerModel(this);
254 disasm_ui.treeView->setModel(model);
255
256 connect(disasm_ui.treeView->selectionModel(),
257 SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), model,
258 SLOT(OnSelectionChanged(const QModelIndex&)));
259 connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), model, SLOT(OnSetOrUnsetBreakpoint()));
260 connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), model,
261 SLOT(OnSetOrUnsetBreakpoint()));
262
263 Init();
264 setEnabled(true);
265}
266
267void DisassemblerWidget::OnEmulationStopping() {
268 disasm_ui.treeView->setModel(nullptr);
269 delete model;
270 emu_thread = nullptr;
271 setEnabled(false);
272}
diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h
deleted file mode 100644
index a6e59515c..000000000
--- a/src/citra_qt/debugger/disassembler.h
+++ /dev/null
@@ -1,76 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <QAbstractListModel>
8#include <QDockWidget>
9#include "common/break_points.h"
10#include "common/common_types.h"
11#include "ui_disassembler.h"
12
13class QAction;
14class EmuThread;
15
16class DisassemblerModel : public QAbstractListModel {
17 Q_OBJECT
18
19public:
20 explicit DisassemblerModel(QObject* parent);
21
22 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
23 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
24 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
25
26 QModelIndex IndexFromAbsoluteAddress(unsigned int address) const;
27 const BreakPoints& GetBreakPoints() const;
28
29public slots:
30 void ParseFromAddress(unsigned int address);
31 void OnSelectionChanged(const QModelIndex&);
32 void OnSetOrUnsetBreakpoint();
33 void SetNextInstruction(unsigned int address);
34
35private:
36 unsigned int base_address;
37 unsigned int code_size;
38 unsigned int program_counter;
39
40 QModelIndex selection;
41 BreakPoints breakpoints;
42};
43
44class DisassemblerWidget : public QDockWidget {
45 Q_OBJECT
46
47public:
48 DisassemblerWidget(QWidget* parent, EmuThread* emu_thread);
49
50 void Init();
51
52public slots:
53 void OnContinue();
54 void OnStep();
55 void OnStepInto();
56 void OnPause();
57 void OnToggleStartStop();
58
59 void OnDebugModeEntered();
60 void OnDebugModeLeft();
61
62 void OnEmulationStarting(EmuThread* emu_thread);
63 void OnEmulationStopping();
64
65private:
66 // returns -1 if no row is selected
67 int SelectedRow();
68
69 Ui::DockWidget disasm_ui;
70
71 DisassemblerModel* model;
72
73 u32 base_addr;
74
75 EmuThread* emu_thread;
76};
diff --git a/src/citra_qt/debugger/disassembler.ui b/src/citra_qt/debugger/disassembler.ui
deleted file mode 100644
index 5ca6dc5d2..000000000
--- a/src/citra_qt/debugger/disassembler.ui
+++ /dev/null
@@ -1,81 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>DockWidget</class>
4 <widget class="QDockWidget" name="DockWidget">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>430</width>
10 <height>401</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Disassembly</string>
15 </property>
16 <widget class="QWidget" name="dockWidgetContents">
17 <layout class="QVBoxLayout" name="verticalLayout">
18 <item>
19 <layout class="QHBoxLayout" name="horizontalLayout">
20 <item>
21 <widget class="QPushButton" name="button_step">
22 <property name="text">
23 <string>Step</string>
24 </property>
25 </widget>
26 </item>
27 <item>
28 <widget class="QPushButton" name="button_pause">
29 <property name="text">
30 <string>Pause</string>
31 </property>
32 </widget>
33 </item>
34 <item>
35 <widget class="QPushButton" name="button_continue">
36 <property name="text">
37 <string>Continue</string>
38 </property>
39 </widget>
40 </item>
41 <item>
42 <widget class="QPushButton" name="pushButton">
43 <property name="text">
44 <string>Step Into</string>
45 </property>
46 </widget>
47 </item>
48 <item>
49 <widget class="QPushButton" name="button_breakpoint">
50 <property name="text">
51 <string>Set Breakpoint</string>
52 </property>
53 </widget>
54 </item>
55 </layout>
56 </item>
57 <item>
58 <widget class="QTreeView" name="treeView">
59 <property name="alternatingRowColors">
60 <bool>true</bool>
61 </property>
62 <property name="indentation">
63 <number>20</number>
64 </property>
65 <property name="rootIsDecorated">
66 <bool>false</bool>
67 </property>
68 <property name="uniformRowHeights">
69 <bool>true</bool>
70 </property>
71 <attribute name="headerVisible">
72 <bool>false</bool>
73 </attribute>
74 </widget>
75 </item>
76 </layout>
77 </widget>
78 </widget>
79 <resources/>
80 <connections/>
81</ui>
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index ea66cc425..50149bcb0 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -17,7 +17,6 @@
17#include "citra_qt/configuration/config.h" 17#include "citra_qt/configuration/config.h"
18#include "citra_qt/configuration/configure_dialog.h" 18#include "citra_qt/configuration/configure_dialog.h"
19#include "citra_qt/debugger/callstack.h" 19#include "citra_qt/debugger/callstack.h"
20#include "citra_qt/debugger/disassembler.h"
21#include "citra_qt/debugger/graphics/graphics.h" 20#include "citra_qt/debugger/graphics/graphics.h"
22#include "citra_qt/debugger/graphics/graphics_breakpoints.h" 21#include "citra_qt/debugger/graphics/graphics_breakpoints.h"
23#include "citra_qt/debugger/graphics/graphics_cmdlists.h" 22#include "citra_qt/debugger/graphics/graphics_cmdlists.h"
@@ -130,15 +129,6 @@ void GMainWindow::InitializeDebugWidgets() {
130 debug_menu->addAction(microProfileDialog->toggleViewAction()); 129 debug_menu->addAction(microProfileDialog->toggleViewAction());
131#endif 130#endif
132 131
133 disasmWidget = new DisassemblerWidget(this, emu_thread.get());
134 addDockWidget(Qt::BottomDockWidgetArea, disasmWidget);
135 disasmWidget->hide();
136 debug_menu->addAction(disasmWidget->toggleViewAction());
137 connect(this, &GMainWindow::EmulationStarting, disasmWidget,
138 &DisassemblerWidget::OnEmulationStarting);
139 connect(this, &GMainWindow::EmulationStopping, disasmWidget,
140 &DisassemblerWidget::OnEmulationStopping);
141
142 registersWidget = new RegistersWidget(this); 132 registersWidget = new RegistersWidget(this);
143 addDockWidget(Qt::RightDockWidgetArea, registersWidget); 133 addDockWidget(Qt::RightDockWidgetArea, registersWidget);
144 registersWidget->hide(); 134 registersWidget->hide();
@@ -391,16 +381,12 @@ void GMainWindow::BootGame(const QString& filename) {
391 connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame())); 381 connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame()));
392 // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views 382 // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
393 // before the CPU continues 383 // before the CPU continues
394 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()),
395 Qt::BlockingQueuedConnection);
396 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, 384 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget,
397 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); 385 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
398 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, 386 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget,
399 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); 387 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
400 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), waitTreeWidget, 388 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), waitTreeWidget,
401 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); 389 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
402 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()),
403 Qt::BlockingQueuedConnection);
404 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), 390 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()),
405 Qt::BlockingQueuedConnection); 391 Qt::BlockingQueuedConnection);
406 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), 392 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()),
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index 2f398eb7b..2417dc2cb 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -12,7 +12,6 @@
12 12
13class CallstackWidget; 13class CallstackWidget;
14class Config; 14class Config;
15class DisassemblerWidget;
16class EmuThread; 15class EmuThread;
17class GameList; 16class GameList;
18class GImageInfo; 17class GImageInfo;
@@ -152,7 +151,6 @@ private:
152 // Debugger panes 151 // Debugger panes
153 ProfilerWidget* profilerWidget; 152 ProfilerWidget* profilerWidget;
154 MicroProfileDialog* microProfileDialog; 153 MicroProfileDialog* microProfileDialog;
155 DisassemblerWidget* disasmWidget;
156 RegistersWidget* registersWidget; 154 RegistersWidget* registersWidget;
157 CallstackWidget* callstackWidget; 155 CallstackWidget* callstackWidget;
158 GPUCommandStreamWidget* graphicsWidget; 156 GPUCommandStreamWidget* graphicsWidget;