@@ -21,7 +21,7 @@
#include "Core/HW/CPU.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "DolphinQt2/Debugger/CodeViewWidget.h"
#include "DolphinQt2/Host.h"
#include "DolphinQt2/Settings.h"

CodeWidget::CodeWidget(QWidget* parent) : QDockWidget(parent)
@@ -39,6 +39,12 @@ CodeWidget::CodeWidget(QWidget* parent) : QDockWidget(parent)
connect(&Settings::Instance(), &Settings::CodeVisibilityChanged,
[this](bool visible) { setHidden(!visible); });

connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this, [this] {
if (Core::GetState() == Core::State::Paused)
SetAddress(PowerPC::ppcState.pc, CodeViewWidget::SetAddressUpdate::WithoutUpdate);
Update();
});

connect(&Settings::Instance(), &Settings::DebugModeToggled,
[this](bool enabled) { setHidden(!enabled || !Settings::Instance().IsCodeVisible()); });

@@ -141,7 +147,7 @@ void CodeWidget::ConnectWidgets()
connect(m_search_address, &QLineEdit::textChanged, this, &CodeWidget::OnSearchAddress);
connect(m_search_symbols, &QLineEdit::textChanged, this, &CodeWidget::OnSearchSymbols);

connect(m_symbols_list, &QListWidget::itemSelectionChanged, this, &CodeWidget::OnSelectSymbol);
connect(m_symbols_list, &QListWidget::itemClicked, this, &CodeWidget::OnSelectSymbol);
connect(m_callstack_list, &QListWidget::itemSelectionChanged, this,
&CodeWidget::OnSelectCallstack);
connect(m_function_calls_list, &QListWidget::itemSelectionChanged, this,
@@ -175,7 +181,7 @@ void CodeWidget::OnSearchAddress()
m_search_address->setFont(font);

if (good)
m_code_view->SetAddress(address);
m_code_view->SetAddress(address, CodeViewWidget::SetAddressUpdate::WithUpdate);

Update();
}
@@ -194,7 +200,8 @@ void CodeWidget::OnSelectSymbol()

Symbol* symbol = g_symbolDB.GetSymbolFromAddr(items[0]->data(Qt::UserRole).toUInt());

m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt());
m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt(),
CodeViewWidget::SetAddressUpdate::WithUpdate);
UpdateCallstack();
UpdateFunctionCalls(symbol);
UpdateFunctionCallers(symbol);
@@ -208,7 +215,8 @@ void CodeWidget::OnSelectCallstack()
if (items.isEmpty())
return;

m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt());
m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt(),
CodeViewWidget::SetAddressUpdate::WithUpdate);
Update();
}

@@ -218,7 +226,8 @@ void CodeWidget::OnSelectFunctionCalls()
if (items.isEmpty())
return;

m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt());
m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt(),
CodeViewWidget::SetAddressUpdate::WithUpdate);
Update();
}

@@ -228,25 +237,30 @@ void CodeWidget::OnSelectFunctionCallers()
if (items.isEmpty())
return;

m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt());
m_code_view->SetAddress(items[0]->data(Qt::UserRole).toUInt(),
CodeViewWidget::SetAddressUpdate::WithUpdate);
Update();
}

void CodeWidget::SetAddress(u32 address, CodeViewWidget::SetAddressUpdate update)
{
m_code_view->SetAddress(address, update);
}

void CodeWidget::Update()
{
Symbol* symbol = g_symbolDB.GetSymbolFromAddr(m_code_view->GetAddress());

UpdateCallstack();
UpdateSymbols();

m_code_view->Update();
m_code_view->setFocus();

if (!symbol)
return;

UpdateFunctionCalls(symbol);
UpdateFunctionCallers(symbol);

m_code_view->Update();
m_code_view->setFocus();
}

void CodeWidget::UpdateCallstack()
@@ -358,10 +372,7 @@ void CodeWidget::Step()
sync_event.WaitFor(std::chrono::milliseconds(20));
PowerPC::SetMode(old_mode);
Core::DisplayMessage(tr("Step successful!").toStdString(), 2000);

Core::SetState(Core::State::Paused);
m_code_view->SetAddress(PC);
Update();
// Will get a UpdateDisasmDialog(), don't update the GUI here.
}

void CodeWidget::StepOver()
@@ -381,10 +392,6 @@ void CodeWidget::StepOver()
{
Step();
}

Core::SetState(Core::State::Paused);
m_code_view->SetAddress(PC);
Update();
}

// Returns true on a rfi, blr or on a bclr that evaluates to true.
@@ -404,7 +411,6 @@ void CodeWidget::StepOut()
if (!CPU::IsStepping())
return;

Core::SetState(Core::State::Running);
CPU::PauseAndLock(true, false);
PowerPC::breakpoints.ClearAllTemporary();

@@ -447,16 +453,14 @@ void CodeWidget::StepOut()
PowerPC::SetMode(old_mode);
CPU::PauseAndLock(false, false);

emit Host::GetInstance()->UpdateDisasmDialog();

if (PowerPC::breakpoints.IsAddressBreakPoint(PC))
Core::DisplayMessage(tr("Breakpoint encountered! Step out aborted.").toStdString(), 2000);
else if (clock::now() >= timeout)
Core::DisplayMessage(tr("Step out timed out!").toStdString(), 2000);
else
Core::DisplayMessage(tr("Step out successful!").toStdString(), 2000);

Core::SetState(Core::State::Paused);
m_code_view->SetAddress(PC);
Update();
}

void CodeWidget::Skip()
@@ -467,7 +471,7 @@ void CodeWidget::Skip()

void CodeWidget::ShowPC()
{
m_code_view->SetAddress(PC);
m_code_view->SetAddress(PC, CodeViewWidget::SetAddressUpdate::WithUpdate);
Update();
}

@@ -8,8 +8,8 @@
#include <QString>

#include "Common/CommonTypes.h"
#include "DolphinQt2/Debugger/CodeViewWidget.h"

class CodeViewWidget;
class QCloseEvent;
class QLineEdit;
class QSplitter;
@@ -33,8 +33,10 @@ class CodeWidget : public QDockWidget

void ToggleBreakpoint();
void AddBreakpoint();
void SetAddress(u32 address, CodeViewWidget::SetAddressUpdate update);

void Update();
void UpdateSymbols();
signals:
void BreakpointsChanged();
void RequestPPCComparison(u32 addr);
@@ -43,7 +45,6 @@ class CodeWidget : public QDockWidget
void CreateWidgets();
void ConnectWidgets();
void UpdateCallstack();
void UpdateSymbols();
void UpdateFunctionCalls(Symbol* symbol);
void UpdateFunctionCallers(Symbol* symbol);

@@ -7,6 +7,7 @@
#include "Core/Core.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "DolphinQt2/Host.h"
#include "DolphinQt2/QtUtils/ActionHelper.h"
#include "DolphinQt2/Settings.h"

@@ -30,15 +31,13 @@ RegisterWidget::RegisterWidget(QWidget* parent) : QDockWidget(parent)
PopulateTable();
ConnectWidgets();

connect(&Settings::Instance(), &Settings::EmulationStateChanged, [this](Core::State state) {
connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this, [this] {
if (Settings::Instance().IsDebugModeEnabled() && Core::GetState() == Core::State::Paused)
emit RequestTableUpdate();
});

connect(this, &RegisterWidget::RequestTableUpdate, [this] {
m_updating = true;
emit UpdateTable();
m_updating = false;
{
m_updating = true;
emit UpdateTable();
m_updating = false;
}
});

connect(&Settings::Instance(), &Settings::RegistersVisibilityChanged,
@@ -74,7 +73,8 @@ void RegisterWidget::CreateWidgets()
m_table->verticalHeader()->setVisible(false);
m_table->verticalHeader()->setDefaultSectionSize(24);
m_table->setContextMenuPolicy(Qt::CustomContextMenu);
m_table->setSelectionMode(QAbstractItemView::SingleSelection);
m_table->setSelectionMode(QAbstractItemView::NoSelection);
m_table->setFont(Settings::Instance().GetDebugFont());

QStringList empty_list;

@@ -108,108 +108,105 @@ void RegisterWidget::ShowContextMenu()
{
QMenu* menu = new QMenu(this);

if (m_table->selectedItems().size())
auto variant = m_table->currentItem()->data(DATA_TYPE);

if (!variant.isNull())
{
auto variant = m_table->selectedItems()[0]->data(DATA_TYPE);
auto* item = static_cast<RegisterColumn*>(m_table->currentItem());
auto type = static_cast<RegisterType>(item->data(DATA_TYPE).toInt());
auto display = item->GetDisplay();

AddAction(menu, tr("Add to &watch"), this,
[this, item] { emit RequestMemoryBreakpoint(item->GetValue()); });
menu->addAction(tr("View &memory"));
menu->addAction(tr("View &code"));

menu->addSeparator();

QActionGroup* group = new QActionGroup(menu);
group->setExclusive(true);

if (!variant.isNull())
auto* view_hex = menu->addAction(tr("Hexadecimal"));
auto* view_int = menu->addAction(tr("Signed Integer"));
auto* view_uint = menu->addAction(tr("Unsigned Integer"));
// i18n: A floating point number
auto* view_float = menu->addAction(tr("Float"));
// i18n: A double precision floating point number
auto* view_double = menu->addAction(tr("Double"));

for (auto* action : {view_hex, view_int, view_uint, view_float, view_double})
{
action->setCheckable(true);
action->setVisible(false);
action->setActionGroup(group);
}

switch (display)
{
auto* item = reinterpret_cast<RegisterColumn*>(m_table->selectedItems()[0]);
auto type = static_cast<RegisterType>(item->data(DATA_TYPE).toInt());
auto display = item->GetDisplay();

AddAction(menu, tr("Add to &watch"), this,
[this, item] { emit RequestMemoryBreakpoint(item->GetValue()); });
menu->addAction(tr("View &memory"));
menu->addAction(tr("View &code"));

menu->addSeparator();

QActionGroup* group = new QActionGroup(menu);
group->setExclusive(true);

auto* view_hex = menu->addAction(tr("Hexadecimal"));
auto* view_int = menu->addAction(tr("Signed Integer"));
auto* view_uint = menu->addAction(tr("Unsigned Integer"));
// i18n: A floating point number
auto* view_float = menu->addAction(tr("Float"));
// i18n: A double precision floating point number
auto* view_double = menu->addAction(tr("Double"));

for (auto* action : {view_hex, view_int, view_uint, view_float, view_double})
{
action->setCheckable(true);
action->setVisible(false);
action->setActionGroup(group);
}

switch (display)
{
case RegisterDisplay::Hex:
view_hex->setChecked(true);
break;
case RegisterDisplay::SInt32:
view_int->setChecked(true);
break;
case RegisterDisplay::UInt32:
view_uint->setChecked(true);
break;
case RegisterDisplay::Float:
view_float->setChecked(true);
break;
case RegisterDisplay::Double:
view_double->setChecked(true);
break;
}

switch (type)
{
case RegisterType::gpr:
view_hex->setVisible(true);
view_int->setVisible(true);
view_uint->setVisible(true);
view_float->setVisible(true);
break;
case RegisterType::fpr:
view_hex->setVisible(true);
view_double->setVisible(true);
break;
default:
break;
}

connect(view_hex, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::Hex);
m_updating = false;
});

connect(view_int, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::SInt32);
m_updating = false;
});

connect(view_uint, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::UInt32);
m_updating = false;
});

connect(view_float, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::Float);
m_updating = false;
});

connect(view_double, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::Double);
m_updating = false;
});

menu->addSeparator();
case RegisterDisplay::Hex:
view_hex->setChecked(true);
break;
case RegisterDisplay::SInt32:
view_int->setChecked(true);
break;
case RegisterDisplay::UInt32:
view_uint->setChecked(true);
break;
case RegisterDisplay::Float:
view_float->setChecked(true);
break;
case RegisterDisplay::Double:
view_double->setChecked(true);
break;
}

switch (type)
{
case RegisterType::gpr:
view_hex->setVisible(true);
view_int->setVisible(true);
view_uint->setVisible(true);
view_float->setVisible(true);
break;
case RegisterType::fpr:
view_hex->setVisible(true);
view_double->setVisible(true);
break;
default:
break;
}

connect(view_hex, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::Hex);
m_updating = false;
});

connect(view_int, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::SInt32);
m_updating = false;
});

connect(view_uint, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::UInt32);
m_updating = false;
});

connect(view_float, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::Float);
m_updating = false;
});

connect(view_double, &QAction::triggered, [this, item] {
m_updating = true;
item->SetDisplay(RegisterDisplay::Double);
m_updating = false;
});

menu->addSeparator();
}

AddAction(menu, tr("Update"), this, [this] { emit RequestTableUpdate(); });
@@ -356,10 +353,12 @@ void RegisterWidget::AddRegister(int row, int column, RegisterType type, std::st

m_table->setItem(row, column, label);
m_table->setItem(row, column + 1, value);
m_table->item(row, column + 1)->setTextAlignment(Qt::AlignRight);
}
else
{
m_table->setItem(row, column, value);
m_table->item(row, column)->setTextAlignment(Qt::AlignRight);
}

connect(this, &RegisterWidget::UpdateTable, [value] { value->RefreshValue(); });
@@ -14,6 +14,7 @@
#include "Core/Debugger/PPCDebugInterface.h"
#include "Core/Host.h"
#include "Core/PowerPC/PowerPC.h"
#include "DolphinQt2/QtUtils/RunOnObject.h"
#include "DolphinQt2/Settings.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoConfig.h"
@@ -109,6 +110,10 @@ void Host_YieldToUI()

void Host_UpdateDisasmDialog()
{
RunOnObject(QApplication::instance(), [&] {
emit Host::GetInstance()->UpdateDisasmDialog();
return true;
});
}

void Host_UpdateProgressDialog(const char* caption, int position, int total)
@@ -33,6 +33,7 @@ class Host final : public QObject
void RequestStop();
void RequestRenderSize(int w, int h);
void UpdateProgressDialog(QString label, int position, int maximum);
void UpdateDisasmDialog();

private:
Host();
@@ -54,6 +54,7 @@
#include "DolphinQt2/Config/Mapping/MappingWindow.h"
#include "DolphinQt2/Config/SettingsWindow.h"
#include "DolphinQt2/Debugger/BreakpointWidget.h"
#include "DolphinQt2/Debugger/CodeViewWidget.h"
#include "DolphinQt2/Debugger/CodeWidget.h"
#include "DolphinQt2/Debugger/JITWidget.h"
#include "DolphinQt2/Debugger/MemoryWidget.h"
@@ -256,6 +257,10 @@ void MainWindow::CreateComponents()
&CodeWidget::Update);
connect(m_breakpoint_widget, &BreakpointWidget::BreakpointsChanged, m_memory_widget,
&MemoryWidget::Update);
connect(m_breakpoint_widget, &BreakpointWidget::SelectedBreakpoint, [this](u32 address) {
if (Core::GetState() == Core::State::Paused)
m_code_widget->SetAddress(address, CodeViewWidget::SetAddressUpdate::WithUpdate);
});

#if defined(HAVE_XRANDR) && HAVE_XRANDR
m_xrr_config = std::make_unique<X11Utils::XRRConfiguration>(
@@ -346,6 +351,12 @@ void MainWindow::ConnectMenuBar()
connect(m_game_list, &GameList::SelectionChanged, m_menu_bar, &MenuBar::SelectionChanged);
connect(this, &MainWindow::ReadOnlyModeChanged, m_menu_bar, &MenuBar::ReadOnlyModeChanged);
connect(this, &MainWindow::RecordingStatusChanged, m_menu_bar, &MenuBar::RecordingStatusChanged);

// Symbols
connect(m_menu_bar, &MenuBar::NotifySymbolsUpdated, [this] {
m_code_widget->UpdateSymbols();
m_code_widget->Update();
});
}

void MainWindow::ConnectHotkeys()
@@ -453,14 +464,14 @@ void MainWindow::ConnectStack()
setCentralWidget(m_stack);

setTabPosition(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea, QTabWidget::North);
addDockWidget(Qt::RightDockWidgetArea, m_log_widget);
addDockWidget(Qt::RightDockWidgetArea, m_log_config_widget);
addDockWidget(Qt::RightDockWidgetArea, m_code_widget);
addDockWidget(Qt::RightDockWidgetArea, m_register_widget);
addDockWidget(Qt::RightDockWidgetArea, m_watch_widget);
addDockWidget(Qt::RightDockWidgetArea, m_breakpoint_widget);
addDockWidget(Qt::RightDockWidgetArea, m_memory_widget);
addDockWidget(Qt::RightDockWidgetArea, m_jit_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_log_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_log_config_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_code_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_register_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_watch_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_breakpoint_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_memory_widget);
addDockWidget(Qt::LeftDockWidgetArea, m_jit_widget);

tabifyDockWidget(m_log_widget, m_log_config_widget);
tabifyDockWidget(m_log_widget, m_code_widget);
@@ -46,6 +46,7 @@
#include "DiscIO/WiiSaveBanner.h"

#include "DolphinQt2/AboutDialog.h"
#include "DolphinQt2/Host.h"
#include "DolphinQt2/QtUtils/ActionHelper.h"
#include "DolphinQt2/Settings.h"

@@ -65,6 +66,9 @@ MenuBar::MenuBar(QWidget* parent) : QMenuBar(parent)

connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
[=](Core::State state) { OnEmulationStateChanged(state); });
connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this,
[this] { OnEmulationStateChanged(Core::GetState()); });

OnEmulationStateChanged(Core::GetState());
connect(&Settings::Instance(), &Settings::DebugModeToggled, this, &MenuBar::OnDebugModeToggled);

@@ -1016,13 +1020,13 @@ void MenuBar::ClearSymbols()
return;

g_symbolDB.Clear();
Host_NotifyMapLoaded();
emit NotifySymbolsUpdated();
}

void MenuBar::GenerateSymbolsFromAddress()
{
PPCAnalyst::FindFunctions(0x80000000, 0x81800000, &g_symbolDB);
Host_NotifyMapLoaded();
emit NotifySymbolsUpdated();
}

void MenuBar::GenerateSymbolsFromSignatureDB()
@@ -1044,7 +1048,7 @@ void MenuBar::GenerateSymbolsFromSignatureDB()
tr("'%1' not found, no symbol names generated").arg(QString::fromStdString(TOTALDB)));
}

Host_NotifyMapLoaded();
emit NotifySymbolsUpdated();
}

void MenuBar::GenerateSymbolsFromRSO()
@@ -1063,7 +1067,7 @@ void MenuBar::GenerateSymbolsFromRSO()
if (rso_chain.Load(static_cast<u32>(address)))
{
rso_chain.Apply(&g_symbolDB);
Host_NotifyMapLoaded();
emit NotifySymbolsUpdated();
}
else
{
@@ -1097,7 +1101,7 @@ void MenuBar::LoadSymbolMap()
}

HLE::PatchFunctions();
Host_NotifyMapLoaded();
emit NotifySymbolsUpdated();
}

void MenuBar::SaveSymbolMap()
@@ -1119,7 +1123,7 @@ void MenuBar::LoadOtherSymbolMap()

g_symbolDB.LoadMap(file.toStdString());
HLE::PatchFunctions();
Host_NotifyMapLoaded();
emit NotifySymbolsUpdated();
}

void MenuBar::SaveSymbolMapAs()
@@ -102,6 +102,9 @@ class MenuBar final : public QMenuBar
void RecordingStatusChanged(bool recording);
void ReadOnlyModeChanged(bool read_only);

// Synbols
void NotifySymbolsUpdated();

private:
void OnEmulationStateChanged(Core::State state);

@@ -8,6 +8,7 @@
#include <QIcon>

#include "Core/Core.h"
#include "DolphinQt2/Host.h"
#include "DolphinQt2/QtUtils/ActionHelper.h"
#include "DolphinQt2/Resources.h"
#include "DolphinQt2/Settings.h"
@@ -33,6 +34,9 @@ ToolBar::ToolBar(QWidget* parent) : QToolBar(parent)
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
[this](Core::State state) { OnEmulationStateChanged(state); });

connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this,
[this] { OnEmulationStateChanged(Core::GetState()); });

connect(&Settings::Instance(), &Settings::DebugModeToggled, this, &ToolBar::OnDebugModeToggled);

connect(&Settings::Instance(), &Settings::ToolBarVisibilityChanged, this, &ToolBar::setVisible);
@@ -56,6 +60,13 @@ void ToolBar::OnEmulationStateChanged(Core::State state)
m_play_action->setVisible(!playing);
m_pause_action->setEnabled(playing);
m_pause_action->setVisible(playing);

bool paused = Core::GetState() == Core::State::Paused;
m_step_action->setEnabled(paused);
m_step_over_action->setEnabled(paused);
m_step_out_action->setEnabled(paused);
m_skip_action->setEnabled(paused);
m_set_pc_action->setEnabled(paused);
}

void ToolBar::closeEvent(QCloseEvent*)
@@ -71,6 +82,13 @@ void ToolBar::OnDebugModeToggled(bool enabled)
m_skip_action->setVisible(enabled);
m_show_pc_action->setVisible(enabled);
m_set_pc_action->setVisible(enabled);

bool paused = Core::GetState() == Core::State::Paused;
m_step_action->setEnabled(paused);
m_step_over_action->setEnabled(paused);
m_step_out_action->setEnabled(paused);
m_skip_action->setEnabled(paused);
m_set_pc_action->setEnabled(paused);
}

void ToolBar::MakeActions()