From 1915e580641d923fe2135fdc77f138954e83cd41 Mon Sep 17 00:00:00 2001 From: Paulo Vitor F G Pivotto Date: Wed, 17 Jun 2026 17:14:49 -0300 Subject: [PATCH 1/2] Add debugger color configuration options --- bsnes/ui-qt/config.cpp | 15 +++++ bsnes/ui-qt/config.hpp | 21 +++++++ bsnes/ui-qt/debugger/debugger.cpp | 60 +++++++++++++++---- .../disassembler/disassemblerview.cpp | 24 ++++++-- .../debugger/tools/qhexedit2/qhexedit.cpp | 27 +++++++-- 5 files changed, 128 insertions(+), 19 deletions(-) diff --git a/bsnes/ui-qt/config.cpp b/bsnes/ui-qt/config.cpp index 9ab2d376..c8d43698 100644 --- a/bsnes/ui-qt/config.cpp +++ b/bsnes/ui-qt/config.cpp @@ -137,6 +137,21 @@ Configuration::Configuration() { attach(debugger.saveSymbols = true, "debugger.saveSymbols"); attach(debugger.showHClocks = false, "debugger.showHClocks"); + attach(debugger.disassembler.opColor = "#000088", "debugger.disassembler.opColor"); + attach(debugger.disassembler.paramImmediateColor = "#008800", "debugger.disassembler.paramImmediatColor"); + attach(debugger.disassembler.paramAddressColor = "#880000", "debugger.disassembler.paramAddressColor"); + attach(debugger.disassembler.paramSymbolColor = "#ff0000", "debugger.disassembler.paramSymbolColor"); + + attach(debugger.console.breakpointColor = "#a000a0", "debugger.console.breakpointColor"); + attach(debugger.console.cpuStepColor = "#0000a0", "debugger.console.cpuStepColor"); + attach(debugger.console.smpStepColor = "#a00000", "debugger.console.smpStepColor"); + attach(debugger.console.coprocessorStepColor = "#008000", "debugger.console.coprocessorStepColor"); + + attach(debugger.hexEditor.readUsageColor = "#0000e0", "debugger.hexEditor.readUsageColor"); + attach(debugger.hexEditor.writeUsageColor = "#0000e0", "debugger.hexEditor.writeUsageColor"); + attach(debugger.hexEditor.execUsageColor = "#e00000", "debugger.hexEditor.execUsageColor"); + attach(debugger.hexEditor.rweUsageColor = "#e000e0", "debugger.hexEditor.rweUsageColor"); + attach(geometry.mainWindow = "", "geometry.mainWindow"); attach(geometry.loaderWindow = "", "geometry.loaderWindow"); attach(geometry.stateSelectWindow = "", "geometry.stateSelectWindow"); diff --git a/bsnes/ui-qt/config.hpp b/bsnes/ui-qt/config.hpp index 946fe090..c3dc2632 100644 --- a/bsnes/ui-qt/config.hpp +++ b/bsnes/ui-qt/config.hpp @@ -83,6 +83,27 @@ class Configuration : public configuration { bool loadDefaultSymbols; bool saveSymbols; bool showHClocks; + + struct Disassembler { + string opColor; + string paramImmediateColor; + string paramAddressColor; + string paramSymbolColor; + } disassembler; + + struct Console { + string breakpointColor; + string cpuStepColor; + string smpStepColor; + string coprocessorStepColor; + } console; + + struct HexEditor { + string readUsageColor; + string writeUsageColor; + string execUsageColor; + string rweUsageColor; + } hexEditor; } debugger; struct Geometry { diff --git a/bsnes/ui-qt/debugger/debugger.cpp b/bsnes/ui-qt/debugger/debugger.cpp index b167006e..66c59f70 100644 --- a/bsnes/ui-qt/debugger/debugger.cpp +++ b/bsnes/ui-qt/debugger/debugger.cpp @@ -588,7 +588,11 @@ void Debugger::event() { SNES::cpu.disassemble_opcode(t, SNES::cpu.opcode_pc, config().debugger.showHClocks); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.breakpointColor()); + if (!color.isValid()) { + color = QColor("#a000a0"); + } + echo(string() << "" << s << "
"); debugCPU->refresh(SNES::cpu.opcode_pc); registerEditCPU->setEnabled(true); editTabs->setCurrentIndex(0); @@ -600,7 +604,11 @@ void Debugger::event() { SNES::sa1.disassemble_opcode(t, SNES::sa1.opcode_pc, config().debugger.showHClocks); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.breakpointColor()); + if (!color.isValid()) { + color = QColor("#a000a0"); + } + echo(string() << "" << s << "
"); debugSA1->refresh(SNES::sa1.opcode_pc); registerEditSA1->setEnabled(true); editTabs->setCurrentIndex(editTabs->indexOf(debugSA1)); @@ -613,7 +621,11 @@ void Debugger::event() { SNES::smp.disassemble_opcode(t, SNES::smp.opcode_pc); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.breakpointColor()); + if (!color.isValid()) { + color = QColor("#a000a0"); + } + echo(string() << "" << s << "
"); debugSMP->refresh(SNES::smp.opcode_pc); registerEditSMP->setEnabled(true); editTabs->setCurrentIndex(1); @@ -625,7 +637,11 @@ void Debugger::event() { SNES::superfx.disassemble_opcode(t, SNES::superfx.opcode_pc); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.breakpointColor()); + if (!color.isValid()) { + color = QColor("#a000a0"); + } + echo(string() << "" << s << "
"); debugSFX->refresh(SNES::superfx.opcode_pc); registerEditSFX->setEnabled(true); editTabs->setCurrentIndex(editTabs->indexOf(debugSFX)); @@ -637,7 +653,11 @@ void Debugger::event() { SNES::supergameboy.disassemble_opcode(t, SNES::supergameboy.opcode_pc); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.breakpointColor()); + if (!color.isValid()) { + color = QColor("#a000a0"); + } + echo(string() << "" << s << "
"); debugSGB->refresh(SNES::supergameboy.opcode_pc); registerEditSGB->setEnabled(true); editTabs->setCurrentIndex(editTabs->indexOf(debugSGB)); @@ -649,7 +669,11 @@ void Debugger::event() { SNES::cpu.disassemble_opcode(t, SNES::cpu.opcode_pc, config().debugger.showHClocks); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.cpuStepColor()); + if (!color.isValid()) { + color = QColor("#0000a0"); + } + echo(string() << "" << s << "
"); debugCPU->refresh(SNES::cpu.opcode_pc); registerEditCPU->setEnabled(true); } break; @@ -658,7 +682,11 @@ void Debugger::event() { SNES::smp.disassemble_opcode(t, SNES::smp.opcode_pc); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.smpStepColor()); + if (!color.isValid()) { + color = QColor("#a00000"); + } + echo(string() << "" << s << "
"); debugSMP->refresh(SNES::smp.opcode_pc); registerEditSMP->setEnabled(true); } break; @@ -667,7 +695,11 @@ void Debugger::event() { SNES::sa1.disassemble_opcode(t, SNES::sa1.opcode_pc, config().debugger.showHClocks); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.coprocessorStepColor()); + if (!color.isValid()) { + color = QColor("#008000"); + } + echo(string() << "" << s << "
"); debugSA1->refresh(SNES::sa1.opcode_pc); registerEditSA1->setEnabled(true); } break; @@ -676,7 +708,11 @@ void Debugger::event() { SNES::superfx.disassemble_opcode(t, SNES::superfx.opcode_pc, true); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.coprocessorStepColor()); + if (!color.isValid()) { + color = QColor("#008000"); + } + echo(string() << "" << s << "
"); debugSFX->refresh(SNES::superfx.opcode_pc); registerEditSFX->setEnabled(true); } break; @@ -685,7 +721,11 @@ void Debugger::event() { SNES::supergameboy.disassemble_opcode(t, SNES::supergameboy.opcode_pc); string s = t; s.replace(" ", " "); - echo(string() << "" << s << "
"); + QColor color = QColor(config().debugger.console.coprocessorStepColor()); + if (!color.isValid()) { + color = QColor("#008000"); + } + echo(string() << "" << s << "
"); debugSGB->refresh(SNES::supergameboy.opcode_pc); registerEditSGB->setEnabled(true); } break; diff --git a/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp b/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp index 28dd7abb..42e0e709 100644 --- a/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp +++ b/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp @@ -665,10 +665,26 @@ void DisassemblerView::paintOpcode(QPainter &painter, RenderableDisassemblerLine addressColor = Qt::gray; textColor = viewport()->palette().color(QPalette::WindowText); - opColor = QColor(0x00, 0x00, 0x88, 0xff); - paramImmediateColor = QColor(0x00, 0x88, 0x00, 0xff); - paramAddressColor = QColor(0x88, 0x00, 0x00, 0xff); - paramSymbolColor = QColor(0xFF, 0x00, 0x00, 0xff); + + opColor = QColor(config().debugger.disassembler.opColor()); + if (!opColor.isValid()) { + opColor = QColor(0x00, 0x00, 0x88, 0xff); + } + + paramImmediateColor = QColor(config().debugger.disassembler.paramImmediateColor()); + if (!paramImmediateColor.isValid()) { + paramImmediateColor = QColor(0x00, 0x88, 0x00, 0xff); + } + + paramAddressColor = QColor(config().debugger.disassembler.paramAddressColor()); + if (!paramAddressColor.isValid()) { + paramAddressColor = QColor(0x88, 0x00, 0x00, 0xff); + } + + paramSymbolColor = QColor(config().debugger.disassembler.paramSymbolColor()); + if (!paramSymbolColor.isValid()) { + paramSymbolColor = QColor(0xFF, 0x00, 0x00, 0xff); + } } if (breakpointEditor->indexOfBreakpointExec(line.line.address, processor->getBreakpointBusName()) >= 0) { diff --git a/bsnes/ui-qt/debugger/tools/qhexedit2/qhexedit.cpp b/bsnes/ui-qt/debugger/tools/qhexedit2/qhexedit.cpp index 2d2a87ab..7b52d4be 100644 --- a/bsnes/ui-qt/debugger/tools/qhexedit2/qhexedit.cpp +++ b/bsnes/ui-qt/debugger/tools/qhexedit2/qhexedit.cpp @@ -721,11 +721,28 @@ void QHexEdit::paintEvent(QPaintEvent *event) // paint hex and ascii area QPen colStandard = QPen(viewport()->palette().color(QPalette::WindowText)); - // TODO: make these configurable - QPen colUsageRead = QPen(QColor(0, 0, 224)); - QPen colUsageWrite = QPen(QColor(0, 0, 224)); - QPen colUsageExec = QPen(QColor(224, 0, 0)); - QPen colUsageRWExec = QPen(QColor(224, 0, 224)); + + QColor readUsageColor = QColor(config().debugger.hexEditor.readUsageColor()); + if (! readUsageColor.isValid()) { + readUsageColor = QColor(0, 224, 128); + } + QColor writeUsageColor = QColor(config().debugger.hexEditor.writeUsageColor()); + if (! writeUsageColor.isValid()) { + writeUsageColor = QColor(0, 128, 224); + } + QColor execUsageColor = QColor(config().debugger.hexEditor.execUsageColor()); + if (! execUsageColor.isValid()) { + execUsageColor = QColor(224, 0, 0); + } + QColor rweUsageColor = QColor(config().debugger.hexEditor.rweUsageColor()); + if (! rweUsageColor.isValid()) { + rweUsageColor = QColor(224, 0, 224); + } + + QPen colUsageRead = QPen(readUsageColor); + QPen colUsageWrite = QPen(writeUsageColor); + QPen colUsageExec = QPen(execUsageColor); + QPen colUsageRWExec = QPen(rweUsageColor); painter.setBackgroundMode(Qt::TransparentMode); From 986f8a6bcfc90d96b9be00cd786b905771903411 Mon Sep 17 00:00:00 2001 From: Paulo Vitor F G Pivotto Date: Wed, 17 Jun 2026 22:25:15 -0300 Subject: [PATCH 2/2] Add debugger color edit dialog --- bsnes/ui-qt/config.cpp | 1 + bsnes/ui-qt/config.hpp | 1 + bsnes/ui-qt/debugger/debugger.cpp | 24 +++ bsnes/ui-qt/debugger/debugger.moc.hpp | 7 +- .../disassembler/disassemblerview.cpp | 37 ++-- .../colorpickerbutton/colorpickerbutton.cpp | 40 ++++ .../colorpickerbutton.moc.hpp | 23 +++ bsnes/ui-qt/debugger/tools/debuggercolors.cpp | 180 ++++++++++++++++++ .../debugger/tools/debuggercolors.moc.hpp | 61 ++++++ bsnes/ui-qt/ui-base.hpp | 1 + 10 files changed, 355 insertions(+), 20 deletions(-) create mode 100644 bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.cpp create mode 100644 bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.moc.hpp create mode 100644 bsnes/ui-qt/debugger/tools/debuggercolors.cpp create mode 100644 bsnes/ui-qt/debugger/tools/debuggercolors.moc.hpp diff --git a/bsnes/ui-qt/config.cpp b/bsnes/ui-qt/config.cpp index c8d43698..e6434d06 100644 --- a/bsnes/ui-qt/config.cpp +++ b/bsnes/ui-qt/config.cpp @@ -169,6 +169,7 @@ Configuration::Configuration() { attach(geometry.breakpointEditor = "", "geometry.breakpointEditor"); attach(geometry.memoryEditor = "", "geometry.memoryEditor"); attach(geometry.propertiesViewer = "", "geometry.propertiesViewer"); + attach(geometry.debuggerColors = "", "geometry.debuggerColors"); attach(geometry.layerToggle = "", "geometry.layerToggle"); attach(geometry.tileViewer = "", "geometry.tileViewer"); attach(geometry.tilemapViewer = "", "geometry.tilemapViewer"); diff --git a/bsnes/ui-qt/config.hpp b/bsnes/ui-qt/config.hpp index c3dc2632..28c25235 100644 --- a/bsnes/ui-qt/config.hpp +++ b/bsnes/ui-qt/config.hpp @@ -124,6 +124,7 @@ class Configuration : public configuration { string breakpointEditor; string memoryEditor; string propertiesViewer; + string debuggerColors; string layerToggle; string tileViewer; string tilemapViewer; diff --git a/bsnes/ui-qt/debugger/debugger.cpp b/bsnes/ui-qt/debugger/debugger.cpp index 66c59f70..ba253ae9 100644 --- a/bsnes/ui-qt/debugger/debugger.cpp +++ b/bsnes/ui-qt/debugger/debugger.cpp @@ -24,6 +24,7 @@ Debugger *debugger; #include "debuggerview.cpp" #include "tools/breakpoint.cpp" +#include "tools/debuggercolors.cpp" #include "tools/memory.cpp" #include "tools/properties.cpp" @@ -86,6 +87,8 @@ Debugger::Debugger() { menu_misc_showHClocks->setCheckable(true); menu_misc_showHClocks->setChecked(config().debugger.showHClocks); + menu_misc_editColors = menu_misc->addAction("Edit c&olors ..."); + tracer = new Tracer; breakpointEditor = new BreakpointEditor; propertiesViewer = new PropertiesViewer; @@ -93,6 +96,7 @@ Debugger::Debugger() { tilemapViewer = new TilemapViewer; oamViewer = new OamViewer; cgramViewer = new CgramViewer; + debuggerColors = new DebuggerColorsWindow; registerEditCPU = new RegisterEditCPU(SNES::cpu); registerEditSMP = new RegisterEditSMP; @@ -226,6 +230,7 @@ Debugger::Debugger() { connect(menu_misc_loadDefaultSymbols, SIGNAL(triggered()), this, SLOT(synchronize())); connect(menu_misc_saveSymbols, SIGNAL(triggered()), this, SLOT(synchronize())); connect(menu_misc_showHClocks, SIGNAL(triggered()), this, SLOT(synchronize())); + connect(menu_misc_editColors, SIGNAL(triggered()), debuggerColors, SLOT(show())); connect(runBreak->defaultAction(), SIGNAL(triggered()), this, SLOT(toggleRunStatus())); @@ -250,6 +255,9 @@ Debugger::Debugger() { connect(debugSGB, SIGNAL(traceStateChanged(int)), tracer, SLOT(setSgbTraceState(int))); connect(traceMask->defaultAction(), SIGNAL(toggled(bool)), tracer, SLOT(setTraceMaskState(bool))); + connect(debuggerColors, SIGNAL(disassemblerColorChanged()), this, SLOT(refreshDebuggerViews())); + connect(debuggerColors, SIGNAL(hexEditorColorChanged()), this, SLOT(refreshMemoryEditors())); + frameCounter = 0; synchronize(); resize(855, 745); @@ -778,4 +786,20 @@ void Debugger::autoUpdate() { } } +void Debugger::refreshDebuggerViews() { + registerEditCPU->setEnabled(false); + registerEditSMP->setEnabled(false); + debugCPU->refresh(SNES::cpu.opcode_pc); + debugSMP->refresh(SNES::smp.opcode_pc); + registerEditCPU->setEnabled(true); + registerEditSMP->setEnabled(true); +} + +void Debugger::refreshMemoryEditors() { + QVectorIterator i(memoryEditors); + while (i.hasNext()) { + i.next()->refresh(); + } +} + #endif diff --git a/bsnes/ui-qt/debugger/debugger.moc.hpp b/bsnes/ui-qt/debugger/debugger.moc.hpp index cc2a37d4..1e2294d6 100644 --- a/bsnes/ui-qt/debugger/debugger.moc.hpp +++ b/bsnes/ui-qt/debugger/debugger.moc.hpp @@ -20,6 +20,7 @@ class Debugger : public Window { QAction *menu_misc_saveSymbols; QAction *menu_misc_showHClocks; QAction *menu_misc_options; + QAction *menu_misc_editColors; QVBoxLayout *layout; QSplitter *consoleLayout; @@ -61,7 +62,7 @@ public slots: void clear(); void synchronize(); void frameTick(); - + void toggleRunStatus(); void stepAction(); void stepOverAction(); @@ -71,7 +72,9 @@ public slots: void stepToNMIAction(); void stepToIRQAction(); void createMemoryEditor(); - + void refreshDebuggerViews(); + void refreshMemoryEditors(); + protected: void closeEvent(QCloseEvent *event); diff --git a/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp b/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp index 42e0e709..341e9089 100644 --- a/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp +++ b/bsnes/ui-qt/debugger/disassembler/disassemblerview.cpp @@ -50,7 +50,7 @@ void DisassemblerView::setFont(const QFont &font) { // ------------------------------------------------------------------------ void DisassemblerView::setAddressWidth(uint32_t width) { addressWidth = width; - + // adjust text dimensions setFont(font()); } @@ -164,7 +164,7 @@ void DisassemblerView::updateVisibleLines() { } bottomLineAddress = address; - + if (address == currentLineAddress) { stopped = true; // no next instruction found } @@ -306,7 +306,7 @@ void DisassemblerView::mousePressEvent(QMouseEvent * event) { // Calculate the visible row from the mouse position. int row = (event->y() - lineOffset + charHeight) / charHeight; - if (row >= 0 && row < (int)lines.size()) { + if (row >= 0 && row < (int)lines.size()) { // Make sure this line isn’t empty before selecting. if (!lines[row].line.isEmpty()) { uint32_t addr = lines[row].line.address; @@ -421,13 +421,13 @@ void DisassemblerView::copyInstructions() { // If no valid selection exists, do nothing. if (selectionStartAddress == INVALID_ADDRESS || selectionEndAddress == INVALID_ADDRESS) return; - + // Determine the lower and upper bounds from the two selected addresses. uint32_t lower = qMin(selectionStartAddress, selectionEndAddress); uint32_t upper = qMax(selectionStartAddress, selectionEndAddress); - + QString copiedText; - + // Iterate over the current disassembled lines. for (int i = 0; i < (int)lines.size(); i++) { const DisassemblerLine &line = lines[i].line; @@ -437,15 +437,15 @@ void DisassemblerView::copyInstructions() { // Print the instruction address (padded in hexadecimal). lineStr += QString("%1").arg(line.address, addressWidth, 16, QChar('0')); lineStr += "\t"; // tab separator - + // Convert the nall::string opcode text into a QString. // (Assuming nall::string overloads operator const char*()) QString qLineText = QString::fromUtf8((const char *)line.text); lineStr += qLineText; - + QString paramsStr; QString directComment; - + // Convert the nall::string parameter format into a QString similarly. QString qParamFormat = QString::fromUtf8((const char *)line.paramFormat); if (!qParamFormat.isEmpty()) { @@ -522,18 +522,18 @@ void DisassemblerView::copyInstructions() { if (left < textLength) paramsStr += qParamFormat.mid(left); } - + // Append parameters and the direct comment (if any) separated by tabs. if (!paramsStr.isEmpty()) lineStr += "\t" + paramsStr; if (!directComment.isEmpty()) lineStr += "\t" + directComment; - + // Append the completed line and a newline. copiedText += lineStr + "\n"; } } - + // Place the final copied text into the clipboard. QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(copiedText); @@ -665,12 +665,12 @@ void DisassemblerView::paintOpcode(QPainter &painter, RenderableDisassemblerLine addressColor = Qt::gray; textColor = viewport()->palette().color(QPalette::WindowText); - + opColor = QColor(config().debugger.disassembler.opColor()); if (!opColor.isValid()) { opColor = QColor(0x00, 0x00, 0x88, 0xff); } - + paramImmediateColor = QColor(config().debugger.disassembler.paramImmediateColor()); if (!paramImmediateColor.isValid()) { paramImmediateColor = QColor(0x00, 0x88, 0x00, 0xff); @@ -741,8 +741,9 @@ void DisassemblerView::paintOpcode(QPainter &painter, RenderableDisassemblerLine path.lineTo(ar, t + hw); path.lineTo(al, t + w + ap); - painter.setPen(Qt::black); - painter.setBrush(Qt::black); + textColor = viewport()->palette().color(QPalette::WindowText); + painter.setPen(textColor); + painter.setBrush(textColor); painter.drawEllipse(QPoint(l + hw, b - hw), hw, hw); painter.drawEllipse(QPoint(l + hw, t + hw), hw, hw); painter.drawRect(l, t + hw, w, b - t - w); @@ -861,7 +862,7 @@ int DisassemblerView::renderValue(QPainter &painter, int x, int y, uint8_t type, case 'D': text = QString("%1").arg((int32_t)value, size, 10, QChar('0')); break; - + case 'U': text = QString("%1").arg(value, size, 10, QChar('0')); break; @@ -886,7 +887,7 @@ void DisassemblerView::paintHeader(QPainter &painter) { painter.drawLine(columnPositions[i], 0, columnPositions[i], headerHeight); } - painter.setPen(Qt::black); + painter.setPen(viewport()->palette().color(QPalette::WindowText)); SET_CLIPPING(1); painter.drawText(columnPositions[1] + charPadding, headerHeight - charPadding, "Disassembly"); SET_CLIPPING(2); diff --git a/bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.cpp b/bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.cpp new file mode 100644 index 00000000..05e14794 --- /dev/null +++ b/bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.cpp @@ -0,0 +1,40 @@ +#include "colorpickerbutton.moc.hpp" +#include + +ColorPickerButton::ColorPickerButton(const QColor &defaultColor, QWidget *parent) + : QPushButton(parent), m_color(defaultColor) { + connect(this, &QPushButton::clicked, this, &ColorPickerButton::pickColor); + updateButtonStyle(); +} + +QColor ColorPickerButton::color() const { + return m_color; +} + +void ColorPickerButton::setColor(const QColor &color) { + if (color.isValid() && m_color != color) { + m_color = color; + + if (objectName().isEmpty()) { + setObjectName(QString("color-picker-%1").arg(reinterpret_cast(this))); + } + + updateButtonStyle(); + emit colorChanged(m_color); + } +} + +void ColorPickerButton::pickColor() { + QColor selectedColor = QColorDialog::getColor(m_color, this, "Select Color"); + if (selectedColor.isValid()) { + setColor(selectedColor); + } +} + +void ColorPickerButton::updateButtonStyle() { + QString style = QString( + "#%1 { background-color: %2; border: 1px solid #999; min-width: 40px; }" + ).arg(objectName(), m_color.name()); + + setStyleSheet(style); +} diff --git a/bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.moc.hpp b/bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.moc.hpp new file mode 100644 index 00000000..7e49d7b9 --- /dev/null +++ b/bsnes/ui-qt/debugger/tools/colorpickerbutton/colorpickerbutton.moc.hpp @@ -0,0 +1,23 @@ +#ifndef COLORPICKERBUTTON_H +#define COLORPICKERBUTTON_H + +class ColorPickerButton : public QPushButton { + Q_OBJECT + +public: + explicit ColorPickerButton(const QColor &defaultColor = Qt::white, QWidget *parent = nullptr); + QColor color() const; + void setColor(const QColor &color); + +signals: + void colorChanged(const QColor &color); + +private slots: + void pickColor(); + +private: + void updateButtonStyle(); + QColor m_color; +}; + +#endif // COLORPICKERBUTTON_H diff --git a/bsnes/ui-qt/debugger/tools/debuggercolors.cpp b/bsnes/ui-qt/debugger/tools/debuggercolors.cpp new file mode 100644 index 00000000..47940011 --- /dev/null +++ b/bsnes/ui-qt/debugger/tools/debuggercolors.cpp @@ -0,0 +1,180 @@ +#include "debuggercolors.moc" +#include "colorpickerbutton.moc" + +#include "colorpickerbutton/colorpickerbutton.cpp" + +DebuggerColorsWindow *debuggerColors; + +DebuggerColorsWindow::DebuggerColorsWindow() { + setObjectName("debugger-colors"); + setWindowTitle("Debugger Colors"); + setGeometryString(&config().geometry.debuggerColors); + setMinimumWidth(300); + application.windowList.append(this); + + layout = new QVBoxLayout; + layout->setMargin(Style::WindowMargin); + layout->setSpacing(Style::WidgetSpacing); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + disassemblerLabel = new QLabel("Disassembler"); + layout->addWidget(disassemblerLabel); + + disassemblerLayout = new QGridLayout; + layout->addLayout(disassemblerLayout); + + disassemblerOpLabel = new QLabel("Opcode:"); + disassemblerLayout->addWidget(disassemblerOpLabel, 0, 0); + disassemblerOpPicker = new ColorPickerButton; + disassemblerLayout->addWidget(disassemblerOpPicker, 0, 1); + + disassemblerParamImmediateLabel = new QLabel("Immediate parameter:"); + disassemblerLayout->addWidget(disassemblerParamImmediateLabel, 1, 0); + disassemblerParamImmediatePicker = new ColorPickerButton; + disassemblerLayout->addWidget(disassemblerParamImmediatePicker, 1, 1); + + disassemblerParamAddressLabel = new QLabel("Address parameter:"); + disassemblerLayout->addWidget(disassemblerParamAddressLabel, 2, 0); + disassemblerParamAddressPicker = new ColorPickerButton; + disassemblerLayout->addWidget(disassemblerParamAddressPicker, 2, 1); + + disassemblerParamSymbolLabel = new QLabel("Symbol parameter:"); + disassemblerLayout->addWidget(disassemblerParamSymbolLabel, 3, 0); + disassemblerParamSymbolPicker = new ColorPickerButton; + disassemblerLayout->addWidget(disassemblerParamSymbolPicker, 3, 1); + + consoleLabel = new QLabel("Console"); + layout->addWidget(consoleLabel); + + consoleLayout = new QGridLayout; + layout->addLayout(consoleLayout); + + consoleBreakpointLabel = new QLabel("Breakpoint:"); + consoleLayout->addWidget(consoleBreakpointLabel, 0, 0); + consoleBreakpointPicker = new ColorPickerButton; + consoleLayout->addWidget(consoleBreakpointPicker, 0, 1); + + consoleCpuStepLabel = new QLabel("CPU step:"); + consoleLayout->addWidget(consoleCpuStepLabel, 1, 0); + consoleCpuStepPicker = new ColorPickerButton; + consoleLayout->addWidget(consoleCpuStepPicker, 1, 1); + + consoleSmpStepLabel = new QLabel("SMP step:"); + consoleLayout->addWidget(consoleSmpStepLabel, 2, 0); + consoleSmpStepPicker = new ColorPickerButton; + consoleLayout->addWidget(consoleSmpStepPicker, 2, 1); + + consoleCoprocessorStepLabel = new QLabel("Coprocessor step:"); + consoleLayout->addWidget(consoleCoprocessorStepLabel, 3, 0); + consoleCoprocessorStepPicker = new ColorPickerButton; + consoleLayout->addWidget(consoleCoprocessorStepPicker, 3, 1); + + hexEditorLabel = new QLabel("Hex Editor"); + layout->addWidget(hexEditorLabel); + + hexEditorLayout = new QGridLayout; + layout->addLayout(hexEditorLayout); + + hexEditorReadUsageLabel = new QLabel("Read usage:"); + hexEditorLayout->addWidget(hexEditorReadUsageLabel, 0, 0); + hexEditorReadUsagePicker = new ColorPickerButton; + hexEditorLayout->addWidget(hexEditorReadUsagePicker, 0, 1); + + hexEditorWriteUsageLabel = new QLabel("Write usage:"); + hexEditorLayout->addWidget(hexEditorWriteUsageLabel, 1, 0); + hexEditorWriteUsagePicker = new ColorPickerButton; + hexEditorLayout->addWidget(hexEditorWriteUsagePicker, 1, 1); + + hexEditorExecUsageLabel = new QLabel("Exec usage:"); + hexEditorLayout->addWidget(hexEditorExecUsageLabel, 2, 0); + hexEditorExecUsagePicker = new ColorPickerButton; + hexEditorLayout->addWidget(hexEditorExecUsagePicker, 2, 1); + + hexEditorRWEUsageLabel = new QLabel("R/W/E usage:"); + hexEditorLayout->addWidget(hexEditorRWEUsageLabel, 3, 0); + hexEditorRWEUsagePicker = new ColorPickerButton; + hexEditorLayout->addWidget(hexEditorRWEUsagePicker, 3, 1); + + initializeUi(); + + connect(disassemblerOpPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(setDisassemblerOpColor(const QColor &))); + connect(disassemblerParamImmediatePicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(setDisassemblerParamImmediateColor(const QColor &))); + connect(disassemblerParamAddressPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(setDisassemblerParamAddressColor(const QColor &))); + connect(disassemblerParamSymbolPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(setDisassemblerParamSymbolColor(const QColor &))); + connect(hexEditorReadUsagePicker, SIGNAL(colorChanged(const QColor &)), this, SIGNAL(hexEditorColorChanged())); + connect(hexEditorWriteUsagePicker, SIGNAL(colorChanged(const QColor &)), this, SIGNAL(hexEditorColorChanged())); + connect(hexEditorExecUsagePicker, SIGNAL(colorChanged(const QColor &)), this, SIGNAL(hexEditorColorChanged())); + connect(hexEditorRWEUsagePicker, SIGNAL(colorChanged(const QColor &)), this, SIGNAL(hexEditorColorChanged())); +} + +void DebuggerColorsWindow::initializeUi() { + disassemblerOpPicker->setColor(config().debugger.disassembler.opColor()); + disassemblerParamImmediatePicker->setColor(config().debugger.disassembler.paramImmediateColor()); + disassemblerParamAddressPicker->setColor(config().debugger.disassembler.paramAddressColor()); + disassemblerParamSymbolPicker->setColor(config().debugger.disassembler.paramSymbolColor()); + consoleBreakpointPicker->setColor(config().debugger.console.breakpointColor()); + consoleCpuStepPicker->setColor(config().debugger.console.cpuStepColor()); + consoleSmpStepPicker->setColor(config().debugger.console.smpStepColor()); + consoleCoprocessorStepPicker->setColor(config().debugger.console.coprocessorStepColor()); + hexEditorReadUsagePicker->setColor(config().debugger.hexEditor.readUsageColor()); + hexEditorWriteUsagePicker->setColor(config().debugger.hexEditor.writeUsageColor()); + hexEditorExecUsagePicker->setColor(config().debugger.hexEditor.execUsageColor()); + hexEditorRWEUsagePicker->setColor(config().debugger.hexEditor.rweUsageColor()); +} + +void DebuggerColorsWindow::setDisassemblerOpColor(const QColor &color) { + config().debugger.disassembler.opColor = color.name(); + emit disassemblerColorChanged(); +} + +void DebuggerColorsWindow::setDisassemblerParamImmediateColor(const QColor &color) { + config().debugger.disassembler.paramImmediateColor = color.name(); + emit disassemblerColorChanged(); +} + +void DebuggerColorsWindow::setDisassemblerParamAddressColor(const QColor &color) { + config().debugger.disassembler.paramAddressColor = color.name(); + emit disassemblerColorChanged(); +} + +void DebuggerColorsWindow::setDisassemblerParamSymbolColor(const QColor &color) { + config().debugger.disassembler.paramSymbolColor = color.name(); + emit disassemblerColorChanged(); +} + +void DebuggerColorsWindow::setConsoleBreakpointColor(const QColor &color) { + config().debugger.console.breakpointColor = color.name(); +} + +void DebuggerColorsWindow::setConsoleCpuStepColor(const QColor &color) { + config().debugger.console.cpuStepColor = color.name(); +} + +void DebuggerColorsWindow::setConsoleSmpStepColor(const QColor &color) { + config().debugger.console.smpStepColor = color.name(); +} + +void DebuggerColorsWindow::setConsoleCoprocessorStepColor(const QColor &color) { + config().debugger.console.coprocessorStepColor = color.name(); +} + +void DebuggerColorsWindow::setHexEditorReadUsageColor(const QColor &color) { + config().debugger.hexEditor.readUsageColor = color.name(); + emit hexEditorColorChanged(); +} + +void DebuggerColorsWindow::setHexEditorWriteUsageColor(const QColor &color) { + config().debugger.hexEditor.writeUsageColor = color.name(); + emit hexEditorColorChanged(); +} + +void DebuggerColorsWindow::setHexEditorExecUsageColor(const QColor &color) { + config().debugger.hexEditor.execUsageColor = color.name(); + emit hexEditorColorChanged(); +} + +void DebuggerColorsWindow::setHexEditorRWEUsageColor(const QColor &color) { + config().debugger.hexEditor.rweUsageColor = color.name(); + emit hexEditorColorChanged(); +} \ No newline at end of file diff --git a/bsnes/ui-qt/debugger/tools/debuggercolors.moc.hpp b/bsnes/ui-qt/debugger/tools/debuggercolors.moc.hpp new file mode 100644 index 00000000..32cbe3ad --- /dev/null +++ b/bsnes/ui-qt/debugger/tools/debuggercolors.moc.hpp @@ -0,0 +1,61 @@ +#include "colorpickerbutton/colorpickerbutton.moc.hpp" + +class DebuggerColorsWindow : public Window { + Q_OBJECT + +public: + QVBoxLayout *layout; + QLabel *disassemblerLabel; + QGridLayout *disassemblerLayout; + QLabel *disassemblerOpLabel; + ColorPickerButton *disassemblerOpPicker; + QLabel *disassemblerParamImmediateLabel; + ColorPickerButton *disassemblerParamImmediatePicker; + QLabel *disassemblerParamAddressLabel; + ColorPickerButton *disassemblerParamAddressPicker; + QLabel *disassemblerParamSymbolLabel; + ColorPickerButton *disassemblerParamSymbolPicker; + QLabel *consoleLabel; + QGridLayout *consoleLayout; + QLabel *consoleBreakpointLabel; + ColorPickerButton *consoleBreakpointPicker; + QLabel *consoleCpuStepLabel; + ColorPickerButton *consoleCpuStepPicker; + QLabel *consoleSmpStepLabel; + ColorPickerButton *consoleSmpStepPicker; + QLabel *consoleCoprocessorStepLabel; + ColorPickerButton *consoleCoprocessorStepPicker; + QLabel *hexEditorLabel; + QGridLayout *hexEditorLayout; + QLabel *hexEditorReadUsageLabel; + ColorPickerButton *hexEditorReadUsagePicker; + QLabel *hexEditorWriteUsageLabel; + ColorPickerButton *hexEditorWriteUsagePicker; + QLabel *hexEditorExecUsageLabel; + ColorPickerButton *hexEditorExecUsagePicker; + QLabel *hexEditorRWEUsageLabel; + ColorPickerButton *hexEditorRWEUsagePicker; + + void initializeUi(); + DebuggerColorsWindow(); + +public slots: + void setDisassemblerOpColor(const QColor &color); + void setDisassemblerParamImmediateColor(const QColor &color); + void setDisassemblerParamAddressColor(const QColor &color); + void setDisassemblerParamSymbolColor(const QColor &color); + void setConsoleBreakpointColor(const QColor &color); + void setConsoleCpuStepColor(const QColor &color); + void setConsoleSmpStepColor(const QColor &color); + void setConsoleCoprocessorStepColor(const QColor &color); + void setHexEditorReadUsageColor(const QColor &color); + void setHexEditorWriteUsageColor(const QColor &color); + void setHexEditorExecUsageColor(const QColor &color); + void setHexEditorRWEUsageColor(const QColor &color); + +signals: + void disassemblerColorChanged(); + void hexEditorColorChanged(); +}; + +extern DebuggerColorsWindow *debuggerColors; \ No newline at end of file diff --git a/bsnes/ui-qt/ui-base.hpp b/bsnes/ui-qt/ui-base.hpp index eb49a24d..31f0ac88 100644 --- a/bsnes/ui-qt/ui-base.hpp +++ b/bsnes/ui-qt/ui-base.hpp @@ -55,6 +55,7 @@ using namespace ruby; #include "debugger/tools/breakpoint.moc.hpp" #include "debugger/tools/memory.moc.hpp" #include "debugger/tools/properties.moc.hpp" + #include "debugger/tools/debuggercolors.moc.hpp" #include "debugger/ppu/base-renderer.hpp" #include "debugger/ppu/tile-renderer.hpp"