DisassemblyWidget: Allow showing opcodes & some key bind modification

This commit is contained in:
Ty Lamontagne 2024-02-21 18:51:10 -05:00 committed by refractionpcsx2
parent a272d99335
commit 78b6323272
2 changed files with 52 additions and 13 deletions

View File

@ -320,6 +320,13 @@ void DisassemblyWidget::contextRestoreFunction()
QMessageBox::warning(this, tr("Restore Function Error"), tr("Unable to stub selected address.")); QMessageBox::warning(this, tr("Restore Function Error"), tr("Unable to stub selected address."));
} }
} }
void DisassemblyWidget::contextShowOpcode()
{
m_showInstructionOpcode = !m_showInstructionOpcode;
this->repaint();
}
void DisassemblyWidget::SetCpu(DebugInterface* cpu) void DisassemblyWidget::SetCpu(DebugInterface* cpu)
{ {
m_cpu = cpu; m_cpu = cpu;
@ -406,11 +413,11 @@ void DisassemblyWidget::paintEvent(QPaintEvent* event)
s32 skippedBranches = 0; s32 skippedBranches = 0;
for (const auto& branchLine : branchLines) for (const auto& branchLine : branchLines)
{ {
if (branchCount == 5) if (branchCount == (m_showInstructionOpcode ? 3 : 5))
break; break;
const int winBottom = this->height(); const int winBottom = this->height();
const int x = this->width() - 10 - ((std::max(0, branchLine.laneIndex - skippedBranches)) * 10); const int x = this->width() - 10 - (branchCount * 10);
int top, bottom; int top, bottom;
// If the start is technically 'above' our address view // If the start is technically 'above' our address view
@ -621,6 +628,9 @@ void DisassemblyWidget::keyPressEvent(QKeyEvent* event)
case Qt::Key_G: case Qt::Key_G:
contextGoToAddress(); contextGoToAddress();
break; break;
case Qt::Key_J:
contextJumpToCursor();
break;
case Qt::Key_C: case Qt::Key_C:
contextCopyInstructionText(); contextCopyInstructionText();
break; break;
@ -637,6 +647,9 @@ void DisassemblyWidget::keyPressEvent(QKeyEvent* event)
case Qt::Key_Left: case Qt::Key_Left:
gotoAddress(m_cpu->getPC()); gotoAddress(m_cpu->getPC());
break; break;
case Qt::Key_O:
m_showInstructionOpcode = !m_showInstructionOpcode;
break;
} }
this->repaint(); this->repaint();
@ -654,7 +667,8 @@ void DisassemblyWidget::customMenuRequested(QPoint pos)
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextCopyAddress); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextCopyAddress);
contextMenu->addAction(action = new QAction(tr("Copy Instruction Hex"), this)); contextMenu->addAction(action = new QAction(tr("Copy Instruction Hex"), this));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextCopyInstructionHex); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextCopyInstructionHex);
contextMenu->addAction(action = new QAction(tr("Copy Instruction Text"), this)); contextMenu->addAction(action = new QAction(tr("&Copy Instruction Text"), this));
action->setShortcut(QKeySequence(Qt::Key_C));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextCopyInstructionText); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextCopyInstructionText);
if (m_selectedAddressStart == m_cpu->GetSymbolMap().GetFunctionStart(m_selectedAddressStart)) if (m_selectedAddressStart == m_cpu->GetSymbolMap().GetFunctionStart(m_selectedAddressStart))
{ {
@ -667,21 +681,25 @@ void DisassemblyWidget::customMenuRequested(QPoint pos)
contextMenu->addAction(action = new QAction(tr("Restore Instruction(s)"), this)); contextMenu->addAction(action = new QAction(tr("Restore Instruction(s)"), this));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextRestoreInstruction); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextRestoreInstruction);
} }
contextMenu->addAction(action = new QAction(tr("Assemble new Instruction(s)"), this)); contextMenu->addAction(action = new QAction(tr("Asse&mble new Instruction(s)"), this));
action->setShortcut(QKeySequence(Qt::Key_M));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextAssembleInstruction); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextAssembleInstruction);
contextMenu->addAction(action = new QAction(tr("NOP Instruction(s)"), this)); contextMenu->addAction(action = new QAction(tr("NOP Instruction(s)"), this));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextNoopInstruction); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextNoopInstruction);
contextMenu->addSeparator(); contextMenu->addSeparator();
contextMenu->addAction(action = new QAction(tr("Run to Cursor"), this)); contextMenu->addAction(action = new QAction(tr("Run to Cursor"), this));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextRunToCursor); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextRunToCursor);
contextMenu->addAction(action = new QAction(tr("Jump to Cursor"), this)); contextMenu->addAction(action = new QAction(tr("&Jump to Cursor"), this));
action->setShortcut(QKeySequence(Qt::Key_J));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextJumpToCursor); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextJumpToCursor);
contextMenu->addAction(action = new QAction(tr("Toggle Breakpoint"), this)); contextMenu->addAction(action = new QAction(tr("Toggle &Breakpoint"), this));
action->setShortcut(QKeySequence(Qt::Key_B));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextToggleBreakpoint); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextToggleBreakpoint);
contextMenu->addAction(action = new QAction(tr("Follow Branch"), this)); contextMenu->addAction(action = new QAction(tr("Follow Branch"), this));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextFollowBranch); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextFollowBranch);
contextMenu->addSeparator(); contextMenu->addSeparator();
contextMenu->addAction(action = new QAction(tr("Go to Address"), this)); contextMenu->addAction(action = new QAction(tr("&Go to Address"), this));
action->setShortcut(QKeySequence(Qt::Key_G));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextGoToAddress); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextGoToAddress);
contextMenu->addAction(action = new QAction(tr("Go to in Memory View"), this)); contextMenu->addAction(action = new QAction(tr("Go to in Memory View"), this));
connect(action, &QAction::triggered, this, [this]() { gotoInMemory(m_selectedAddressStart); }); connect(action, &QAction::triggered, this, [this]() { gotoInMemory(m_selectedAddressStart); });
@ -702,6 +720,14 @@ void DisassemblyWidget::customMenuRequested(QPoint pos)
contextMenu->addAction(action = new QAction(tr("Stub (NOP) Function"), this)); contextMenu->addAction(action = new QAction(tr("Stub (NOP) Function"), this));
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextStubFunction); connect(action, &QAction::triggered, this, &DisassemblyWidget::contextStubFunction);
} }
contextMenu->addSeparator();
contextMenu->addAction(action = new QAction(tr("Show &Opcode"), this));
action->setShortcut(QKeySequence(Qt::Key_O));
action->setCheckable(true);
action->setChecked(m_showInstructionOpcode);
connect(action, &QAction::triggered, this, &DisassemblyWidget::contextShowOpcode);
contextMenu->setAttribute(Qt::WA_DeleteOnClose); contextMenu->setAttribute(Qt::WA_DeleteOnClose);
contextMenu->popup(this->mapToGlobal(pos)); contextMenu->popup(this->mapToGlobal(pos));
} }
@ -720,10 +746,19 @@ inline QString DisassemblyWidget::DisassemblyStringFromAddress(u32 address, QFon
const bool isCurrentPC = m_cpu->getPC() == address; const bool isCurrentPC = m_cpu->getPC() == address;
const std::string addressSymbol = m_cpu->GetSymbolMap().GetLabelName(address); const std::string addressSymbol = m_cpu->GetSymbolMap().GetLabelName(address);
const u32 opcode = m_cpu->read32(address);
const auto demangler = demangler::CDemangler::createGcc(); const auto demangler = demangler::CDemangler::createGcc();
QString lineString(" %1 %2 %3 %4 %5"); QString lineString;
if (m_showInstructionOpcode)
{
lineString = QString(" %1 %2 %3 %4 %5 %6");
}
else
{
lineString = QString(" %1 %2 %3 %4 %5");
}
if (addressSymbol.empty()) // The address wont have symbol text if it's the start of a function for example if (addressSymbol.empty()) // The address wont have symbol text if it's the start of a function for example
lineString = lineString.arg(address, 8, 16, QChar('0')).toUpper(); lineString = lineString.arg(address, 8, 16, QChar('0')).toUpper();
@ -745,9 +780,12 @@ inline QString DisassemblyWidget::DisassemblyStringFromAddress(u32 address, QFon
symbolString = QString::fromStdString(addressSymbol); symbolString = QString::fromStdString(addressSymbol);
} }
lineString = lineString.arg(metric.elidedText(symbolString, Qt::ElideRight, (selected ? 32 : 8) * font.pointSize())); lineString = lineString.arg(metric.elidedText(symbolString, Qt::ElideRight, (selected ? 32.0f : 7.5f) * font.pointSize()));
} }
if (m_showInstructionOpcode)
lineString = lineString.arg(QtUtils::FilledQStringFromValue(opcode, 16));
lineString = lineString.leftJustified(4, ' ') // Address / symbol lineString = lineString.leftJustified(4, ' ') // Address / symbol
.arg(line.name.c_str()) .arg(line.name.c_str())
.arg(line.params.c_str()) // opcode + arguments .arg(line.params.c_str()) // opcode + arguments
@ -760,7 +798,7 @@ inline QString DisassemblyWidget::DisassemblyStringFromAddress(u32 address, QFon
QColor DisassemblyWidget::GetAddressFunctionColor(u32 address) QColor DisassemblyWidget::GetAddressFunctionColor(u32 address)
{ {
// This is an attempt to figure out if the current palette is dark or light // This is an attempt to figure out if the current palette is dark or light
// We calculate the luminescence of the alternateBase colour // We calculate the luminance of the alternateBase colour
// and swap between our darker and lighter function colours // and swap between our darker and lighter function colours
std::array<QColor, 6> colors; std::array<QColor, 6> colors;
@ -832,7 +870,7 @@ void DisassemblyWidget::gotoAddress(u32 address, bool should_set_focus)
m_selectedAddressEnd = destAddress; m_selectedAddressEnd = destAddress;
this->repaint(); this->repaint();
if(should_set_focus) if (should_set_focus)
this->setFocus(); this->setFocus();
} }

View File

@ -56,6 +56,7 @@ public slots:
void contextRemoveFunction(); void contextRemoveFunction();
void contextStubFunction(); void contextStubFunction();
void contextRestoreFunction(); void contextRestoreFunction();
void contextShowOpcode();
void gotoAddress(u32 address, bool should_set_focus = true); void gotoAddress(u32 address, bool should_set_focus = true);
@ -79,7 +80,7 @@ private:
std::map<u32, std::tuple<u32, u32>> m_stubbedFunctions; std::map<u32, std::tuple<u32, u32>> m_stubbedFunctions;
bool m_demangleFunctions = true; bool m_demangleFunctions = true;
bool m_showInstructionOpcode = true;
DisassemblyManager m_disassemblyManager; DisassemblyManager m_disassemblyManager;
inline QString DisassemblyStringFromAddress(u32 address, QFont font, u32 pc, bool selected); inline QString DisassemblyStringFromAddress(u32 address, QFont font, u32 pc, bool selected);