Skip to content
This repository was archived by the owner on Dec 6, 2025. It is now read-only.

Commit e2e1f27

Browse files
recurseanSternXD
authored andcommitted
Debugger: Add column titles to Disassembly view.
Added new column title row to the "Disassembly" view in the debugger. Title row is non-selectable (single/double/right clicking on row do nothing) and branch lines do not get drawn on the title row. Format of title row was based on similar, existing title row on the VU0f tab in the "Registers" view.
1 parent e8c7209 commit e2e1f27

File tree

2 files changed

+113
-33
lines changed

2 files changed

+113
-33
lines changed

pcsx2-qt/Debugger/DisassemblyWidget.cpp

Lines changed: 111 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -355,37 +355,48 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
355355
// Get the row height
356356
m_rowHeight = fm.height() + 2;
357357

358-
// Find the amount of visible rows
359-
m_visibleRows = h / m_rowHeight;
358+
// Find the amount of visible disassembly rows. Minus 1 to not count column title row.
359+
m_visibleRows = h / m_rowHeight - 1;
360360

361361
m_disassemblyManager.analyze(m_visibleStart, m_disassemblyManager.getNthNextAddress(m_visibleStart, m_visibleRows) - m_visibleStart);
362362

363-
// Draw the rows
363+
const u32 curPC = cpu().getPC(); // Get the PC here, because it'll change when we are drawing and make it seem like there are two PCs
364+
365+
// Format and draw title line on first row
366+
const QString titleLineString = GetDisassemblyTitleLine();
367+
const QColor titleLineColor = GetDisassemblyTitleLineColor();
368+
painter.fillRect(0, 0 * m_rowHeight, w, m_rowHeight, titleLineColor);
369+
painter.drawText(2, 0 * m_rowHeight, w, m_rowHeight, Qt::AlignLeft, titleLineString);
370+
371+
// Prepare to draw the disassembly rows
364372
bool inSelectionBlock = false;
365373
bool alternate = m_visibleStart % 8;
366374

367-
const u32 curPC = cpu().getPC(); // Get the PC here, because it'll change when we are drawing and make it seem like there are two PCs
368-
375+
// Draw visible disassembly rows
369376
for (u32 i = 0; i <= m_visibleRows; i++)
370377
{
378+
// Address of instruction being displayed on row
371379
const u32 rowAddress = (i * 4) + m_visibleStart;
372-
// Row backgrounds
373380

381+
// Row will be drawn at row index+1 to offset past title row
382+
const u32 rowIndex = (i + 1) * m_rowHeight;
383+
384+
// Row backgrounds
374385
if (inSelectionBlock || (m_selectedAddressStart <= rowAddress && rowAddress <= m_selectedAddressEnd))
375386
{
376-
painter.fillRect(0, i * m_rowHeight, w, m_rowHeight, this->palette().highlight());
387+
painter.fillRect(0, rowIndex, w, m_rowHeight, this->palette().highlight());
377388
inSelectionBlock = m_selectedAddressEnd != rowAddress;
378389
}
379390
else
380391
{
381-
painter.fillRect(0, i * m_rowHeight, w, m_rowHeight, alternate ? this->palette().base() : this->palette().alternateBase());
392+
painter.fillRect(0, rowIndex, w, m_rowHeight, alternate ? this->palette().base() : this->palette().alternateBase());
382393
}
383394

384395
// Row text
385396
painter.setPen(GetAddressFunctionColor(rowAddress));
386397
QString lineString = DisassemblyStringFromAddress(rowAddress, painter.font(), curPC, rowAddress == m_selectedAddressStart);
387398

388-
painter.drawText(2, i * m_rowHeight, w, m_rowHeight, Qt::AlignLeft, lineString);
399+
painter.drawText(2, rowIndex, w, m_rowHeight, Qt::AlignLeft, lineString);
389400

390401
// Breakpoint marker
391402
bool enabled;
@@ -394,11 +405,11 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
394405
if (enabled)
395406
{
396407
painter.setPen(Qt::green);
397-
painter.drawText(2, i * m_rowHeight, w, m_rowHeight, Qt::AlignLeft, "\u25A0");
408+
painter.drawText(2, rowIndex, w, m_rowHeight, Qt::AlignLeft, "\u25A0");
398409
}
399410
else
400411
{
401-
painter.drawText(2, i * m_rowHeight, w, m_rowHeight, Qt::AlignLeft, "\u2612");
412+
painter.drawText(2, rowIndex, w, m_rowHeight, Qt::AlignLeft, "\u2612");
402413
}
403414
}
404415
alternate = !alternate;
@@ -435,9 +446,10 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
435446
// Explaination
436447
// ((branchLine.first - m_visibleStart) -> Find the amount of bytes from the top of the view
437448
// / 4 -> Convert that into rowss in instructions
449+
// + 1 -> Offset 1 to account for column title row
438450
// * m_rowHeight -> convert that into rows in pixels
439451
// + (m_rowHeight / 2) -> Add half a row in pixels to center the arrow
440-
top = (((branchLine.first - m_visibleStart) / 4) * m_rowHeight) + (m_rowHeight / 2);
452+
top = (((branchLine.first - m_visibleStart) / 4 + 1) * m_rowHeight) + (m_rowHeight / 2);
441453
}
442454

443455
if (branchLine.second < m_visibleStart)
@@ -450,7 +462,7 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
450462
}
451463
else
452464
{
453-
bottom = (((branchLine.second - m_visibleStart) / 4) * m_rowHeight) + (m_rowHeight / 2);
465+
bottom = (((branchLine.second - m_visibleStart) / 4 + 1) * m_rowHeight) + (m_rowHeight / 2);
454466
}
455467

456468
branchCount++;
@@ -467,7 +479,8 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
467479
if (top < 0) // first is not visible, but second is
468480
{
469481
painter.drawLine(x - 2, bottom, x + 2, bottom);
470-
painter.drawLine(x + 2, bottom, x + 2, 0);
482+
// Draw to first visible disassembly row so branch line is not drawn on title line
483+
painter.drawLine(x + 2, bottom, x + 2, m_rowHeight);
471484

472485
if (branchLine.type == LINE_DOWN)
473486
{
@@ -515,40 +528,56 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
515528

516529
void DisassemblyWidget::mousePressEvent(QMouseEvent* event)
517530
{
518-
const u32 selectedAddress = (static_cast<int>(event->position().y()) / m_rowHeight * 4) + m_visibleStart;
519-
if (event->buttons() & Qt::LeftButton)
531+
// Calculate index of row that was clicked
532+
const u32 selectedRowIndex = static_cast<int>(event->position().y()) / m_rowHeight;
533+
534+
// Only process if a row other than the column title row was clicked
535+
if (selectedRowIndex > 0)
520536
{
521-
if (event->modifiers() & Qt::ShiftModifier)
537+
// Calculate address of selected row. Index minus one for title row.
538+
const u32 selectedAddress = ((selectedRowIndex - 1) * 4) + m_visibleStart;
539+
if (event->buttons() & Qt::LeftButton)
522540
{
523-
if (selectedAddress < m_selectedAddressStart)
541+
if (event->modifiers() & Qt::ShiftModifier)
524542
{
525-
m_selectedAddressStart = selectedAddress;
543+
if (selectedAddress < m_selectedAddressStart)
544+
{
545+
m_selectedAddressStart = selectedAddress;
546+
}
547+
else if (selectedAddress > m_visibleStart)
548+
{
549+
m_selectedAddressEnd = selectedAddress;
550+
}
526551
}
527-
else if (selectedAddress > m_visibleStart)
552+
else
528553
{
554+
m_selectedAddressStart = selectedAddress;
529555
m_selectedAddressEnd = selectedAddress;
530556
}
531557
}
532-
else
533-
{
534-
m_selectedAddressStart = selectedAddress;
535-
m_selectedAddressEnd = selectedAddress;
536-
}
537-
}
538-
else if (event->buttons() & Qt::RightButton)
539-
{
540-
if (m_selectedAddressStart == m_selectedAddressEnd)
558+
else if (event->buttons() & Qt::RightButton)
541559
{
542-
m_selectedAddressStart = selectedAddress;
543-
m_selectedAddressEnd = selectedAddress;
560+
if (m_selectedAddressStart == m_selectedAddressEnd)
561+
{
562+
m_selectedAddressStart = selectedAddress;
563+
m_selectedAddressEnd = selectedAddress;
564+
}
544565
}
566+
this->repaint();
545567
}
546-
this->repaint();
547568
}
548569

549570
void DisassemblyWidget::mouseDoubleClickEvent(QMouseEvent* event)
550571
{
551-
toggleBreakpoint((static_cast<int>(event->position().y()) / m_rowHeight * 4) + m_visibleStart);
572+
// Calculate index of row that was double clicked
573+
const u32 selectedRowIndex = static_cast<int>(event->position().y()) / m_rowHeight;
574+
575+
// Only process if a row other than the column title row was double clicked
576+
if (selectedRowIndex > 0)
577+
{
578+
// Calculate address of selected row. Index minus one for title row.
579+
toggleBreakpoint(((selectedRowIndex - 1) * 4) + m_visibleStart);
580+
}
552581
}
553582

554583
void DisassemblyWidget::wheelEvent(QWheelEvent* event)
@@ -641,6 +670,10 @@ void DisassemblyWidget::openContextMenu(QPoint pos)
641670
if (!cpu().isAlive())
642671
return;
643672

673+
// Dont open context menu when used on column title row
674+
if (pos.y() / m_rowHeight == 0)
675+
return;
676+
644677
QMenu* menu = new QMenu(this);
645678
menu->setAttribute(Qt::WA_DeleteOnClose);
646679

@@ -743,6 +776,51 @@ void DisassemblyWidget::openContextMenu(QPoint pos)
743776
menu->popup(this->mapToGlobal(pos));
744777
}
745778

779+
QString DisassemblyWidget::GetDisassemblyTitleLine()
780+
{
781+
// Disassembly column title line based on format created by DisassemblyStringFromAddress()
782+
QString title_line_string;
783+
784+
// Determine layout of disassembly row. Layout depends on user setting "Show Instruction Bytes".
785+
const bool show_instruction_bytes = m_showInstructionBytes && cpu().isAlive();
786+
if (show_instruction_bytes)
787+
{
788+
title_line_string = QCoreApplication::translate("DisassemblyWidgetColumnTitle", " %1 %2 %3 %4");
789+
}
790+
else
791+
{
792+
title_line_string = QCoreApplication::translate("DisassemblyWidgetColumnTitle", " %1 %2 %3");
793+
}
794+
795+
// First 2 chars in disassembly row is always for non-returning functions (NR)
796+
// Do not display column title for this field.
797+
title_line_string = title_line_string.arg(" ");
798+
799+
// Second column title is always address of instruction
800+
title_line_string = title_line_string.arg(QCoreApplication::translate("DisassemblyWidgetColumnTitle", "Location"));
801+
802+
// If user specified to "Show Instruction Bytes", third column is opcode + args
803+
if (show_instruction_bytes)
804+
{
805+
title_line_string = title_line_string.arg(QCoreApplication::translate("DisassemblyWidgetColumnTitle", "Bytes "));
806+
}
807+
808+
// Last column title is always disassembled instruction
809+
title_line_string = title_line_string.arg(QCoreApplication::translate("DisassemblyWidgetColumnTitle", "Instruction"));
810+
811+
return title_line_string;
812+
}
813+
814+
QColor DisassemblyWidget::GetDisassemblyTitleLineColor()
815+
{
816+
// Determine color of column title line. Based on QFusionStyle.
817+
QColor title_line_color = this->palette().button().color();
818+
const int title_line_color_val = qGray(title_line_color.rgb());
819+
title_line_color = title_line_color.lighter(100 + qMax(1, (180 - title_line_color_val) / 6));
820+
title_line_color.setHsv(title_line_color.hue(), title_line_color.saturation() * 0.75, title_line_color.value());
821+
return title_line_color.lighter(104);
822+
}
823+
746824
inline QString DisassemblyWidget::DisassemblyStringFromAddress(u32 address, QFont font, u32 pc, bool selected)
747825
{
748826
DisassemblyLineInfo line;

pcsx2-qt/Debugger/DisassemblyWidget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ public slots:
8080
bool m_goToProgramCounterOnPause = true;
8181
DisassemblyManager m_disassemblyManager;
8282

83+
QString GetDisassemblyTitleLine();
84+
QColor GetDisassemblyTitleLineColor();
8385
inline QString DisassemblyStringFromAddress(u32 address, QFont font, u32 pc, bool selected);
8486
QColor GetAddressFunctionColor(u32 address);
8587
enum class SelectionInfo

0 commit comments

Comments
 (0)