diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index 6471c97ac8..6d15d485e3 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -363,6 +363,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -598,6 +603,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -853,6 +863,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -1088,6 +1103,11 @@
true
true
+
+ true
+ true
+ true
+
true
true
@@ -1301,6 +1321,7 @@
+
@@ -1787,6 +1808,24 @@
.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"
+
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing %(Identity)...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB "-DBRANCH=$(BRANCH)" -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing %(Identity)...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing %(Identity)...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing %(Identity)...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"
+
$(QTDIR)\bin\moc.exe;%(FullPath)
Moc%27ing %(Identity)...
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index 1ef9787ac5..a3f0cc56ec 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -646,6 +646,9 @@
Gui\debugger
+
+ Gui\debugger
+
Generated Files\Release - LLVM
@@ -658,6 +661,18 @@
Generated Files\Debug - LLVM
+
+ Generated Files\Release - LLVM
+
+
+ Generated Files\Debug
+
+
+ Generated Files\Release
+
+
+ Generated Files\Debug - LLVM
+
Generated Files
@@ -1157,6 +1172,9 @@
Gui\debugger
+
+ Gui\debugger
+
Resource Files
diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt
index 99fbd7e497..4fd2e42991 100644
--- a/rpcs3/rpcs3qt/CMakeLists.txt
+++ b/rpcs3/rpcs3qt/CMakeLists.txt
@@ -3,6 +3,7 @@
auto_pause_settings_dialog.cpp
breakpoint_handler.cpp
breakpoint_list.cpp
+ call_stack_list.cpp
cg_disasm_window.cpp
cheat_manager.cpp
curl_handle.cpp
diff --git a/rpcs3/rpcs3qt/call_stack_list.cpp b/rpcs3/rpcs3qt/call_stack_list.cpp
new file mode 100644
index 0000000000..c59c94c307
--- /dev/null
+++ b/rpcs3/rpcs3qt/call_stack_list.cpp
@@ -0,0 +1,37 @@
+#include "call_stack_list.h"
+
+constexpr auto qstr = QString::fromStdString;
+
+call_stack_list::call_stack_list(QWidget* parent) : QListWidget(parent)
+{
+ setEditTriggers(QAbstractItemView::NoEditTriggers);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ // connects
+ connect(this, &QListWidget::itemDoubleClicked, this, &call_stack_list::OnCallStackListDoubleClicked);
+}
+
+void call_stack_list::UpdateCPUData(std::weak_ptr cpu, std::shared_ptr disasm)
+{
+ this->cpu = cpu;
+}
+
+void call_stack_list::HandleUpdate(std::vector call_stack)
+{
+ clear();
+
+ for (auto addr : call_stack)
+ {
+ const QString call_stack_item_text = qstr(fmt::format("0x%08llx", addr));
+ QListWidgetItem* callStackItem = new QListWidgetItem(call_stack_item_text);
+ callStackItem->setData(Qt::UserRole, { addr });
+ addItem(callStackItem);
+ }
+}
+
+void call_stack_list::OnCallStackListDoubleClicked()
+{
+ const u32 address = currentItem()->data(Qt::UserRole).value();
+ Q_EMIT RequestShowAddress(address);
+}
diff --git a/rpcs3/rpcs3qt/call_stack_list.h b/rpcs3/rpcs3qt/call_stack_list.h
new file mode 100644
index 0000000000..ca778e5e3b
--- /dev/null
+++ b/rpcs3/rpcs3qt/call_stack_list.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "stdafx.h"
+
+#include "Emu/CPU/CPUThread.h"
+#include "Emu/CPU/CPUDisAsm.h"
+
+#include
+
+class call_stack_list : public QListWidget
+{
+ Q_OBJECT
+
+public:
+ call_stack_list(QWidget* parent);
+ void UpdateCPUData(std::weak_ptr cpu, std::shared_ptr disasm);
+
+Q_SIGNALS:
+ void RequestShowAddress(u32 addr);
+public Q_SLOTS:
+ void HandleUpdate(std::vector call_stack);
+private Q_SLOTS:
+ void OnCallStackListDoubleClicked();
+private:
+ std::weak_ptr cpu;
+};
diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp
index 10864abee2..472c27f044 100644
--- a/rpcs3/rpcs3qt/debugger_frame.cpp
+++ b/rpcs3/rpcs3qt/debugger_frame.cpp
@@ -5,6 +5,7 @@
#include "debugger_list.h"
#include "breakpoint_list.h"
#include "breakpoint_handler.h"
+#include "call_stack_list.h"
#include "qt_utils.h"
#include "Emu/System.h"
@@ -48,10 +49,12 @@ debugger_frame::debugger_frame(std::shared_ptr settings, QWidget *
hbox_b_main->setContentsMargins(0, 0, 0, 0);
m_breakpoint_handler = new breakpoint_handler();
+ m_breakpoint_list = new breakpoint_list(this, m_breakpoint_handler);
+
m_debugger_list = new debugger_list(this, settings, m_breakpoint_handler);
m_debugger_list->installEventFilter(this);
- m_breakpoint_list = new breakpoint_list(this, m_breakpoint_handler);
+ m_call_stack_list = new call_stack_list(this);
m_choice_units = new QComboBox(this);
m_choice_units->setSizeAdjustPolicy(QComboBox::AdjustToContents);
@@ -97,13 +100,20 @@ debugger_frame::debugger_frame(std::shared_ptr settings, QWidget *
m_debugger_list->setFont(m_mono);
m_misc_state->setFont(m_mono);
m_regs->setFont(m_mono);
+ m_call_stack_list->setFont(m_mono);
m_right_splitter = new QSplitter(this);
m_right_splitter->setOrientation(Qt::Vertical);
m_right_splitter->addWidget(m_misc_state);
m_right_splitter->addWidget(m_regs);
+ m_right_splitter->addWidget(m_call_stack_list);
m_right_splitter->addWidget(m_breakpoint_list);
- m_right_splitter->setStretchFactor(0, 1);
+
+ // Set relative sizes for widgets
+ m_right_splitter->setStretchFactor(0, 2); // misc state
+ m_right_splitter->setStretchFactor(1, 8); // registers
+ m_right_splitter->setStretchFactor(2, 3); // call stack
+ m_right_splitter->setStretchFactor(3, 1); // breakpoint list
m_splitter = new QSplitter(this);
m_splitter->addWidget(m_debugger_list);
@@ -161,6 +171,9 @@ debugger_frame::debugger_frame(std::shared_ptr settings, QWidget *
connect(m_debugger_list, &debugger_list::BreakpointRequested, m_breakpoint_list, &breakpoint_list::HandleBreakpointRequest);
connect(m_breakpoint_list, &breakpoint_list::RequestShowAddress, m_debugger_list, &debugger_list::ShowAddress);
+ connect(this, &debugger_frame::CallStackUpdateRequested, m_call_stack_list, &call_stack_list::HandleUpdate);
+ connect(m_call_stack_list, &call_stack_list::RequestShowAddress, m_debugger_list, &debugger_list::ShowAddress);
+
m_debugger_list->ShowAddress(m_debugger_list->m_pc);
UpdateUnitList();
}
@@ -409,6 +422,7 @@ void debugger_frame::OnSelectUnit()
m_debugger_list->UpdateCPUData(this->cpu, m_disasm);
m_breakpoint_list->UpdateCPUData(this->cpu, m_disasm);
+ m_call_stack_list->UpdateCPUData(this->cpu, m_disasm);
DoUpdate();
UpdateUI();
}
@@ -448,6 +462,8 @@ void debugger_frame::WritePanels()
m_regs->clear();
m_regs->setText(qstr(cpu->dump_regs()));
m_regs->verticalScrollBar()->setValue(loc);
+
+ Q_EMIT CallStackUpdateRequested(cpu->dump_callstack_list());
}
void debugger_frame::ShowGotoAddressDialog()
@@ -560,6 +576,11 @@ void debugger_frame::ClearBreakpoints()
m_breakpoint_list->ClearBreakpoints();
}
+void debugger_frame::ClearCallStack()
+{
+ Q_EMIT CallStackUpdateRequested({});
+}
+
void debugger_frame::ShowPC()
{
m_debugger_list->ShowAddress(GetPc());
diff --git a/rpcs3/rpcs3qt/debugger_frame.h b/rpcs3/rpcs3qt/debugger_frame.h
index 9b9c877fb1..e16908282e 100644
--- a/rpcs3/rpcs3qt/debugger_frame.h
+++ b/rpcs3/rpcs3qt/debugger_frame.h
@@ -15,6 +15,7 @@ class gui_settings;
class debugger_list;
class breakpoint_list;
class breakpoint_handler;
+class call_stack_list;
class debugger_frame : public custom_dock_widget
{
@@ -53,6 +54,8 @@ class debugger_frame : public custom_dock_widget
breakpoint_list* m_breakpoint_list;
breakpoint_handler* m_breakpoint_handler;
+ call_stack_list* m_call_stack_list;
+
std::shared_ptr xgui_settings;
public:
@@ -71,6 +74,7 @@ public:
void ShowGotoAddressDialog();
u64 EvaluateExpression(const QString& expression);
void ClearBreakpoints(); // Fallthrough method into breakpoint_list.
+ void ClearCallStack();
/** Needed so key press events work when other objects are selected in debugger_frame. */
bool eventFilter(QObject* object, QEvent* event) override;
@@ -83,6 +87,7 @@ protected:
Q_SIGNALS:
void DebugFrameClosed();
+ void CallStackUpdateRequested(std::vector call_stack);
public Q_SLOTS:
void DoStep(bool stepOver = false);
diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp
index 7ac39586d3..7737d1d474 100644
--- a/rpcs3/rpcs3qt/main_window.cpp
+++ b/rpcs3/rpcs3qt/main_window.cpp
@@ -991,6 +991,7 @@ void main_window::OnEmuStop()
m_debugger_frame->EnableButtons(false);
m_debugger_frame->ClearBreakpoints();
+ m_debugger_frame->ClearCallStack();
ui->sysPauseAct->setText(Emu.IsReady() ? tr("&Play\tCtrl+E") : tr("&Resume\tCtrl+E"));
ui->sysPauseAct->setIcon(m_icon_play);